Sites de Busca
Básico
Google
Yahoo!
msn
dmoz
Outras SEs
Mais Info
|
Retornar à página sobre a Google
4 Anatomia do Sistema
Inicialmente, apresentamos uma discussão superficial sobre a
arquitetura. A seguir, descrevemos em profundidade algumas estruturas
de dados importantes. Por fim, discutimos em profundidade as
aplicações principais: rastreamento (crawling),
indexação (indexing) e pesquisa (searching).
Figura 1. Arquitetura Geral da Google
4.1 Arquitetura Simplificada da Google
Nessa seção, nós dados uma visão geral de
como o sistema funciona, conforme mostrado na Figura 1.
Seções mais adiante discutirão as
aplicações e estruturas de dados que não
são mencionadas nessa seção. A maior parte da
Google foi implementada em C ou C++, por razões de
eficiência, e roda em Solaris ou Linux.
Na Google, o rastreamento da web (web crawling - downloading de
páginas da web) é feito por vários crawlers
distribuídos. Existe um servidor de URL que envia aos cralers
listas de URLs a serem recuperadas. As páginas recuperadas
são enviadas ao storeserver. O storeserver comprime e armazena
as páginas web em um repositório. Toda página web
recebe um número de identificação chamado docID,
que é assignado toda vez que uma nova URL é
extraída de uma página. A indexação
é realizada pelo indexador (indexer) e pelo ordenador (sorter).
O indexer executa funções variadas; ele lê o
repositório, descomprime os documentos, e interpreta a sintaxe
(processo chamado "parse" ou "parsing"). Cada documento é
convertido em um conjunto de ocorrências de palavras, denominado
hits.
[Nota do Tradutor: o termo "hit" é largamente empregado nesse
texto, em um sentido pouco usual aos que não estão
familiarizados com Search Engines. Um hit, basicamente, é a
ocorrência de uma palavra de interesse em um documento sendo
pesquisado. Se estamos pesquisando a palavra "livro" e a mesma aparece
no documento http://www.dominio.com/biblioteca.html", dizemos que
ocorreu um hit; uma hit list (lista de hits) para a palavra "livros"
registraria a ocorrência no documento
http://www.dominio.com/biblioteca.html"]. Os hits gravam a palavra, a
posição no documento, uma estimativa do tamanho da fonte,
e a ocorrência de letras maiúsculas. O indexer distribui
esses hits através de um conjunto de "barrels", criando um
índice direto (forward index), parcialmente ordenado. O indexer
exerce outra função importante: ele extrai todos os links
de todas as páginas e armazena informações
relevantes sobre eles em um arquivo de âncoras (anchor file).
Esse arquivo contém informações suficientes para
determinar onde o link se origina, para onde se destina, e qual o texto
do link.
O resolvedor de URLs lê o arquivo de âncoras, converte URLs
relativas em URLs absolutas, e a seguir em docIDs. Ele coloca o texto
da âncora no índice direto, associado ao docID da
página para a qual o link aponta. Ele também gera um
banco de dados de links composto de pares de docIDs. O banco de dados
de links é utilizado para calcular o PageRank de todos os
documentos.
O sorter pega os barrels, que estão ordenados por docID (essa
é uma simplificação, ver Seção
4.2.5), e os reordena por wordID, para criar o índice invertido
(inverted index). Isso é feito no próprio local, de forma
que pouco espaço temporário seja necessário para a
operação. O sorter também produz uma lista de
wordIDs e offsets no índice invertido. Um programa chamado Dump
Lexicon pega essa lista, juntamente com o lexicon produzido pelo
indexer, e gera um novo lexicon que será utilizado pelo
searcher. O searcher é executado em um servidor web; para
responder às pesquisas, ele utiliza o lexicon produzido pelo
DumpLexicon, o índice invertido e os PageRanks.
4.2 Principais estruturas de dados
As estruturas de dados da Google são otimizadas de forma a
permitir que grandes conjuntos de documentos sejam rastreados,
indexados e pesquisados com um baixo custo. Embora CPUs e dispositivos
de entrada e saída tenham melhorado dramaticamente ao longo dos
últimos anos, uma pesquisa em disco ainda requer aproximadamente
10 ms para ser completada. Google foi projetada para evitar ao
máximo pesquisas em disco, e isso teve uma influência
considerável no projeto das estruturas de dados.
4.2.1 BigFiles
BigFiles são arquivos virtuais espalhados através de
múltiplos sistemas de arquivos, que são
endereçados por inteiros de 64 bits. A alocação
entre os múltiplos sistemas de arquivos é feita
automaticamente. O sistema de BigFiles também faz
alocação e desalocação dos descritores de
arquivos, já que os sistemas operacionais não suprem as
nossas necessidades. BigFiles suportam também algumas
opções básicas de compressão.
4.2.2 Repositório
Figura 2. Estrutura do Repositório de Dados
O repositório contém o HTML completo de cada
página web. Cada página é comprimida utilizando-se
zlib (ver RFC1950). A escolha da técnica de compressão
foi baseada em velocidade e taxa de compressão. Nós
escolhemos zlib por ser a mais rápida, emb ora bzip oferecesse
uma taxa de compressão significantemente maior. A taxa de
compressão da bzip foi aproximadamente 4 para 1, enquanto a da
zlib foi 3 para 1. No repositório, os documentos são
armazenados um após o outro e são prefixados pelo docID,
tamanho e URL, como ode ser visto na Figura 2. O repositório
não requer que nenhuma outra parte da estrutura de dados seja
usada para acessá-lo; esse fato é útil para se
conseguir consistência de dados e torna o desenvolvimento muito
mais fácil: podemos reconstruir todas as outras estruturas a
partir de tão somente o repositório e um arquivo que
liste erros reportados pelos crawlers.
4.2.3 Índice dos Documentos
O índice de documentos contém informações
sobre cada documen to. O índice é do tipo ISAM
(Index sequencial access mode), de largura fixa, ordenado por docIDs. A
informação armazenada em cada entry inclui o status atual
do documento, um ponteiro para o depositório, um checksum para
cada documento, e várias estatísticas. Se o documento foi
crawled, o índice conterá também um ponteiro para
um arquivo de tamanho variável chamado docinfo, que armazena o
URL e título do documento; caso contrário, o
ponteiro aponta para a URLlist, que armazena apenas a URL. Essa
decisão foi tomada com o intuito de se obter uma estrutura de
dados razoavelmente compacta, e ainda permitir o acesso a um record com
apenas uma pesquisa no disco.
Adicionalmente, existe um arquivo que é utilizado para converter
URLs em docIDs. Trata-se de uma lista de URLs, checksums e
docIDs, ordenada por checksum. Para encontrar o docID de uma URL em
particular, o checksum da URL é computado e uma busca
binária é realizada nesse arquivo; batches de URLs podem
ser convertidos em docIDs utilizando-se esse arquivo. Essa é a
técnica utilizada pelo URLresolver para transformar URLs em
docIDs. Esse modo de trabalho em batches é crucial, pois de
outra forma teríamos que realizar uma busca para cada link, o
que demandaria, para o nosso conjunto de 322 milhões de links,
mais de um mês de processamento.
4.2.4 Lexicon
O lexicon tem diversas peculiaridades. Uma importante mudança em
relação a sistemas anteriores é que o lexicon pode
ser totalmente alocado em memória, por um preço
razoável. Na implementação atual nós
mantemos o lexicon na memória de uma máquina com 256MB de
memória principal. O lexiconatual contém 14
milhões de palavras (algumas palavras raras não foram
adicionadas ao lexicon). Ele é implementado em duas partes : uma
lista de palavras (concatenadas juntas, mas separadas por nulls) e uma
tabela de hash de ponteiros. A lista de palavras exerce algumas
funções auxiliares, que estão além do
escopo desse paper.
4.2.5
Hit Lists
Uma hit list corresponde a uma lista de ocorrências de uma
determinada palavra em um determinado documento, incluindo
posição, fonte e capitalização (uso de
maiúsculas e minúsculas). As hit lists ocupam a maior
parte do espaço utilizado tanto no índice direto como no
índice invertido; por causa disso, é importante que sua
representação seja a mais eficiente possível.
[Nota do Tradutor: o conceito de hit list foi explicado de forma
demasiadamente resumida pelos autores do documento. Um exemplo
ajudará a esclarecer o que significa hit list. Suponhamos que,
no documento http://www.meudominio.com.br/automoveis.html, a palavra
"carro" apareça em várias partes: uma vez no
título "Melhores carros usados do mercado", uma vez em letras
maiúsculas no primeiro parágrafo (a décima palavra
do texto) e outra vez no terceiro parágrafo (a centésima
palavra do texto). Nesse exemplo, a hit list do documento
http://www.meudominio.com.br/automoveis.html (que será
identificado por um docID), para a palavra "carros" (que é
identificada por um wordID), deverá de alguma maneira armazenar
as informações: wordID aparece como 2a. palavra no
título do docID; word ID aparece como 10a palavra do texto, e
está em negrito; wordID aparece como 100a palavra do texto,
fonte normal. A hit list assim formada é empregada, como se
verá mais adiante, para a formação dos
índices direto e invertido.]
Nós analisamos diversas alternativas para
codificação da posição, fonte e
capitalização: codificação simples (uma
tripla de inteiros), codificação compacta (uma
alocação otimizada de bits), e a
codificação Huffman. Ao final, optamos pela segunda
opção, pois essa exigia muito menos espaço que a
primeira opção e muito menos manipulação de
bits que a codificação Huffman. Os detalhes sobre os hits
são mostrados na Figura 3.
Nossa codificação compacta utiliza dois bytes para cada
hit. Existem dois tipos de hits: fancy hits (hits especiais) e plain
hits (hits comuns). Fancy hits incluem hits que ocorrem na URL, no
título, nos textos das âncoras e nos meta tags. Todos os
outros hits são plain hits. Um plain hit é composto de um
bit para indicar capitalização, um bit para tamanho de
fonte, e 12 bits para a posição da palavra no documento
(todas as posições acima de 4095 - o limite
representável por doze bits - são consideradas como sendo
posição 4096). O tamanho de fonte toma três bits
(apenas 7 valores podem ser representados, pois 111 é um flag
para indicar um fancy hit), e é representado levando-se em conta
uma comparação com o restante do documento. Um fancy hit
é composto por um bit de capitalização, três
bits de tamanho que são sempre representados por 111, 4 bits
para indicar a classe de fancy hit, e 8 bits para
posição. Para hits de âncoras, os 8 bits de
posição são divididos em 4 bits para
posição dentro da âncora e 4 bits para um hash do
docID do documento no qual a âncora aparece. Isso nos dá
uma limitada capacidade de busca por frases, desde que não
existam muitas âncoras contendo uma determinada palavra.
Nós temos a expectativa de melhorar a maneira como os hits de
âncoras são armazenadas, a fim de permitir maior
resolução nos campos de posição e hashIDs.
A comparação do tamanho da fonte com o restante do
documento é feita porque não desejamos dar mais
importância a um de dois documentos idênticos somente
porque ele foi escrito com fontes maiores.
Figura 3. Indice Direto, Indice Invertido e o Lexicon
O tamanho de uma hit list é armazenada antes da
relação de hits. Para economizar espaço, os bits
que codificam o tamanho da hit list são combinados com os bits
da wordID no índice direto e com os do docID no índice
invertido. Isso limita a 8 e 5, respectivamente, o número de
bits disponíveis para representar o tamanho da hit list
(há alguns truques que permitem o empréstimo de 8 bits da
wordID para uso no tamanho da hit list). Se o tamanho é maior do
que o que pode ser descrito no número de bits disponível,
um escape code é colocado nesses bits, e os próximos dois
bytes passam a conter o tamanho da lista.
4.2.6. Indice direto
O índice direto já está, na realidade,
parcialmente ordenado. Ele é armazenado em vários barris
(nós usamos 64). Cada barril abriga uma faixa de wordIDs. Se um
documento contém palavras que caiam na faixa de um determinado
barril, o docID é gravado naquele barril, seguido por uma lista
de wordIDs e hitlists correspondentes àquelas palavras. [Nota do
Tradutor: novamente, um exemplo pode ajudar a clarificar a
questão. Suponhamos que determinado docID contenha, entre
várias outras, as palavras "comida" e "bebida", e que os wordIDs
dessas duas palavras caiam numa mesma faixa de wordIDs (ou seja, devam
ser armazenadas num mesmo barril). Então, para esse exemplo,
esse barril armazenará, pela ordem: docID; wordID de "comida";
hitlist de "comida"; wordID de "bebida" (observe que não
há necessidade de se repetir o docID); hitlist de "bebida"; null
wordID (para separar esse docID do seguinte); próximo docID que
contenha palavras que caiam nessa faixa de wordIDs; ....]
Esse esquema requer um pouco a mais de espaço de
armazenamento por causa dos docIDs duplicados, mas a diferença
é pequena para um número razoável de buckets e
economiza tempo e capacidade de processamento no estágio final
de indexação, realizado pelo sorter. Além disso,
em vez de armazenar os verdadeiros wordIDs, nós armazenamos cada
wordID como a diferença em relação ao menor wordID
que deva ser armazenado em um dado barril. Assim, podemos usar apenas
24 bits para as wordIDs nos barris não ordenados, deixando assim
8 bits para o comprimento da hit list.
[Nota do Tradutor: o índice direto permite recompor a totalidade
de um documento HTML; para tal, faz-se o seguinte: a partir da URL,
identifico o docID do documento que desejo recompor; vou ao primeiro
barril, localizo aquele docID e recupero todas as palavras (wordIDs) e
respectivas posições (hit list) que estejam armazenadas
nesse barril; repito o procedimento para todos os barris; ao final do
último barril, o texto estará inteiramente recomposto].
4.2.7. Indice invertido
O indice invertido compõe-se dos mesmos barris do indice direto,
exceto que eles são processados pelo sorter. Para cada wordID
válida, o lexicon contém um ponteiro para um barril que
armazena aquela wordID, o qual por sua vez aponta para uma lista de
docIDs, juntamente com as respectivas hit lists. Essa lista de docIDs,
chamada doclist, representa todas as ocorrências daquela palavra
em todos os documentos.
Uma questão importante é o critério de ordenamento
de docIDs na doclist. Uma solução simples seria
armazená-los por ordem crescente de docIDs; isso permitiria uma
rápida mesclagem (merging) de diferentes doclists, para o caso
de pesquisas com mais de uma palavra-chave. Uma outra
opção é armazenar docIDs de acordo com o
número de vezes que a palavra aparece em cada documento (ou
seja, o primeiro docID seria aquele em que aparece o maior
número de vezes, o segundo docID seria aquele em que a palavra
aparece o segundo maior número de vezes, etc); essa
opção tornaria mais simples as pesquisas com apenas uma
palavra-chave, e provavelmente as páginas de respostas mais
relevantes para pesquisas de múltiplas palavras apareceriam
perto do topo. Entretanto, nessa opção, o merging
é muito mais difícil; além disso, desenvolvimentos
futuros tornam-se muito mais complicados, pois qualquer
alteração na função de rankeamento
requereria uma completa reconstrução do índice.
Nós optamos por um compromisso entre essas duas
opções: mantemos dois conjuntos de barris invertidos; um
conjunto para hit lists que incluem hits no título ou nas
âncoras, e outro conjunto para todos os demais hits. Dessa forma,
nós checamos o primeiro conjunto de barris em primeiro lugar, e
se não houver matches suficientes dentro desses barris,
nós partimos para o outro conjunto.
4.3 Rastreando (crawling) a web
Operar um web crawler é uma tarefa desafiadora. Existem
questões problemáticas relativas a desempenho e
confiabilidade; mais importante, existem questões sociais.
Crawling é a mais frágil das aplicações,
pois envolve a interação com centenas de milhares de
servidores web e vários servidores de nome (name servers) que
estão além do nosso controle.
A fim de crescer ao nível de centenas de milhões de
páginas web, Google desenvolveu um sistema de crawling
distrubuído. Um único servidor de URL serve listas de
URLs para vários crawlers (nós tipicamente operamos
rodamos três). Ambos, servidor URL e crawlers, são
implementados em Python. Cada crawler mantém aproximadamente 30
conexões abertas ao mesmo tempo; isso é necessário
para recuperar web pages a um ritmo suficientemente rápido.
Operando a velocidade máxima, o sistema pode rastrear mais de
100 páginas por segundo usando quatro crawlers; isso equivale a
aproximadamente 600 K por segundo de dados.
Uma grande causa de preocupação é a consulta a DNS
(DNS lookup). Cada crawler mantém seu próprio cache de
DNS, a fim de evitar fazer um DNS lookup antes de recuperar cada
documento. Cada uma das centenas de conexões pode estar em
diversos estados: consultando DNS, conectando ao host, enviando
requisições, e recebendo respostas. Esses fatores tornam
o crawler um componente complexo do sistema.
O crawler utiliza IO assíncronos para gerenciar eventos, e um
número de filas de controle que monitoram o estado de cada
página pesquisada.
É fato que rodar um crawler que se conecta a mais de meio
milhão de servidores, e gera dezenas de milhões de linhas
de log, resulta em um número considerável de emails e
telefonemas. Por causa do enorme contingente de pessoas que está
se conectando online, sempre existem aquelas que não sabem o que
um crawler faz (já que é o primeiro crawler que elas
vêem). Quase que diariamente, nós recebemos uma mensagem
do tipo "Legal, vocês visitaram um grande número de
páginas do meu site. Vocês gostaram?". Muitas pessoas
desconhecem também a existência de protocolos de
exclusão de robots, e pensam que suas páginas
estão protegidas apenas porque colocaram um aviso como "Esta
página está protegida por direitos de autor e não
deve ser indexada", o que, desnecessário dizer, não
é entendido por crawlers. Ademais, por causa da enorme
quantidade de dados em jogo, coisas inesperadas acontecem. Por exemplo,
nosso sistema tentou rastrear um jogo online; isso resultou em
várias mensagens estranhas para os jogadores, no meio da
paretida. Esse problema específico foi fácil de se
resolver, mas somente depois que nós já tínhamos
baixado dezenas de milhões de páginas. Por causa da
imensa variedade de páginas e servidores, é virtualmente
impossível testar um crawler sem que o soltemos livremente em
uma grande porção da internet. Invariavelmente, existem
centenas de problemas obscuros que ocorrem em apenas uma página
da internet inteira e causam um crash no crawler ou, pior ainda, causam
um comportamento incorreto e imprevisível. Sistemas que acessam
grandes porções da internet precisam ser projetados para
ser muito robustos e devem ser cuidadosamente testados. Como é
certo que sistemas complexos como crawlers causarão problemas,
é necessário que uma parte dos recursos seja alocada para
ler emails e resolver problemas, à medida que surjam.
4.4 Indexando a Web
Interpretando a sintaxe de páginas (Parsing) - qualquer parser
que seja projetado para rodar na Web deve ser capaz de tratar uma gama
enorme de possíveis erros. Esses podem variar de pequenos erros
de datilografia em tags HTML até kilobytes de zeros no meio de
um tag, caracteres não-ASCII, aninhamentos de tags HTML em
centenas de níveis, e uma grande variedade de outros erros que
desafiam a imaginação de qualquer pessoa. Para
máximo desempenho, em vez de utilizar YACC para gerar um parser
CFG, nós utilizamos flex para gerar um analisador léxico,
que a seguir nós aprimoramos. Desenvolver esse parser, que roda
a velocidade razoável e é muito robusto, exigiu uma
grande quantidade de trabalho.
Após cada documento ser interpretado, ele é armazenado em
um número de barris. Cada palavra é convertida em uma
wordID, com a ajuda de uma tabela hash que reside em meória - o
lexicon. Novos termos que vão sendo adicionados à tabela
hash do lexicon são registrados em um arquivo. Após a
conversão das palavras em wordIDs, sua(s) ocorrência(s)
é(são) registradas em hit lists e são armazenadas
nos barris diretos (barris que armazenam o índice direto). A
maior dificuldade para implementar a paralelização na
fase de indexação é que o lexicon precisa ser
compartilhado. Em vez de compartilhar o lexicon, nós adotamos o
método de escrever um log com todas as palavras novas que
não constavam do lexicon básico, que continha 14
milhões de palavras. Assim, múltiplos indexadores podem
rodar em paralelo e, ao final, o pequeno arquivo de palavras novas pode
ser processada, por um indexador final.
Ordenamento (sorting). Para criar o índice invertido, o
sorter visita cada um dos barris diretos e os ordena por wordID, cria
um barril invertido apenas para palavras no título e nas
âncoras, e um barril invertido para o texto completo. Esse
processo é feito em um barril de cada vez, e por isso requer
pouco espaço de armazenamento temporário. Além
disso, nós paralelizamos essa fase de ordenamento, usando todas
as máquinas disponíveis para rodar a maior quantidade de
sorters possível, os quais podem processar diferentes trechos de
disco ao mesmo tempo. Como os barris não cabem na memória
principal, o sorter os divide em cestas, baseadas em wordIDs e docIDs,
que caibam na memória. O sorter, então, carrega cada
cesta na memória, ordena-a e grava o arquivo ordenado nos dois
barris invertidos.
4.5 Pesquisas (searching)
O objetivo das pesquisas é prover resultados com qualidade e
eficiência. Muitas das grandes search engines comerciais parecem
ter feito grande progresso em termos de eficiência. Por isso,
nós nos focamos mais na qualidade das pesquisas, embora
nós acreditemos que nossas soluções sejam
aplicáveis a volumes comerciais com um pouco de esforço.
O processo de pesquisa da Google funciona como mostrado na figura 4.
1. Interpretar os dados fornecidos pelo usuário (parse the
query).
2. Converter palavras em wordIDs.
3. Ir ao início da doclist no barril curto (apenas
títulos e âncoras) para cada uma das palavras.
4. Examinar as doclists até encontrar um documento que contenha
todas as palavras.
5. Computar o rank para cada um dos documentos.
6. Se estiver no barril curto e atingir o final de alguma doclist,
procurar o início da doclist no barril completo (todo o texto)
para cada palavra e retornar ao passo 4.
7. Se não estiver no final de alguma doclist, voltar para o
passo 4.
8. Ordenar os documentos por rank e retornar os que estejam entre os K
primeiros.
Figura 4. Como a Google processa as pesquisas
Para limitar o tempo de resposta, quando um certo número
(atualmente 40.000) de documentos é encontrado, o searcher
automaticamente vai para o passo 8. Isso significa que é
possível que resultados sub-ótimos sejam apresentados.
Estamos atualmente investigando outras maneiras de resolver esse
problema. No passado, nós ordenamos os hits por PageRank, o que
nos pareceu melhorar a situação.
4.5.1. O sistema de rankeamento
A Google mantém muito mais informação sobre os
documentos web do que outras search engines. Toda hitlist inclui
informação sobre posição, font e
capitalização. Além disso, levamos em
consideração hits que ocorram nos textos das
âncoras e o PageRank do documento. Combinar todas essas
informações em um ranking é difícil.
Nós projetamos nosso método de rankeamento de maneira tal
que nenhum fator tivesse demasiada influência.
Primeiro, consideremos o caso mais simples - uma pesquisa com uma
única palavra-chave. A fim de rankear um documento para tal
pesquisa, Google olha para a hit list do documento para a palavra
pesquisada. Google analisa cada hit separadamente, dividindo-os em
tipos (título, âncoras, URLs, texto em fonte grande, texto
em fonte pequena, etc), e atribui pesos diferentes a cada tipo. Os
pesos formam um vetor, indexado por tipos. A seguir cada contagem (ou
seja, cada ocorrência) é convertida em pesos de contagem.
Os pesos de contagem aumentam linearmente com as primeiras
ocorrências, mas rapidamente atingem um limite, de maneiras que
ocorrências a partir de um certo número são
descartadas. Nós tomamos então o produto escalar entre o
vetor de pesos de contagens e o vetor de pesos de tipos para computar
um score IR para o documento (Nota do tradutor: não há
definição de o que seja IR nesse contexto; o termo IR usualmente significa Information Retrieval). Finalmente, o score IR
é combinado com PageRank para dar um rank final ao documento.
Para uma pesquisa multi-palavras, o processo é mais complicado.
Dessa feita, múltiplas hit lists devem ser consultadas, em busca
de palavras que estejam próximas. Toda vez que um conjunto de
hits é encontrado, um índice de proximidade entre eles
é computado. O valor do índice depende da distância
entre os hits no documento (ou âncoras), mas é
classificado em apenas dez diferentes valores, variando desde um
casamento perfeito até um "muito distantes entre si". As
ocorrências são computadas levando-se em conta não
apenas para todos os tipos de hit (título, âncora, etc),
mas também a proximidade entre elas. Cada par tipo-proximidade
tem um peso-tipo-proximidade. As ocorrências são
convertidas em pesos de contagens e nós então tomamos o
produto escalar entre os pesos de contagens e os pesos-tipo-proximidade
para computar um score IR. [Nota do Tradutor: o documento original
não menciona, mas é evidente que o PageRank é
também levado em conta, para apresentação do
resultado final].
Todos esses números e matrizes podem ser exibidos juntamente com
os resultados das pesquisas, utilizando-se um modo de debug. Isso tem
sido muito útil para aprimorar o sistema de ranking.
4.5.2. Feedback
A função de ranking tem muitos parâmetros, como os
pesos-de-tipos e os pesos-tipo-proximidade. Estipular os melhores
valores para esses parâmetros requer um pouco de magia negra.
Para superar essa deficiência, nós nos baseamos em
feedback dos usuários. Alguns usuários podem manifestar
suas opiniões sobre os resultados que lhes são
apresentados; essas opiniões são armazenadas. Quando
qualquer modificação é introduzida no rankeamento,
podemos comparar os resultados através da análise das
opiniões dos usuários. Embora esteja longe da
perfeição, esse método nos dá alguma
idéia de como os usuários estão vendo as
mudanças que introduzimos.
|
|