Subindo o CRF Até a Busca Bugar
Por Brenner Cruvinel • 6 minutos de leitura
a pergunta da madrugada anterior era simples de fazer e eu demorei pra fazer. o app tem o jpeg de cada carta em cache pra exibir. o .nest não precisa ser bonito, precisa responder qual carta é. então o crf, o ajuste de qualidade do codec, pode subir até o vetor bugar, e o vetor buga bem depois do olho. se isso fosse verdade, valia até pensar em duas camadas: um thumb dentro do nest pra busca, e a carta inteira sob demanda quando o app precisar mostrar.
eu tinha um jeito de medir isso, ou achava que tinha. o gate de qualidade do nest tem dois lados: uma métrica visual, que compara o frame decodificado com a fonte, e a drift do vetor, que mede o quanto o vetor do clip se move entre a imagem original e a decodificada. a ideia do drift é que uma imagem pode parecer boa e ainda assim ter mudado de lugar no espaço de busca. eu tinha confiança nessa métrica. era a minha, eu tinha insistido nela no plano, e o motivo era bom: na dermatoscopia ela tinha pego um caso em que a imagem passava no olho e a busca por texto clínico caía pela metade.
o gate reprovou a ladder inteira
tirei o lado visual do gate e deixei só o drift, com o floor que o nest usa desde a dermatoscopia. mandei o crf subir numa ladder de crf 40 a 60. o gate reprovou a ladder inteira, inclusive o primeiro, e caiu no mais conservador da ladder porque não tinha pra onde ir. o drift já estava abaixo do floor no crf 40 e só piorava. e a métrica visual, que eu tinha tirado do gate mas continuava calculando, contava a mesma história por outro ângulo: a partir do crf cinquenta ela dava valor negativo em algumas cartas, coisa que eu nem sabia que ela fazia.
o arquivo que o gate entregou, no crf 40, o mais baixo da ladder, ficou perto de um giga, quatro vezes menor que a fonte. já era menor que o build recomendado, e o gate tinha reprovado ele também, só não tinha pra onde cair.
pela lógica do gate, nenhum desses arquivos servia. buildei um no crf cinquenta mesmo assim, sem gate, só pra ver o tamanho. meio giga. sete vezes e meia menor que a fonte, e as cartas viraram borrão, o texto de regra ilegível, a arte reconhecível só de longe. um arquivo que eu não mostraria pra ninguém.
aí rodei a métrica que interessa mesmo, e que eu não tinha rodado antes por preguiça de montar: a busca por nome. cem buscas do tipo "a arte da carta tal", nos cinco arquivos que eu tinha do corpus completo, do sem perda de 3,6 GB até o borrão de meio giga. a primeira rodada deu zero acerto em dois dos cinco arquivos, o sem perda e o recomendado, e por um minuto eu achei que tinha quebrado a busca. era o bench: ele casava o resultado pelo número de ordem da carta no stream, e os dois arquivos com ordenação por similaridade têm outra ordem. o nest tem um id de conteúdo por item justamente pra isso, e quando o bench passou a casar por ele os cinco arquivos voltaram a responder.
e o acerto ficou dentro do ruído em todos. o de meio giga acha a carta certa tão bem quanto o de 1,3 GB, e os dois ficam dentro do ruído do sem perda.
a busca sobrevive a muito mais compressão do que o olho
fiquei com isso na tela um tempo. drift de cosseno mede se o vetor se moveu. busca mede se o vetor ainda acha. eu estava usando a primeira como se fosse a segunda, e ela teria vetado um arquivo que funciona. o vetor se move, sim, e continua mais perto da carta certa do que de qualquer outra. a distância que ele anda não importa se os vizinhos dele não mudam. um gate que preste pra esse uso precisa de hit@k como floor, não de cosseno.
isso virou um perfil no nest, retrieval-only, que deixa escrito no manifest que o arquivo serve busca e nunca exibição. e o avif, que no benchmark tinha ficado uns 12% menor que o av1 na mesma qualidade, confirmou no corpus inteiro: 13% menor que o build recomendado. é o candidato a virar o backend padrão pra stills, e eu ainda não decidi, porque o avif custa quatro a dez vezes mais tempo de build pra embedar.
tem uma terceira métrica que eu rodei junto e que não vale nada, e vale dizer por quê. a identidade: dar a própria imagem como busca e ver se ela acha ela mesma. deu cem por cento em todos os arquivos, até no borrão. parece ótimo e não diz nada, porque a busca é a imagem que gerou o frame, e o controle sem compressão também dá cem. serve só pra provar que o codec não destruiu o dado. eu deixei ela no bench pra ninguém confundir estabilidade de pipeline com utilidade, que foi exatamente a confusão que eu fiz com o drift.
a métrica é fraca e eu sei. são cem buscas com um modelo que acerta pouco nesse corpus, o clip, que só olha a arte. "não caiu" quer dizer "não consegui medir queda", não "é igual". e o wemm, que lê o nome impresso na carta e acerta nove em dez, pode sofrer muito mais com o borrão do que o clip, porque o que ele lê é exatamente o que o crf destrói primeiro. não medi. é a próxima coisa, junto com o corpus de reprints inteiro, que é onde o inter tem o que prever.
o que me ficou dessa semana foi menos sobre compressão e mais sobre o que eu escolho medir. eu tinha uma métrica que eu mesmo desenhei, que parecia rigorosa, e ela respondia uma pergunta que eu não estava fazendo. e antes de publicar qualquer um desses números, eu queria validar cada um contra o disco, porque relatório escrito de madrugada erra.