{"id":71852,"date":"2020-02-28T20:59:58","date_gmt":"2020-02-28T17:59:58","guid":{"rendered":"https:\/\/prohoster.info\/blog\/kak-my-rabotaem-nad-kachestvom-i-skorostyu-podbora-rekomendaczij"},"modified":"2020-03-03T16:14:08","modified_gmt":"2020-03-03T13:14:08","slug":"kak-my-rabotaem-nad-kachestvom-i-skorostyu-podbora-rekomendaczij","status":"publish","type":"post","link":"https:\/\/prohoster.info\/nl\/blog\/administrirovanie\/kak-my-rabotaem-nad-kachestvom-i-skorostyu-podbora-rekomendaczij","title":{"rendered":"Hoe wij werken aan de kwaliteit en snelheid van aanbevelingen","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Mijn naam is Pavel Parkhomenko, ik ben ML-ontwikkelaar. In dit artikel wil ik het hebben over de werking van de Yandex.Zen-service en technische verbeteringen delen die hebben geleid tot een verhoogde kwaliteit van de aanbevelingen. In deze post leer je hoe je binnen enkele milliseconden de meest relevante documenten voor de gebruiker kunt vinden uit miljoenen; hoe je een continue decompositie van een grote matrix (bestaande uit miljoenen kolommen en tientallen miljoenen rijen) kunt uitvoeren, zodat nieuwe documenten binnen enkele tientallen minuten hun vector krijgen; en hoe je de decompositie van de gebruiker-artikelmatrix kunt hergebruiken om een goede vectorrepresentatie voor video te verkrijgen.<\/p>\n<p><img decoding=\"async\" alt=\"Hoe wij werken aan de kwaliteit en snelheid van aanbevelingen\" src=\"\/wp-content\/uploads\/2020\/02\/d63caf9162ca3533548fdef9cd740c24.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex> <br \/>\nOnze aanbevelingsdatabase bevat miljoenen documenten in verschillende formaten: tekstartikelen, die op ons platform zijn gemaakt en van externe sites zijn genomen, video's, verhalen en korte berichten. De ontwikkeling van een dergelijke service gaat gepaard met een groot aantal technische uitdagingen. Hier zijn enkele daarvan:<\/p>\n<ul>\n<li>Computatietaken splitsen: voer alle zware bewerkingen offline uit en pas in real-time alleen snel de modellen toe om binnen 100-200 ms te reageren.<\/li>\n<li>Snel de acties van de gebruiker registreren. Hiervoor is het noodzakelijk dat alle gebeurtenissen onmiddellijk naar de aanbeveler worden verzonden en invloed hebben op de uitkomst van de modellen.<\/li>\n<li>De feed zo inrichten dat deze zich snel aanpast aan het gedrag van nieuwe gebruikers. Net aangekomen mensen in het systeem moeten het gevoel hebben dat hun feedback invloed heeft op de aanbevelingen.<\/li>\n<li>Snel begrijpen wie een nieuw artikel aan te bevelen.<\/li>\n<li>Snel reageren op de constante toevoer van nieuwe content. Tienduizenden artikelen verschijnen elke dag, en velen daarvan hebben een beperkte levensduur (bijvoorbeeld nieuws). Dit onderscheidt ze van films, muziek en andere content die lang meegaat en duur is om te maken.<\/li>\n<li>Kennis van het ene domein naar het andere overdragen. Als er getrainde modellen voor tekstartikelen in het aanbevelingssysteem zijn en we video toevoegen, kunnen bestaande modellen worden hergebruikt om de ranking van nieuwe content te verbeteren.<\/li>\n<\/ul>\n<p>\nIk zal uitleggen hoe we deze uitdagingen hebben aangepakt.<\/p>\n<h2>Selectie van kandidaten<\/h2>\n<p>\n<b>Hoe je in enkele milliseconden het aantal onderzochte documenten duizenden keren kunt verminderen, zonder de kwaliteit van de ranking praktisch te verslechteren?<\/b><\/p>\n<p>Stel, we hebben veel ML-modellen getraind, hebben daaruit kenmerken gegenereerd en hebben nog een model getraind dat documenten voor de gebruiker rangschikt. Alles zou goed zijn, maar je kunt niet zomaar alle kenmerken voor alle documenten in real-time berekenen als die documenten miljoenen zijn en de aanbevelingen binnen 100-200 ms moeten worden gedaan. De uitdaging is om een subset uit miljoenen te kiezen die voor de gebruiker gerangschikt zal worden. Deze fase wordt meestal de kandidaatselectie genoemd. Er zijn een paar eisen waaraan deze moet voldoen. Ten eerste moet de selectie heel snel plaatsvinden, zodat er zoveel mogelijk tijd overblijft voor de daadwerkelijke ranking. Ten tweede, door het aantal documenten voor rangschikking sterk te verkleinen, moeten we de relevante documenten voor de gebruiker zo volledig mogelijk behouden.<\/p>\n<p>Ons principe voor kandidaatselectie is ge\u00ebvolueerd en op dit moment zijn we aangekomen bij een meertrapschema:<\/p>\n<p><img decoding=\"async\" alt=\"Hoe wij werken aan de kwaliteit en snelheid van aanbevelingen\" src=\"\/wp-content\/uploads\/2020\/02\/ed9657ed1febe871f36dc7cf7e585963.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nEerst worden alle documenten in groepen verdeeld en vanuit elke groep worden de populairste documenten geselecteerd. Groepen kunnen websites, onderwerpen of clusters zijn. Voor elke gebruiker worden op basis van zijn geschiedenis de meest relevante groepen geselecteerd en uit deze groepen worden de beste documenten genomen. We maken ook gebruik van een kNN-index om in real-time de meest relevante documenten voor de gebruiker te selecteren. Er zijn verschillende methoden voor het bouwen van een kNN-index, en voor ons heeft de beste gewerkt: <noindex><a rel=\"nofollow\" href=\"https:\/\/arxiv.org\/abs\/1603.09320\">HNSW<\/a><\/noindex> (Hierarchical Navigable Small World graphs). Dit is een hi\u00ebrarchisch model dat in enkele milliseconden de N dichtstbijzijnde vectors voor de gebruiker kan vinden uit een database van miljoenen. Vooraf indexeren we offline al onze documenten. Aangezien de zoekopdracht in de index redelijk snel werkt, kunnen we met een aantal sterke embeddings ook meerdere indexen maken (\u00e9\u00e9n index voor elke embedding) en in real-time naar elk van deze indexen verwijzen.<\/p>\n<p>We hebben tienduizenden documenten voor elke gebruiker. Dit blijft veel als het gaat om het tellen van alle kenmerken, dus in dit stadium passen we lichte rangschikking toe - een vereenvoudigd model van zware rangschikking met minder kenmerken. Het doel is om te voorspellen welke documenten bovenaan de zware model zullen staan. Documenten met de hoogste voorspelling worden gebruikt in het zware model, dat wil zeggen in de laatste rangschikkingsfase. Deze aanpak maakt het mogelijk om in enkele milliseconden de database van documenten die voor de gebruiker in aanmerking komen van miljoenen tot duizenden te reduceren.<\/p>\n<h2>ALS-stap in runtime<\/h2>\n<p>\n<b>Hoe feedback van de gebruiker te verwerken onmiddellijk na de klik?<\/b><\/p>\n<p>Een belangrijke factor in aanbevelingen is de responstijd op de feedback van de gebruiker. Dit is vooral belangrijk voor nieuwe gebruikers: wanneer iemand net begint met het gebruik van het aanbevelingssysteem, ontvangt hij een ongepersonaliseerde feed van diverse documenten. Zodra hij de eerste klik maakt, moet dit onmiddellijk worden in overweging genomen en moet het systeem zich afstemmen op zijn interesses. Als alle factoren offline worden berekend, wordt een snelle reactie van het systeem onmogelijk door de vertraging. Daarom is het noodzakelijk om de acties van de gebruiker in realtime te verwerken. Voor deze doeleinden gebruiken we de ALS-stap in runtime om de vectorrepresentatie van de gebruiker op te bouwen.<\/p>\n<p>Laten we aannemen dat we voor alle documenten een vectorrepresentatie hebben. Bijvoorbeeld, we kunnen offline op basis van de tekst van het artikel embeddings bouwen met behulp van ELMo, BERT of andere machine learning-modellen. Hoe kunnen we een vectorrepresentatie van gebruikers in dezelfde ruimte verkrijgen op basis van hun interactie in het systeem?<\/p>\n<p><b class=\"spoiler_title\">Algemeen principe van het vormen en ontleden van de gebruikers-documentmatrix<\/b>Laten we aannemen dat we m gebruikers en n documenten hebben. Voor sommige gebruikers is hun relatie tot bepaalde documenten bekend. Deze informatie kan worden weergegeven in een matrix van m x n: de rijen komen overeen met de gebruikers en de kolommen met de documenten. Aangezien de meeste documenten door de gebruiker niet zijn bekeken, blijven veel cellen in de matrix leeg, terwijl andere gevuld zullen zijn. Voor elk evenement (like, dislike, klik) is er een waarde in de matrix \u2014 maar laten we een vereenvoudigd model beschouwen waarin een like overeenkomt met 1 en een dislike met -1.<\/p>\n<p>We splitsen de matrix in twee: P (m x d) en Q (d x n), waarbij d de dimensionele representatie is (meestal een klein aantal). Dan komt aan elk object een d-dimensionale vector toe (de gebruiker is een rij in matrix P, het document is een kolom in matrix Q). Deze vectoren zijn de embeddings van de overeenkomstige objecten. Om te voorspellen of een gebruiker een document leuk zal vinden, kunnen we eenvoudigweg hun embeddings vermenigvuldigen.<\/p>\n<p><img decoding=\"async\" alt=\"Hoe wij werken aan de kwaliteit en snelheid van aanbevelingen\" src=\"\/wp-content\/uploads\/2020\/02\/a0c721bccb3806f2c4a18693a9458a89.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nEen van de mogelijke methoden voor matrixfactorisatie is ALS (Alternating Least Squares). We optimaliseren de volgende verliesfunctie:<\/p>\n<p><img decoding=\"async\" alt=\"Hoe wij werken aan de kwaliteit en snelheid van aanbevelingen\" src=\"\/wp-content\/uploads\/2020\/02\/aab8a1ae1cdf39de21e7469864c5190a.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p>\nHier is rui de interactie van gebruiker u met document i, qi de vector van document i, en pu de vector van gebruiker u.<\/p>\n<p>Dan wordt de optimale vector voor de gebruiker (bij vastgestelde documentvectoren) analytisch bepaald door de oplossing van de overeenkomstige lineaire regressie.<\/p>\n<p>Dit wordt de 'ALS-stap' genoemd. Het ALS-algoritme houdt in dat we om de beurt een van de matrices (gebruikers en artikelen) fixeren en de andere bijwerken om de optimale oplossing te vinden.<\/p>\n<p>Gelukkig is het vinden van de vectorrepresentatie van een gebruiker een vrij snelle operatie die in real-time kan worden uitgevoerd met behulp van vectorinstructies. Deze truc maakt het mogelijk om onmiddellijk rekening te houden met de feedback van de gebruiker in de rangschikking. Een vergelijkbare embedding kan ook worden gebruikt in de kNN-index voor een betere selectie van kandidaten.<\/p>\n<h2>Gedistribueerde collaboratieve filtering<\/h2>\n<p>\n<b>Hoe doe je incrementele gedistribueerde matrixfactorisatie en vind je snel de vectorrepresentatie van nieuwe artikelen?<\/b><\/p>\n<p>Content is not the only source of signals for recommendations. Another important source is collaborative information. Good indicators in ranking can traditionally be obtained from the decomposition of the user-document matrix. However, when attempting to carry out such decomposition, we encountered several problems:<\/p>\n<p>1. We have millions of documents and tens of millions of users. The matrix does not fit entirely on one machine, and the decomposition will take a very long time.<br \/>\n2. Most of the content in the system has a short lifespan: documents remain relevant for only a few hours. Therefore, it is necessary to construct their vector representation as quickly as possible.<br \/>\n3. If the decomposition is built immediately after the document is published, it won't be evaluated by a sufficient number of users in time. Consequently, its vector representation is likely to be suboptimal.<br \/>\n4. If a user likes or dislikes a document, we won't be able to take this into account in the decomposition immediately.<\/p>\n<p>To resolve these issues, we implemented a distributed decomposition of the user-document matrix with frequent incremental updates. How exactly does this work?<\/p>\n<p>Let\u2019s assume we have a cluster of N machines (N counts in the hundreds) and we want to perform a distributed decomposition of a matrix that does not fit on a single machine. The question is how to execute this decomposition in such a way that, on one hand, each machine has enough data, and on the other hand, the computations are independent? <\/p>\n<p><img decoding=\"async\" alt=\"Hoe wij werken aan de kwaliteit en snelheid van aanbevelingen\" src=\"\/wp-content\/uploads\/2020\/02\/9170b0fecb6efcd41754ec20ee539a15.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nWe will use the ALS decomposition algorithm described above. Let\u2019s consider how to perform one step of ALS in a distributed manner\u2014subsequent steps will be similar. Suppose we have a fixed document matrix and we want to construct a user matrix. For this, we will split it into N parts by rows, each part containing approximately the same number of rows. We will send to each machine the non-empty cells of the corresponding rows, as well as the document embedding matrix (in its entirety). Since its size is not very large, and the user-document matrix is usually quite sparse, this data will fit on a regular machine.<\/p>\n<p>Deze truc kan gedurende meerdere tijdperken worden herhaald tot de modelconvergentie, door afwisselend de vaste matrix te wijzigen. Maar zelfs dan kan het ontledigen van de matrix enkele uren duren. En dit lost het probleem niet op dat we snel de embeddings van nieuwe documenten moeten krijgen en de embeddings van die documenten moeten bijwerken waarvoor we tijdens de modelbouw weinig informatie hadden. <\/p>\n<p>We hebben het implementeren van een snelle incrementele update van het model geholpen. Stel dat we een actuele getrainde model hebben. Sinds de training zijn er nieuwe artikelen verschenen die onze gebruikers hebben bekeken, evenals artikelen die tijdens training weinig interactie hadden. Voor het snel verkrijgen van de embedding van dergelijke artikelen gebruiken we de gebruikersembeddings die tijdens de eerste grote training van het model zijn verkregen, en we doen \u00e9\u00e9n stap ALS om de documentmatrix te berekenen met een vaste gebruikersmatrix. Dit stelt ons in staat om embeddings vrij snel te krijgen - binnen enkele minuten na publicatie van het document - en vaak de embeddings van nieuwe documenten bij te werken.<\/p>\n<p>Om direct rekening te houden met de acties van de gebruiker bij aanbevelingen, gebruiken we in runtime de offline verkregen gebruikersembeddings niet. In plaats daarvan doen we een stap ALS en verkrijgen we de actuele gebruikersvector.<\/p>\n<h2>Overdracht naar een ander domein<\/h2>\n<p>\n<b>Hoe kunnen we de feedback van gebruikers op tekstartikelen gebruiken om een vectorrepresentatie van video te bouwen?<\/b><\/p>\n<p>Oorspronkelijk raadden we alleen tekstartikelen aan, waardoor veel van onze algoritmes zijn gericht op dit type inhoud. Maar bij het toevoegen van andere soorten inhoud kwamen we de behoefte tegen om de modellen aan te passen. Hoe hebben we deze uitdaging aangepakt aan de hand van video? Een van de opties is om alle modellen vanaf nul opnieuw te trainen. Maar dit kost veel tijd en bovendien zijn sommige algoritmes veeleisend wat betreft de hoeveelheid trainingsdata, die in de eerste momenten van het leven van nieuwe inhoud op de service nog niet in voldoende hoeveelheid aanwezig is.<\/p>\n<p>We took a different approach and reused text models for videos. In creating vector representations of videos, we utilized the same ALS trick. We took the vector representation of users based on textual articles and implemented an ALS step, using video view information. This allowed us to easily obtain the vector representation of the video. During runtime, we simply calculate the similarity between the user vector derived from text articles and the video vector.<\/p>\n<h2>Conclusie<\/h2>\n<p>\nThe development of the core real-time recommendation system is associated with numerous tasks. We need to quickly process data and apply ML methods for effective use of this data; build complex distributed systems capable of processing user signals and new content units in minimal time; and many other challenges.<\/p>\n<p>In the current system, the design of which I have described, the quality of recommendations for the user grows with their activity and the duration of their stay on the service. However, therein lies the main challenge: the system struggles to instantly understand the interests of a person who has interacted little with the content. Improving recommendations for new users is our key task. We will continue to optimize algorithms so that relevant content reaches their feeds faster, while irrelevant content is not displayed.<br \/>\n<br \/>Bron: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/yandex\/blog\/490140\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u041f\u0430\u0432\u0435\u043b \u041f\u0430\u0440\u0445\u043e\u043c\u0435\u043d\u043a\u043e, \u044f ML-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a. \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0445\u043e\u0442\u0435\u043b \u0431\u044b \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043e\u0431 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u042f\u043d\u0434\u0435\u043a\u0441.\u0414\u0437\u0435\u043d \u0438 \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u043c\u0438 \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044f\u043c\u0438, \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u0435 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u043b\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0442\u044c \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u043e \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0439. \u0418\u0437 \u043f\u043e\u0441\u0442\u0430 \u0432\u044b \u0443\u0437\u043d\u0430\u0435\u0442\u0435, \u043a\u0430\u043a \u0432\u0441\u0435\u0433\u043e \u0437\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0438\u043b\u043b\u0438\u0441\u0435\u043a\u0443\u043d\u0434 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c \u0441\u0440\u0435\u0434\u0438 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0440\u0435\u043b\u0435\u0432\u0430\u043d\u0442\u043d\u044b\u0435 \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f; \u043a\u0430\u043a \u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0435\u043f\u0440\u0435\u0440\u044b\u0432\u043d\u043e\u0435 \u0440\u0430\u0437\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043c\u0430\u0442\u0440\u0438\u0446\u044b (\u0441\u043e\u0441\u0442\u043e\u044f\u0449\u0435\u0439 \u0438\u0437 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u0441\u0442\u043e\u043b\u0431\u0446\u043e\u0432 \u0438 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":71853,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-71852","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.3 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u041f\u0430\u0432\u0435\u043b \u041f\u0430\u0440\u0445\u043e\u043c\u0435\u043d\u043a\u043e, \u044f ML-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a. \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0445\u043e\u0442\u0435\u043b \u0431\u044b \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043e\u0431 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u042f\u043d\u0434\u0435\u043a\u0441.\u0414\u0437\u0435\u043d \u0438 \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u043c\u0438 \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044f\u043c\u0438, \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u0435 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u043b\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0442\u044c \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u043e \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0439.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/nl\/blog\/administrirovanie\/kak-my-rabotaem-nad-kachestvom-i-skorostyu-podbora-rekomendaczij\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"nl_NL\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041a\u0430\u043a \u043c\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u043d\u0430\u0434 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u0438 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c\u044e \u043f\u043e\u0434\u0431\u043e\u0440\u0430 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0439 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u041f\u0430\u0432\u0435\u043b \u041f\u0430\u0440\u0445\u043e\u043c\u0435\u043d\u043a\u043e, \u044f ML-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a. \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0445\u043e\u0442\u0435\u043b \u0431\u044b \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043e\u0431 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u042f\u043d\u0434\u0435\u043a\u0441.\u0414\u0437\u0435\u043d \u0438 \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u043c\u0438 \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044f\u043c\u0438, \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u0435 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u043b\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0442\u044c \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u043e \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0439.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/nl\/blog\/administrirovanie\/kak-my-rabotaem-nad-kachestvom-i-skorostyu-podbora-rekomendaczij\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-02-28T17:59:58+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-03-03T13:14:08+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47How we work on improving the quality and speed of recommendations | ProHoster","description":"My name is Pavel Parkhomenko, and I am an ML developer. In this article, I would like to explain the structure of the Yandex Zen service and share technical improvements that have been implemented to enhance the quality of recommendations.","canonical_url":"https:\/\/prohoster.info\/nl\/blog\/administrirovanie\/kak-my-rabotaem-nad-kachestvom-i-skorostyu-podbora-rekomendaczij","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"nl_NL","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041a\u0430\u043a \u043c\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u043d\u0430\u0434 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u0438 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c\u044e \u043f\u043e\u0434\u0431\u043e\u0440\u0430 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0439 | ProHoster","og:description":"\u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u041f\u0430\u0432\u0435\u043b \u041f\u0430\u0440\u0445\u043e\u043c\u0435\u043d\u043a\u043e, \u044f ML-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a. \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0445\u043e\u0442\u0435\u043b \u0431\u044b \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043e\u0431 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u042f\u043d\u0434\u0435\u043a\u0441.\u0414\u0437\u0435\u043d \u0438 \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u043c\u0438 \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044f\u043c\u0438, \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u0435 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u043b\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0442\u044c \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u043e \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0439.","og:url":"https:\/\/prohoster.info\/nl\/blog\/administrirovanie\/kak-my-rabotaem-nad-kachestvom-i-skorostyu-podbora-rekomendaczij","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-02-28T17:59:58+00:00","article:modified_time":"2020-03-03T13:14:08+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"71852","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 18:55:28","updated":"2022-10-09 15:47:56","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/posts\/71852","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/comments?post=71852"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/posts\/71852\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/media\/71853"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/media?parent=71852"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/categories?post=71852"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/tags?post=71852"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}