O que você é Como distinguimos a paródia da humana - e até ganhamos

Recentemente, foi realizado o Desafio de Antiespofamento por Voz ID R&D , cuja principal tarefa era criar um algoritmo capaz de distinguir uma voz humana de um registro sintetizado (spoof). Sou Pesquisador ML no Dasha AI e trabalho muito em reconhecimento de fala, então decidi participar. Juntamente com a equipe, conquistamos o primeiro lugar. Sob o corte, vou falar sobre novas abordagens legais para o processamento de som, bem como sobre as dificuldades e esquisitices que tivemos que enfrentar.

98 pessoas participaram da competição - são poucas as pessoas porque essa é uma competição para processamento de som, em uma plataforma russa e até em uma docker. Eu estava em uma equipe com Dmitry Danevsky, mestre do Kaggle, com quem nos conhecemos e concordamos em participar enquanto discutíamos abordagens em outra competição.

Desafio


Recebemos 5 GB de arquivos de áudio, divididos em classes falsas / humanas, e tivemos que prever a probabilidade da classe, envolvê-la em uma janela de encaixe e enviá-la ao servidor. A solução deveria funcionar em 30 minutos e pesar menos de 100 MB. De acordo com informações oficiais, era necessário distinguir entre a voz de uma pessoa e a gerada automaticamente - embora pessoalmente me parecesse que a classe de spoof também incluía casos em que o som era gerado segurando o alto-falante no microfone (como os atacantes roubam uma gravação da voz de outra pessoa para identificação).

A métrica era EER :



Pegamos o primeiro código que veio da rede, porque o código dos organizadores parecia sobrecarregado.

Concorrência


Os organizadores forneceram a linha de base e, ao mesmo tempo, o principal enigma da competição. Era simples: pegamos arquivos de áudio, contamos espectrogramas de giz , treinamos o MobileNetV2 e nos encontramos em algum lugar em torno do 12º lugar ou menos. Por causa disso, muitos pensariam que uma dúzia de pessoas participasse da competição, mas não foi assim. Durante toda a primeira etapa da competição, nossa equipe não conseguiu quebrar essa linha de base. O código idealmente idêntico deu o resultado muito pior e quaisquer melhorias (como substituir por grades mais pesadas e previsões de OOF ) ajudaram, mas não o aproximaram da linha de base.

E então o inesperado aconteceu: cerca de uma semana antes do final da competição, verificou-se que a implementação da contagem das métricas dos organizadores continha um erro e dependia da ordem das previsões. Na mesma época, constatou-se que, nos contêineres do docker, os organizadores não desligaram a Internet com gentileza; muitos fizeram o download da amostra de teste. Em seguida, o concurso foi congelado por 4 dias, corrigiu a métrica, atualizou os dados, desligou a Internet e recomeçou por mais 2 semanas. Após a recontagem, estávamos no sétimo lugar com uma de nossas primeiras inscrições. Isso serviu como uma forte motivação para continuar participando da competição.

Falando em modelo


Usamos uma grade de convolução do tipo resnet treinada sobre espectrogramas de giz.

  1. No total, havia 5 desses blocos.Depois de cada bloco, fizemos uma supervisão profunda e aumentamos o número de filtros uma vez e meia.
  2. Durante a competição, passamos de uma classificação binária para uma multi-classe, a fim de utilizar com mais eficiência a técnica de mixagem, na qual misturamos dois sons e resumimos seus rótulos de classe. Além disso, após essa transição, conseguimos aumentar artificialmente a probabilidade da classe de falsificação, multiplicando-a por 1,3. Isso nos ajudou, pois havia uma suposição de que o saldo de classes na amostra de teste pode ser diferente da amostra de treinamento e, portanto, melhoramos a qualidade dos modelos.
  3. Modelos dobrados foram treinados e as previsões de vários modelos foram calculadas como média.
  4. A técnica de codificação de frequência também foi útil. A linha inferior é: as convoluções 2D são invariantes à posição e, nos espectrogramas, os valores ao longo do eixo vertical têm significados físicos muito diferentes; portanto, gostaríamos de transferir essas informações para o modelo. Para isso, concatenamos o espectrograma e a matriz, consistindo em números em um segmento de -1 a 1 de baixo para cima.

    Para maior clareza, darei o código:

    n, d, h, w = x.size()         vertical = torch.linspace(-1, 1, h).view(1, 1, -1, 1)         vertical = vertical.repeat(n, 1, 1, w)         x = torch.cat([x, vertical], dim=1) 
  5. Treinamos tudo isso, inclusive em dados pseudo-rotulados da amostra de teste vazada do primeiro estágio.

Validação


Desde o início da competição, todos os participantes foram atormentados pela pergunta: por que a validação local fornece EER 0,01 e menor, e leaderboard 0,1 e não se correlaciona particularmente? Tivemos duas hipóteses: ou havia duplicatas nos dados ou os dados de treinamento foram coletados em um conjunto de palestrantes e dados de teste em outro.

A verdade estava em algum lugar no meio. Nos dados de treinamento, cerca de 5% dos dados acabaram sendo duplicados, e isso conta apenas duplicatas completas dos hashes (a propósito, também pode conter recortes diferentes do mesmo arquivo, mas não é tão fácil de verificar - é por isso que não fizemos).

Para testar a segunda hipótese, treinamos uma grade de identificação de alto-falante, recebemos combinações para cada alto-falante, agrupamos tudo com k-médias e as estratificamos. Nomeadamente, treinamos em palestrantes de um cluster e palestrantes previstos de outros. Este método de validação já começou a se correlacionar com a tabela de classificação, embora tenha mostrado uma pontuação 3-4 vezes melhor. Como alternativa, tentamos validar apenas as previsões nas quais o modelo era pelo menos um pouco inseguro, ou seja, a diferença entre a previsão e o rótulo da classe era> 10 ** - 4 (0,0001), mas esse esquema não trouxe resultados.

E o que não deu certo?


Na Internet, basta encontrar milhares de horas de fala humana. Além disso, uma competição semelhante já foi realizada há vários anos. Portanto, parecia uma idéia óbvia baixar muitos dados (baixamos ~ 300 GB) e treinar o classificador nisso. Em alguns casos, o treinamento nesses dados provou ser um pouco se ensinássemos dados adicionais e de treinamento antes de atingirmos um platô e depois treinássemos apenas os dados de treinamento. Mas com esse esquema, o modelo convergiu em cerca de 2 dias, o que significou 10 dias para todas as dobras. Portanto, abandonamos essa ideia.

Além disso, muitos participantes notaram uma correlação entre o tamanho do arquivo e a turma; essa correlação não foi observada na amostra de teste. Grades de imagem comuns como resnext, nasnet-mobile, mobileNetV3 não se mostraram muito bem.

Posfácio


Não foi fácil e às vezes estranho, mas ainda assim tivemos uma experiência interessante e saímos por cima. Por tentativa e erro, percebi quais abordagens estão funcionando e quais não são muito boas. Agora vou usar essas informações conosco ao processar o som. Eu trabalho duro para levar a IA de conversação a um nível indistinguível do humano e, portanto, sempre na busca de tarefas e chips interessantes. Espero que você também tenha aprendido algo novo.

Bem, finalmente, eu publico o nosso código .

Source: https://habr.com/ru/post/pt475480/


All Articles