Gerando Áudio com GANs

Nota: uma versão em inglês desse artigo pode ser encontrada em https://medium.com/@rafalencar/audio-generation-with-gans-428bc2de5a89

Hoje em dia uma das grandes aplicações do Deep Learning são os Modelos Generativos, que usando exemplos de dados conseguem agrupar suas principais características e criar a partir delas novos dados com os mesmo aspectos dos originais. Com isso em mente veio a motivação, o que esses modelos conseguem gerar usando áudios como exemplo?


Machine Learning e Áudio

Quando falamos sobre machine learning para áudio, a primeira coisa que pensamos é em reconhecimento de voz, o famoso Processamento de Linguagem Natural. Podemos ver ele funcionando no nosso dia a dia com as assistentes pessoais de nossos smartphones, as grandes Siri, Cortana e Alexa. Também temos outras diversas aplicações saindo do campo da fala e indo para processamento de áudio no geral, como a segmentação, capaz de identificar e separar os diferentes instrumentos utilizados em uma música. Mas, como dito anteriormente, nosso foco neste artigo será na geração de novos sons.


Criando Sons com GANs

GANs

Neste artigo traremos um pequeno experimento com áudio aplicando uma ferramenta muito utilizada em imagens, as Generative Adversarial Networks (GANs). As GANs operam com o treino de dois modelos:

  • Gerador: recebe um ruído e transforma em um áudio;
  • Discriminador: recebe um áudio e identifica se ele é real ou não;

A cada época de treinamento, temos como se fosse uma rodada de um jogo entre esses dois modelos. O discriminador, na sua vez, treina seus pesos para poder distinguir melhor áudios falsos dos reais. Na vez do gerador, ele também treina seus pesos, mas para enganar o discriminador e fazer ele acreditar que os áudios gerados são reais. A imagem abaixo ilustra um exemplo de GAN:

Modelo de uma GAN com Imagens

Arquitetura

A arquitetura das redes usou como base as Deep Convolutional GANs (DCGANs). Tanto o gerador quanto o discriminador possuem 4 camadas de convolução em uma dimensão, seguidas por camadas de ativação ReLU e uma camada de totalmente conectada com a ativação LeakyReLU. Além disso temos camadas de Batch Normalization e Dropout entre as convoluções.

A maior diferença entre uma rede e outra são as entradas e saídas, com o gerador com 500 entradas de ruído e saída igual à 64000 (16 kHz x 4 segundos), e o discriminador com 64000 entradas referentes ao som e uma saída entre 0 e 1, sendo o primeiro quando o áudio é falso. Para mais detalhes sobre a implementação, temos código foi feito em Python com uso do TensorFlow e Keras, que pode ser encontrado no link abaixo:

Dataset

Para treinar estas redes, o database utilizado foi o Freesound-Audio-Tagging, com mais de 10 mil áudios. Nele temos arquivos com mono áudios modulados por código de pulsos de 16 bits (PCM), taxa de amostragem de 44.1 kHz e duração variada. Além disso, eles estão separados em 41 categorias diferentes incluindo Trompete, Aplausos, Violino, dentre muitas outras. Abaixo temos um dos áudios deste dataset, o som de um Saxofone:

Exemplo de um audio de Saxofone

Cada categoria possui entre 94 e 300 exemplos. As duas principais categorias usadas para este experimento foram o Saxofone e o Violino, já que possuem mais amostras que foram manualmente classificadas. Para padronizar os áudios, todos foram reamostrados de 44.1 para 16 kHz, reduzidos para trechos de 4 segundos e normalizados.


Resultados

O treino foi feito durante 50 épocas, o que durou em torno de 4 minutos. Abaixo podemos ver as curvas das perdas de cada uma das duas redes ao longo das épocas:

Curvas de perdas do Discriminador, em azul, e do Gerador, em vermelho

Abaixo temos dois áudios gerado a partir de exemplos de Violino da primeira e última época respectivamente:

Áudio gerado na primera época
Áudio gerado na última época

Os sons gerados parecem mais com uma gaita de fole do que com um violino. Isso quer dizer que o experimento falhou? Não necessariamente. Se você reparar bem, é possível notar que do primeiro para o segundo áudio temos uma redução de ruído, dando a impressão que ele foi "limpo". Agora vamos tentar entender o porque os sons gerados diferem tanto dos originais analisando os gráficos desses áudios:

Exemplos de áudios originais
Exemplos de áudios gerados

Quando colocamos as imagens em comparação, percebemos que elas têm muitas semelhanças e fica difícil analizar o que uma tem de diferente da outra. Além dos momentos de “silêncio” que alguns áudios originais têm e a rede não foi capaz de reproduzir, a maior diferença está quando damos um zoom neste gráfico.

Vamos agora usar um autoencoder, que irá receber um áudio original, comprimi-lo e depois tentar recriar o áudio original, usando as mesmas redes das GANs. Abaixo temos um zoom que mostra que as ondas originais são com formas bem melhor determinadas do que as geradas. Esse formato da onda é o que define o timbre e é o que diferencia os sons de cada fonte sonora (instrumentos musicais por exemplo). Ou seja, para melhorar o modelo, devem ser adicionadas camadas que corrijam esses formatos de onda.

Áudio original à esquerda e áudio recriado à direita

Conclusão

Este foi um primeiro experimento sobre geração de áudio com GANs e serviu para descobrir o que essa ferramenta pode fazer com áudios e explorar os meios de otimizá-la. Os próximos passos são aprimorar as redes e suas arquiteturas para tornar essas ondas em áudios reais. Poderíamos testar o uso de redes neurais recorrentes (RNN) ou também aplicar técnicas de análise de frequência como transformadas de Fourier para pré-processamento. Cenas para os próximos artigos.