{"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\/pt\/blog\/administrirovanie\/kak-my-rabotaem-nad-kachestvom-i-skorostyu-podbora-rekomendaczij","title":{"rendered":"Como trabalhamos na qualidade e velocidade da sele\u00e7\u00e3o de recomenda\u00e7\u00f5es","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Meu nome \u00e9 Pavel Parkhomenko, sou desenvolvedor de ML. Neste artigo, gostaria de falar sobre o funcionamento do servi\u00e7o Yandex Zen e compartilhar melhorias t\u00e9cnicas que permitiram aumentar a qualidade das recomenda\u00e7\u00f5es. Neste post, voc\u00ea aprender\u00e1 como encontrar entre milh\u00f5es de documentos os mais relevantes para o usu\u00e1rio em apenas alguns milissegundos; como realizar a decomposi\u00e7\u00e3o cont\u00ednua de uma grande matriz (composta por milh\u00f5es de colunas e dezenas de milh\u00f5es de linhas), para que novos documentos recebam seu vetor em apenas algumas dezenas de minutos; como reutilizar a decomposi\u00e7\u00e3o da matriz usu\u00e1rio-artigo, para obter uma boa representa\u00e7\u00e3o vetorial para v\u00eddeos.<\/p>\n<p><img decoding=\"async\" alt=\"Como trabalhamos na qualidade e velocidade da sele\u00e7\u00e3o de recomenda\u00e7\u00f5es\" 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 \/>\nNossa base de recomenda\u00e7\u00f5es cont\u00e9m milh\u00f5es de documentos de diferentes formatos: artigos de texto, criados em nossa plataforma e extra\u00eddos de sites externos, v\u00eddeos, narrativas e posts curtos. O desenvolvimento de um servi\u00e7o como este est\u00e1 associado a muitos desafios t\u00e9cnicos. Aqui est\u00e3o alguns deles:<\/p>\n<ul>\n<li>Dividir as tarefas computacionais: realizar todas as opera\u00e7\u00f5es pesadas offline e na hora, executar apenas a aplica\u00e7\u00e3o r\u00e1pida dos modelos, para responder em 100-200 ms.<\/li>\n<li>Considerar rapidamente as a\u00e7\u00f5es do usu\u00e1rio. Para isso, \u00e9 necess\u00e1rio que todos os eventos sejam instantaneamente entregues ao recomendador e impactem os resultados das modelos.<\/li>\n<li>Fazer com que o feed se adapte rapidamente ao comportamento dos novos usu\u00e1rios. As pessoas que chegam ao sistema devem sentir que seu feedback influencia as recomenda\u00e7\u00f5es.<\/li>\n<li>Compreender rapidamente a quem recomendar um novo artigo.<\/li>\n<li>Reagir rapidamente ao constante surgimento de novo conte\u00fado. Dezena de milhares de artigos s\u00e3o lan\u00e7ados todos os dias, e muitos deles t\u00eam uma vida \u00fatil limitada (como not\u00edcias, por exemplo). Isso os diferencia de filmes, m\u00fasicas e outros conte\u00fados que t\u00eam uma longa dura\u00e7\u00e3o e s\u00e3o mais caros para criar.<\/li>\n<li>Transferir conhecimentos de um dom\u00ednio para outro. Se em um sistema de recomenda\u00e7\u00e3o existem modelos treinados para artigos de texto e acrescentamos v\u00eddeos a ele, podemos reutilizar os modelos existentes para que o novo tipo de conte\u00fado seja melhor classificado.<\/li>\n<\/ul>\n<p>\nVou contar como resolvemos esses desafios.<\/p>\n<h2>Sele\u00e7\u00e3o de candidatos<\/h2>\n<p>\n<b>Como reduzir, em poucos milissegundos, a quantidade de documentos considerados em milhares de vezes, sem praticamente piorar a qualidade da classifica\u00e7\u00e3o?<\/b><\/p>\n<p>Suponha que treinamos muitos modelos de ML, geramos recursos a partir deles e treinamos outro modelo que classifica documentos para o usu\u00e1rio. Tudo estaria bem, mas n\u00e3o se pode simplesmente calcular todos os recursos para todos os documentos em tempo real, se esses documentos s\u00e3o milh\u00f5es e as recomenda\u00e7\u00f5es precisam ser feitas em 100-200 ms. A tarefa \u00e9 escolher de milh\u00f5es um subconjunto que ser\u00e1 classificado para o usu\u00e1rio. Essa etapa \u00e9 geralmente chamada de sele\u00e7\u00e3o de candidatos. Existem alguns requisitos para isso. Em primeiro lugar, a sele\u00e7\u00e3o deve ser muito r\u00e1pida, para que o tempo para a pr\u00f3pria classifica\u00e7\u00e3o seja maximizado. Em segundo lugar, ao reduzir significativamente o n\u00famero de documentos para a classifica\u00e7\u00e3o, devemos preservar ao m\u00e1ximo os documentos relevantes para o usu\u00e1rio.<\/p>\n<p>O nosso princ\u00edpio de sele\u00e7\u00e3o de candidatos evoluiu ao longo do tempo, e atualmente chegamos a um esquema em v\u00e1rias etapas:<\/p>\n<p><img decoding=\"async\" alt=\"Como trabalhamos na qualidade e velocidade da sele\u00e7\u00e3o de recomenda\u00e7\u00f5es\" src=\"\/wp-content\/uploads\/2020\/02\/ed9657ed1febe871f36dc7cf7e585963.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nPrimeiro, todos os documentos s\u00e3o divididos em grupos, e dos grupos s\u00e3o selecionados os documentos mais populares. Os grupos podem ser sites, temas, clusters. Para cada usu\u00e1rio, com base em seu hist\u00f3rico, s\u00e3o selecionados os grupos mais pr\u00f3ximos e, a partir deles, s\u00e3o escolhidos os melhores documentos. Tamb\u00e9m usamos um \u00edndice kNN para encontrar os documentos mais pr\u00f3ximos do usu\u00e1rio em tempo real. Existem v\u00e1rios m\u00e9todos para a constru\u00e7\u00e3o do \u00edndice kNN, e o que melhor funcionou para n\u00f3s foi <noindex><a rel=\"nofollow\" href=\"https:\/\/arxiv.org\/abs\/1603.09320\">HNSW<\/a><\/noindex> (Hierarchical Navigable Small World graphs). Este \u00e9 um modelo hier\u00e1rquico que permite encontrar, em poucos milissegundos, os N vetores mais pr\u00f3ximos para o usu\u00e1rio a partir de uma base de milh\u00f5es. Inicialmente, indexamos toda a nossa base de documentos offline. Como a busca no \u00edndice \u00e9 bastante r\u00e1pida, \u00e9 poss\u00edvel, se tivermos v\u00e1rios embeddings fortes, criar v\u00e1rios \u00edndices (um para cada embedding) e consultar cada um deles em tempo real.<\/p>\n<p>Temos dezenas de milhares de documentos para cada usu\u00e1rio. Isso ainda \u00e9 muito para contar todas as caracter\u00edsticas, ent\u00e3o, neste est\u00e1gio, aplicamos uma classifica\u00e7\u00e3o leve \u2014 um modelo simplificado de classifica\u00e7\u00e3o pesada com menos caracter\u00edsticas. O objetivo \u00e9 prever quais documentos estar\u00e3o no topo do modelo pesado. Os documentos com a maior previs\u00e3o ser\u00e3o usados no modelo pesado, ou seja, na \u00faltima etapa de classifica\u00e7\u00e3o. Essa abordagem permite, em dezenas de milissegundos, reduzir a base de documentos considerados para o usu\u00e1rio de milh\u00f5es para milhares.<\/p>\n<h2>Passo ALS em tempo de execu\u00e7\u00e3o<\/h2>\n<p>\n<b>Como considerar o feedback do usu\u00e1rio imediatamente ap\u00f3s o clique?<\/b><\/p>\n<p>Um fator importante nas recomenda\u00e7\u00f5es \u00e9 o tempo de resposta ao feedback do usu\u00e1rio. Isso \u00e9 especialmente crucial para novos usu\u00e1rios: quando algu\u00e9m come\u00e7a a usar o sistema de recomenda\u00e7\u00f5es, recebe um feed n\u00e3o personalizado com uma variedade de documentos. Assim que faz o primeiro clique, \u00e9 necess\u00e1rio levar isso em conta imediatamente e se ajustar aos seus interesses. Se calcul\u00e1ssemos todos os fatores offline, a r\u00e1pida rea\u00e7\u00e3o do sistema se tornaria imposs\u00edvel devido ao atraso. Portanto, \u00e9 necess\u00e1rio processar as a\u00e7\u00f5es do usu\u00e1rio em tempo real. Para esses fins, usamos o passo ALS em tempo de execu\u00e7\u00e3o para construir a representa\u00e7\u00e3o vetorial do usu\u00e1rio.<\/p>\n<p>Suponha que temos uma representa\u00e7\u00e3o vetorial para todos os documentos. Por exemplo, podemos offline, com base no texto do artigo, construir embeddings usando ELMo, BERT ou outros modelos de aprendizado de m\u00e1quina. Como podemos obter a representa\u00e7\u00e3o vetorial dos usu\u00e1rios neste mesmo espa\u00e7o com base em suas intera\u00e7\u00f5es no sistema?<\/p>\n<p><b class=\"spoiler_title\">Princ\u00edpio geral de forma\u00e7\u00e3o e decomposi\u00e7\u00e3o da matriz usu\u00e1rio-documento<\/b>Suponha que temos m usu\u00e1rios e n documentos. Para alguns usu\u00e1rios, sabemos a rela\u00e7\u00e3o deles com alguns documentos. Ent\u00e3o, essa informa\u00e7\u00e3o pode ser representada na forma de uma matriz m x n: as linhas correspondem aos usu\u00e1rios, e as colunas \u2014 aos documentos. Como a maioria dos documentos n\u00e3o foi vista pela pessoa, a maior parte das c\u00e9lulas da matriz permanecer\u00e1 vazia, enquanto outras estar\u00e3o preenchidas. Para cada evento (curtida, descurtida, clique) na matriz, est\u00e1 previsto algum valor \u2014 mas vamos considerar um modelo simplificado, onde a curtida corresponde a 1 e a descurtida a -1.<\/p>\n<p>Vamos decompor a matriz em duas: P (m x d) e Q (d x n), onde d \u00e9 a dimens\u00e3o da representa\u00e7\u00e3o vetorial (geralmente um n\u00famero pequeno). Assim, cada objeto ter\u00e1 um vetor d-dimensional (o usu\u00e1rio \u2014 uma linha na matriz P, o documento \u2014 uma coluna na matriz Q). Esses vetores ser\u00e3o os embeddings dos respectivos objetos. Para prever se um usu\u00e1rio gostar\u00e1 de um documento, podemos simplesmente multiplicar seus embeddings.<\/p>\n<p><img decoding=\"async\" alt=\"Como trabalhamos na qualidade e velocidade da sele\u00e7\u00e3o de recomenda\u00e7\u00f5es\" src=\"\/wp-content\/uploads\/2020\/02\/a0c721bccb3806f2c4a18693a9458a89.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nUm dos poss\u00edveis m\u00e9todos de decomposi\u00e7\u00e3o de matriz \u00e9 o ALS (Alternating Least Squares). Vamos otimizar a seguinte fun\u00e7\u00e3o de perda:<\/p>\n<p><img decoding=\"async\" alt=\"Como trabalhamos na qualidade e velocidade da sele\u00e7\u00e3o de recomenda\u00e7\u00f5es\" src=\"\/wp-content\/uploads\/2020\/02\/aab8a1ae1cdf39de21e7469864c5190a.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p>\nAqui, rui \u00e9 a intera\u00e7\u00e3o do usu\u00e1rio u com o documento i, qi \u00e9 o vetor do documento i, pu \u00e9 o vetor do usu\u00e1rio u.<\/p>\n<p>Ent\u00e3o, o vetor do usu\u00e1rio otimizado em termos de erro quadr\u00e1tico m\u00e9dio (com vetores de documentos fixos) \u00e9 encontrado analiticamente atrav\u00e9s da solu\u00e7\u00e3o da respectiva regress\u00e3o linear.<\/p>\n<p>Isso \u00e9 chamado de \"passo ALS\". O pr\u00f3prio algoritmo ALS consiste em fixar alternadamente uma das matrizes (dos usu\u00e1rios e dos artigos) e atualizar a outra, encontrando a solu\u00e7\u00e3o \u00f3tima.<\/p>\n<p>Felizmente, encontrar a representa\u00e7\u00e3o vetorial do usu\u00e1rio \u00e9 uma opera\u00e7\u00e3o bastante r\u00e1pida que pode ser realizada em tempo real, utilizando instru\u00e7\u00f5es vetoriais. Esse truque permite que o feedback do usu\u00e1rio seja considerado imediatamente na classifica\u00e7\u00e3o. O mesmo embedding pode ser utilizado em um \u00edndice kNN para melhorar a sele\u00e7\u00e3o de candidatos.<\/p>\n<h2>Filtragem colaborativa distribu\u00edda<\/h2>\n<p>\n<b>Como realizar a fatora\u00e7\u00e3o matricial distribu\u00edda incremental e encontrar rapidamente a representa\u00e7\u00e3o vetorial de novos artigos?<\/b><\/p>\n<p>O conte\u00fado n\u00e3o \u00e9 a \u00fanica fonte de sinais para recomenda\u00e7\u00f5es. Outra fonte importante \u00e9 a informa\u00e7\u00e3o colaborativa. Bons sinais em classifica\u00e7\u00e3o tradicionalmente podem ser obtidos a partir da decomposi\u00e7\u00e3o da matriz usu\u00e1rio-documento. No entanto, ao tentar fazer essa decomposi\u00e7\u00e3o, encontramos problemas:<\/p>\n<p>1. Temos milh\u00f5es de documentos e dezenas de milh\u00f5es de usu\u00e1rios. A matriz n\u00e3o cabe inteira em uma \u00fanica m\u00e1quina, e a decomposi\u00e7\u00e3o ser\u00e1 muito lenta.<br \/>\n2. A maior parte do conte\u00fado no sistema tem um curto tempo de vida: os documentos permanecem relevantes apenas por algumas horas. Portanto, \u00e9 necess\u00e1rio construir sua representa\u00e7\u00e3o vetorial o mais r\u00e1pido poss\u00edvel.<br \/>\n3. Se construirmos a decomposi\u00e7\u00e3o logo ap\u00f3s a publica\u00e7\u00e3o do documento, ele n\u00e3o ter\u00e1 sido avaliado por um n\u00famero suficiente de usu\u00e1rios. Assim, sua representa\u00e7\u00e3o vetorial provavelmente n\u00e3o ser\u00e1 muito boa.<br \/>\n4. Se um usu\u00e1rio der um like ou dislike, n\u00e3o poderemos considerar isso imediatamente na decomposi\u00e7\u00e3o.<\/p>\n<p>Para resolver os problemas listados, implementamos uma decomposi\u00e7\u00e3o distribu\u00edda da matriz usu\u00e1rio-documento com atualiza\u00e7\u00e3o incremental frequente. Como isso funciona?<\/p>\n<p>Suponha que temos um cluster de N m\u00e1quinas (N na casa das centenas) e queremos realizar a decomposi\u00e7\u00e3o distribu\u00edda da matriz, que n\u00e3o cabe em uma \u00fanica m\u00e1quina. A quest\u00e3o \u00e9 como executar essa decomposi\u00e7\u00e3o de modo que, por um lado, cada m\u00e1quina tenha dados suficientes e, por outro, que os c\u00e1lculos sejam independentes? <\/p>\n<p><img decoding=\"async\" alt=\"Como trabalhamos na qualidade e velocidade da sele\u00e7\u00e3o de recomenda\u00e7\u00f5es\" src=\"\/wp-content\/uploads\/2020\/02\/9170b0fecb6efcd41754ec20ee539a15.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nUsaremos o algoritmo de decomposi\u00e7\u00e3o ALS descrito acima. Vamos considerar como executar distribuidamente um passo do ALS \u2013 os passos restantes ser\u00e3o semelhantes. Suponha que temos a matriz de documentos fixada e queremos construir a matriz de usu\u00e1rios. Para isso, vamos dividi-la em N partes por linhas, cada parte contendo aproximadamente o mesmo n\u00famero de linhas. Enviaremos para cada m\u00e1quina as c\u00e9lulas n\u00e3o vazias das linhas correspondentes, bem como a matriz de embeddings dos documentos (por completo). Como ela n\u00e3o \u00e9 muito grande, e a matriz usu\u00e1rio-documento geralmente \u00e9 bem esparsa, esses dados caber\u00e3o em uma m\u00e1quina comum.<\/p>\n<p>Esse truque pode ser repetido ao longo de v\u00e1rias eras at\u00e9 a converg\u00eancia do modelo, alternando a matriz fixa. Mas mesmo assim, a decomposi\u00e7\u00e3o da matriz pode levar v\u00e1rias horas. E isso n\u00e3o resolve o problema de que \u00e9 necess\u00e1rio obter rapidamente os embeddings de novos documentos e atualizar os embeddings daqueles sobre os quais havia pouca informa\u00e7\u00e3o ao construir o modelo. <\/p>\n<p>A implementa\u00e7\u00e3o de uma atualiza\u00e7\u00e3o incremental r\u00e1pida do modelo nos ajudou. Suponha que temos um modelo treinado atualmente. Desde o seu treinamento, surgiraram novos artigos com os quais nossos usu\u00e1rios interagiram, al\u00e9m de artigos que tiveram pouca intera\u00e7\u00e3o durante o treinamento. Para obter rapidamente o embedding desses artigos, usamos os embeddings dos usu\u00e1rios obtidos durante o primeiro grande treinamento do modelo e fazemos um passo de ALS para calcular a matriz de documentos com a matriz de usu\u00e1rios fixa. Isso permite obter os embeddings de forma bastante r\u00e1pida \u2014 em poucos minutos ap\u00f3s a publica\u00e7\u00e3o do documento \u2014 e atualizar frequentemente os embeddings de documentos recentes.<\/p>\n<p>Para que as a\u00e7\u00f5es da pessoa sejam levadas em conta imediatamente nas recomenda\u00e7\u00f5es, durante a execu\u00e7\u00e3o n\u00e3o usamos os embeddings dos usu\u00e1rios obtidos offline. Em vez disso, fazemos um passo de ALS e obtemos o vetor atual do usu\u00e1rio.<\/p>\n<h2>Transfer\u00eancia para outro dom\u00ednio.<\/h2>\n<p>\n<b>Como usar o feedback do usu\u00e1rio em artigos de texto para construir uma representa\u00e7\u00e3o vetorial de v\u00eddeos?<\/b><\/p>\n<p>Inicialmente, recomend\u00e1vamos apenas artigos de texto, portanto, muitos dos nossos algoritmos est\u00e3o ajustados para esse tipo de conte\u00fado. Mas ao adicionar conte\u00fado de outro tipo, nos deparamos com a necessidade de adapta\u00e7\u00e3o dos modelos. Como abordamos esse desafio no caso de v\u00eddeos? Uma das op\u00e7\u00f5es foi re-treinar todos os modelos do zero. Mas isso \u00e9 demorado e, al\u00e9m disso, parte dos algoritmos \u00e9 exigente quanto ao tamanho do conjunto de treinamento, que ainda n\u00e3o est\u00e1 dispon\u00edvel em quantidade suficiente para o conte\u00fado do novo tipo nos primeiros momentos de sua vida no servi\u00e7o.<\/p>\n<p>Seguimos um caminho diferente e reutilizamos modelos de textos para v\u00eddeos. A cria\u00e7\u00e3o de representa\u00e7\u00f5es vetoriais de v\u00eddeos foi facilitada pelo mesmo truque com ALS. Pegamos a representa\u00e7\u00e3o vetorial dos usu\u00e1rios com base em textos e fizemos um passo de ALS, utilizando informa\u00e7\u00f5es sobre visualiza\u00e7\u00f5es de v\u00eddeo. Assim, obtivemos facilmente a representa\u00e7\u00e3o vetorial do v\u00eddeo. E, em tempo de execu\u00e7\u00e3o, simplesmente calculamos a proximidade entre o vetor do usu\u00e1rio, obtido com base em textos, e o vetor do v\u00eddeo.<\/p>\n<h2>Conclus\u00e3o<\/h2>\n<p>\nO desenvolvimento do n\u00facleo de um sistema de recomenda\u00e7\u00e3o em tempo real envolve diversas tarefas. \u00c9 preciso processar dados rapidamente e aplicar m\u00e9todos de ML para utilizar esses dados de forma eficaz; construir sistemas distribu\u00eddos complexos, que consigam processar sinais de usu\u00e1rios e novas unidades de conte\u00fado em um tempo m\u00ednimo; entre muitas outras tarefas.<\/p>\n<p>No sistema atual, cuja estrutura descrevi, a qualidade das recomenda\u00e7\u00f5es para o usu\u00e1rio aumenta conforme sua atividade e dura\u00e7\u00e3o de perman\u00eancia no servi\u00e7o. Mas, claro, aqui reside a principal dificuldade: o sistema tem dificuldade em entender as prefer\u00eancias de uma pessoa que interagiu pouco com o conte\u00fado. Melhorar as recomenda\u00e7\u00f5es para novos usu\u00e1rios \u00e9 nossa tarefa chave. Continuaremos a otimizar os algoritmos para que o conte\u00fado relevante para a pessoa chegue mais rapidamente ao seu feed, enquanto o conte\u00fado irrelevante n\u00e3o seja exibido.<br \/>\n<br \/>Fonte: <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\/pt\/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=\"pt_PT\" \/>\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\/pt\/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\udd47Como trabalhamos na qualidade e velocidade das recomenda\u00e7\u00f5es | ProHoster","description":"Meu nome \u00e9 Pavel Parkhomenko, sou desenvolvedor de ML. Neste artigo, gostaria de falar sobre a estrutura do servi\u00e7o Yandex.Zen e compartilhar melhorias t\u00e9cnicas que, uma vez implementadas, permitiram aumentar a qualidade das recomenda\u00e7\u00f5es.","canonical_url":"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/kak-my-rabotaem-nad-kachestvom-i-skorostyu-podbora-rekomendaczij","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"pt_PT","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\/pt\/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\/pt\/wp-json\/wp\/v2\/posts\/71852","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/comments?post=71852"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts\/71852\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/media\/71853"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/media?parent=71852"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/categories?post=71852"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/tags?post=71852"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}