Sobre o que o YouTube está falando

imagem

No início do aprendizado de máquina, a maioria das soluções parecia muito estranha, isolada e incomum. Hoje, muitos algoritmos de ML já estão alinhados em um familiar para um conjunto de estruturas e kits de ferramentas para programadores com os quais você pode trabalhar sem entrar nos detalhes de sua implementação.
A propósito, sou contra uma abordagem tão superficial, mas gostaria de mostrar aos meus colegas que esse setor está avançando aos trancos e barrancos e não há nada complicado para aplicar suas realizações em projetos de produção.

Como exemplo, mostrarei como você pode ajudar o usuário a encontrar o material de vídeo certo entre centenas de outros em nosso serviço de fluxo de trabalho.

No meu projeto, os usuários criam e compartilham centenas de materiais diferentes: texto, fotos, vídeos, artigos, documentos em vários formatos.

A pesquisa de documentos parece bastante simples. Mas o que fazer com a pesquisa de conteúdo multimídia? Para um serviço completo ao usuário, você deve obrigar a preencher uma descrição, dar um nome ao vídeo ou à imagem, várias tags não serão prejudicadas. Infelizmente, nem todo mundo quer gastar tempo com essas melhorias de conteúdo. Normalmente, o usuário envia um link para o youtube, informa que este é um novo vídeo e clica em salvar. O que um serviço pode fazer com esse conteúdo "cinza"? A primeira ideia é perguntar ao YouTube? Mas o YouTube também é preenchido com usuários (geralmente o mesmo usuário). Geralmente, o material de vídeo pode não ser do serviço do YouTube.
Por isso, tive a ideia de ensinar nosso serviço a "ouvir" o vídeo e a "entender" o que se trata.

Admito que essa ideia não é nova, mas hoje para sua implementação não é necessário ter uma equipe de dez cientistas de dados, apenas dois dias e um pouco de recursos de hardware.

Declaração do problema


Nosso microsserviço, vamos chamá-lo de Summarizer , deve:

  • Baixe o vídeo do serviço de mídia;
  • Extrair faixa de áudio;
  • Ouça a faixa de áudio, na verdade Fala para texto;
  • Encontre 20 palavras-chave;
  • Selecione uma frase do texto, o que poderia maximizar a essência do vídeo;
  • Envie todos os resultados para o serviço de conteúdo;

Confiaremos na implementação do Python , para que você não precise lidar com a integração com soluções de ML prontas.

Etapa 1: áudio para texto.

Primeiro, instale todos os componentes necessários.

pip3 install wave numpy tensorflow youtube_dl ffmpeg-python deepspeech nltk networkx brew install ffmpeg wget 

Em seguida, baixe e descompacte o modelo treinado para a solução Speech to text da Mozilla - Deepspeech.

 mkdir /Users/Volodymyr/Projects/deepspeech/ cd /Users/Volodymyr/Projects/deepspeech/ wget https://github.com/mozilla/DeepSpeech/releases/download/v0.3.0/deepspeech-0.3.0-models.tar.gz tar zxvf deepspeech-0.3.0-models.tar.gz 

A equipe Mozilla criou e treinou uma solução bastante boa que, usando o TensorFlow, pode transformar longos clipes de áudio em grandes pedaços de texto com alta qualidade. O TensorFlow também permite que você trabalhe imediatamente na CPU e na GPU.

Nosso código começará baixando o conteúdo. A maravilhosa biblioteca youtube-dl , que possui um pós-processador interno capaz de converter o vídeo no formato necessário, o ajudará nisso. Infelizmente, o código pós-processador é um pouco limitado, não sabe como reamostrar, por isso vamos ajudá-lo.
Para a entrada Deepspeech, você precisa enviar um arquivo de áudio com uma faixa mono e uma amostra de 16K. Para fazer isso, precisamos reprocessar nosso arquivo recebido.

 _ = ffmpeg.input(youtube_id + '.wav').output(output_file_name, ac=1, t=crop_time, ar='16k').overwrite_output().run(capture_stdout=False) 

Na mesma operação, também podemos limitar a duração do nosso arquivo, passando um parâmetro adicional "t".

Faça o download do modelo deepspeech.

 deepspeech = Model(args.model, N_FEATURES, N_CONTEXT, args.alphabet, BEAM_WIDTH) 

Usando a biblioteca wave, extraímos quadros no formato np.array e os transferimos para a entrada da biblioteca deepspeech.

 fin = wave.open(file_name, 'rb') framerate_sample = fin.getframerate() if framerate_sample != 16000: print('Warning: original sample rate ({}) is different than 16kHz. Resampling might produce erratic speech recognition.'.format(framerate_sample), file=sys.stderr) fin.close() return else: audio = np.frombuffer(fin.readframes(fin.getnframes()), np.int16) audio_length = fin.getnframes() * (1/16000) fin.close() print('Running inference.', file=sys.stderr) inference_start = timer() result = deepspeech.stt(audio, framerate_sample) 

Depois de um tempo, proporcional aos seus recursos de hardware, você receberá um texto.

Etapa 2: Encontrar o "significado"


Para procurar palavras que descrevam o texto resultante, usarei o método gráfico. Este método é baseado na distância entre seqüências. Primeiro encontramos todas as palavras “únicas”, imagine que esses são os vértices do nosso gráfico. Depois de percorrer o texto com uma “janela” de um determinado comprimento, encontramos a distância entre as palavras, elas serão as bordas da nossa gaff. Os vértices adicionados ao gráfico podem ser limitados por filtros de sintaxe que selecionam apenas unidades lexicais de uma determinada parte da fala. Por exemplo, você pode considerar apenas substantivos e verbos a serem adicionados ao gráfico. Portanto, construiremos arestas potenciais com base apenas em relacionamentos que podem ser estabelecidos entre substantivos e verbos.

A pontuação associada a cada vértice é definida como um valor inicial de 1 e o algoritmo de classificação é iniciado. O algoritmo de classificação é um "voto" ou "recomendação". Quando um vértice é conectado a outro, ele “vota” nesse vértice (conectado). Quanto maior o número de votos para um pico, maior a importância desse pico. Além disso, a importância do topo da votação determina a importância da votação em si, e essas informações também são levadas em consideração pelo modelo de classificação. Portanto, a pontuação associada ao topo é determinada com base nos votos expressos e na classificação dos picos que dão esses votos.

Suponha que tenhamos um gráfico G = (V, E) descrito pelos vértices V e arestas E. Para um dado vértice V, deve haver um conjunto de vértices E que estão conectados a ele. Para cada vértice Vi, há vértices In (Vi) associados a ele e vértices Out (Vi) aos quais o vértice Vi está associado. Assim, o peso do vértice Vi pode ser representado pela fórmula.

S big(Vi big)= big(1d big)+d sumj inIn(Vi) frac1 midOut(Vj) midS big(Vj big)



Onde d é o fator de atenuação / supressão, assumindo um valor de 1 a 0.

O algoritmo deve iterar o gráfico várias vezes para obter estimativas aproximadas.
Depois de obter uma estimativa aproximada para cada vértice no gráfico, os vértices são classificados em ordem decrescente. Os vértices que aparecem no topo da lista serão nossas palavras-chave desejadas.

A sentença mais relevante no texto é encontrada ao encontrar a média da adição de estimativas de todas as palavras na sentença. Ou seja, somamos todas as estimativas e dividimos pelo número de palavras na frase.

 iMac:YoutubeSummarizer $ cd /Users/Volodymyr/Projects/YoutubeSummarizer ; env "PYTHONIOENCODING=UTF-8" "PYTHONUNBUFFERED=1" /usr/local/bin/python3 /Users/Volodymyr/.vscode/extensions/ms-python.python-2018.11.0/pythonFiles/experimental/ptvsd_launcher.py --default --client --host localhost --port 53730 /Users/Volodymyr/Projects/YoutubeSummarizer/summarizer.py --youtube-id yA-FCxFQNHg --model /Users/Volodymyr/Projects/deepspeech/models/output_graph.pb --alphabet /Users/Volodymyr/Projects/deepspeech/models/alphabet.txt --lm /Users/Volodymyr/Projects/deepspeech/models/lm.binary --trie /Users/Volodymyr/Projects/deepspeech/models/trie --crop-time 900 Done downloading, now converting ... ffmpeg version 4.1 Copyright (c) 2000-2018 the FFmpeg developers built with Apple LLVM version 10.0.0 (clang-1000.11.45.5) configuration: --prefix=/usr/local/Cellar/ffmpeg/4.1 --enable-shared --enable-pthreads --enable-version3 --enable-hardcoded-tables --enable-avresample --cc=clang --host-cflags= --host-ldflags= --enable-ffplay --enable-gpl --enable-libmp3lame --enable-libopus --enable-libsnappy --enable-libtheora --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libx265 --enable-libxvid --enable-lzma --enable-opencl --enable-videotoolbox libavutil 56. 22.100 / 56. 22.100 libavcodec 58. 35.100 / 58. 35.100 libavformat 58. 20.100 / 58. 20.100 libavdevice 58. 5.100 / 58. 5.100 libavfilter 7. 40.101 / 7. 40.101 libavresample 4. 0. 0 / 4. 0. 0 libswscale 5. 3.100 / 5. 3.100 libswresample 3. 3.100 / 3. 3.100 libpostproc 55. 3.100 / 55. 3.100 Guessed Channel Layout for Input Stream #0.0 : stereo Input #0, wav, from 'yA-FCxFQNHg.wav': Metadata: encoder : Lavf58.20.100 Duration: 00:17:27.06, bitrate: 1536 kb/s Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 48000 Hz, stereo, s16, 1536 kb/s Stream mapping: Stream #0:0 -> #0:0 (pcm_s16le (native) -> pcm_s16le (native)) Press [q] to stop, [?] for help Output #0, wav, to 'result-yA-FCxFQNHg.wav': Metadata: ISFT : Lavf58.20.100 Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 16000 Hz, mono, s16, 256 kb/s Metadata: encoder : Lavc58.35.100 pcm_s16le size= 28125kB time=00:15:00.00 bitrate= 256.0kbits/s speed=1.02e+03x video:0kB audio:28125kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.000271% Loading model from file /Users/Volodymyr/Projects/deepspeech/models/output_graph.pb TensorFlow: v1.11.0-9-g97d851f04e DeepSpeech: unknown Warning: reading entire model file into memory. Transform model file into an mmapped graph to reduce heap usage. 2018-12-14 17:42:03.121170: I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA Loaded model in 0.5s. Loading language model from files /Users/Volodymyr/Projects/deepspeech/models/lm.binary /Users/Volodymyr/Projects/deepspeech/models/trie Loaded language model in 3.17s. Running inference. Building top 20 keywords... {'communicate', 'government', 'repetition', 'terrorism', 'technology', 'thinteeneighty', 'incentive', 'ponsibility', 'experience', 'upsetting', 'democracy', 'infection', 'difference', 'evidesrisia', 'legislature', 'metriamatrei', 'believing', 'administration', 'antagethetruth', 'information', 'conspiracy'} Building summary sentence... intellectually antagethetruth administration thinteeneighty understanding metriamatrei shareholders evidesrisia recognizing ponsibility communicate information legislature abaddoryis technology difference conspiracy repetition experience government protecting categories mankyuses democracy campaigns primarily attackers terrorism believing happening infection seriously incentive upsetting testified fortunate questions president companies prominent actually platform massacre powerful building poblanas thinking supposed accounts murdered function unsolved perverse recently fighting opposite motional election children watching traction speaking measured nineteen repeated coverage imagined positive designed together countess greatest fourteen attacks publish brought through explain russian opinion winking somehow welcome trithis problem looking college gaining feoryhe talking ighting believe happens connect further working ational mistake diverse between ferring Inference took 76.729s for 900.000s audio file. 

Sumário


As idéias que vêm à sua mente podem ser realizadas muito mais rapidamente hoje do que há três ou quatro anos atrás. Experimente, experimente! Eu acho que a inteligência artificial é principalmente a inteligência dos engenheiros que trabalham com ela.

O código está disponível no meu repositório Github .

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


All Articles