Фон

В машинном обучении инженерам приходится иметь дело с различными данными, начиная от числовых, категориальных, изображений, видео, речи и т. д. В этой статье основное внимание будет уделено аудиоданным, используемым в таких действиях, как распознавание речи, преобразование речи в текст, преобразование текста в - речь, звуковая классификация и т. д. Действия, связанные с этими данными, включают, но не ограничиваются:

  • захват аудио
  • сохранение захваченного аудио
  • воспроизведение сохраненного аудио
  • объединение нескольких аудиофайлов
  • разделение аудио на несколько сегментов
  • просмотр различных метаданных
  • преобразование данных (например, из одной частоты кадров в другую)
  • устранение тишины
  • инженерные функции (такие как построение сигналов, спектрограмм и т. д.)
  • строительные модели
  • делать прогнозы

Мы рассмотрим их с примерами кода и полными примерами.

Захват аудио

Для этой цели можно использовать различные пакеты. Здесь мы будем использовать пакет SpeechRecognition.

import speech_recognition as sr
r = sr.Recognizer()
with sr.Microphone() as source: 
    r.adjust_for_ambient_noise(source) 
    print(“Please say something: \n”) 
    audio = r.listen(source) 
    fname = input(“Please enter file name to save recording to: \n”) 
    with open(fname+”.wav”, “wb”) as f: 
        f.write(audio.get_wav_data()) 
        print(“Recorded successfully\n”)

Сохранение записанного аудио

Мы уже видели сохранение аудио в виде файла WAV выше. Существуют различные форматы

with open(fname+".wav", "wb") as f: 
    f.write(audio.get_wav_data())

для аудиофайлов. Несколько распространенных: MP3, WAV, AAC и т. д. Здесь — хорошая статья с их описанием. Существуют различные пакеты и методы для этих форматов.

Воспроизведение сохраненного аудио

Для этого мы будем использовать пакет pydub. Здесь мы читаем файл WAV и проигрываем его.

from pydub import AudioSegment
from pydub.playback import play  

playaudio = AudioSegment.from_file("1.wav", format="WAV")
play(playaudio)

Объединение нескольких аудиофайлов

Это можно сделать с помощью пакета AudioSegments и pydub, которые мы использовали выше. Это также можно сделать с помощью пакета wave, который мы покажем здесь.

import wave

infiles = ["1.wav", "2.wav"]
outfile = "out.wav"

data= []
for infile in infiles:
    w = wave.open(infile, 'rb')
    data.append( [w.getparams(), w.readframes(w.getnframes())] )
    w.close()

output = wave.open(outfile, 'wb')
output.setparams(data[0][0])
output.writeframes(data[0][1])
output.writeframes(data[1][1])
output.close()

Разделение на несколько сегментов

Здесь мы разделяем старую песню на новую, время начала и окончания которой в миллисекундах определяется первым и вторым параметрами соответственно.

from pydub import AudioSegment
import sys

newAudio = AudioSegment.from_wav("oldSong.wav")
newAudio = newAudio[int(sys.argv[1]):int(sys.argv[2])]
newAudio.export('newSong.wav', format="wav")

Метаданные

Вы можете проверить различные атрибуты метаданных как:

import wave
import sys

wf = wave.open(sys.argv[1], 'rb')
print (input, "#channels = ", wf.getnchannels(), "#frames = ", wf.getnframes(), "sample width = ", wf.getsampwidth(), "sample rate = ", wf.getframerate())

Вы можете конвертировать файлы с одним значением атрибута метаданных в другое, используя pydub и связанные с ним методы. Следующий фрагмент кода изменяет частоту кадров с 44 100 на 48 000.

from pydub import AudioSegment as am
import sys

sound = am.from_file(sys.argv[1], format='wav', frame_rate=44100)
sound = sound.set_frame_rate(48000)
sound.export(sys.argv[2], format='wav')

Удаление тишины

Иногда в аудиофайлах есть долгое молчание, которое не может быть обработано с помощью разработки функций и построения модели, которые мы рассмотрим далее. Вот некоторый код, который удаляет такую ​​тишину, используя метод распознавания голосовой активации (VAD).

Разработка функций

Файлы WAV уже содержат сигнал. Здесь мы увидим, как использовать TensorFlow и Keras для чтения ряда таких файлов из папки, разделения их на наборы для обучения и проверки, изменения формы и передачи их в конвейер машинного обучения.

import tensorflow as tf
from keras import utils

train_ds, val_ds = utils.audio_dataset_from_directory(
    directory='audio_samples',
    batch_size=64,
    validation_split=0.2,
    seed=0,
    output_sequence_length=16000,
    subset='both')

Следующий код получает спектрограмму из сигнала в TensorFlow и выполняет дальнейшие обновления по конвейеру машинного обучения.

import tensorflow as tf

def get_spectrogram(waveform):
  # Convert the waveform to a spectrogram via an STFT.
  spectrogram = tf.signal.stft(
      waveform, frame_length=255, frame_step=128)
  # Obtain the magnitude of the STFT.
  spectrogram = tf.abs(spectrogram)
  # Add a `channels` dimension, so that the spectrogram can be used
  # as image-like input data with convolution layers (which expect
  # shape (`batch_size`, `height`, `width`, `channels`).
  spectrogram = spectrogram[..., tf.newaxis]
  return spectrogram

def make_spec_ds(ds):
  return ds.map(
      map_func=lambda audio,label: (get_spectrogram(audio), label),
      num_parallel_calls=tf.data.AUTOTUNE)

train_spectrogram_ds = make_spec_ds(train_ds)
val_spectrogram_ds = make_spec_ds(val_ds)

Построение моделей

Мы можем использовать различные модели в зависимости от наших требований. Есть некоторые модели преобразования речи в текст, такие как шепот и wave2vec2. Есть некоторые модели на основе фонем, такие как wave2vec2phoneme. Мы можем напрямую использовать различные предварительно обученные модели. Мы можем использовать предварительно обученные модели для некоторого трансферного обучения и тонко настраивать их с нашими обучающими данными, которые не обязательно должны быть большими. Мы также можем построить и обучить нашу модель с нуля. Здесь мы будем использовать сверточную нейронную сеть (CNN) в TensorFlow, построенную и обученную с нуля.

# Instantiate the `tf.keras.layers.Normalization` layer.
norm_layer = layers.Normalization()
# Fit the state of the layer to the spectrograms
# with `Normalization.adapt`.
norm_layer.adapt(data=train_spectrogram_ds.map(map_func=lambda spec, label: spec))

model = models.Sequential([
    layers.Input(shape=input_shape),
    # Downsample the input.
    layers.Resizing(32, 32),
    # Normalize.
    norm_layer,
    layers.Conv2D(32, 3, activation='relu'),
    layers.Conv2D(64, 3, activation='relu'),
    layers.MaxPooling2D(),
    layers.Dropout(0.25),
    layers.Flatten(),
    layers.Dense(128, activation='relu'),
    layers.Dropout(0.5),
    layers.Dense(num_labels),
])

model.compile(
    optimizer=tf.keras.optimizers.Adam(),
    loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
    metrics=['accuracy'],
)

EPOCHS = 10
history = model.fit(
    train_spectrogram_ds,
    validation_data=val_spectrogram_ds,
    epochs=EPOCHS,
    callbacks=tf.keras.callbacks.EarlyStopping(verbose=1, patience=2),
)

model.save("model-dir")

Здесь мы использовали слой нормализации, два сверточных слоя, объединяющий слой, регуляризацию исключения и активацию relu.

вывод

Вывод можно сделать для сохраненного тестового звукового образца, как показано ниже:

import speech_recognition as sr

model = keras.models.load_model("model-dir")
# get spectrogram for each sample as above
test_file = sr.AudioFile('test_file1.wav')
with test_file as source:
    waveform = r.record(source)
    spectrogram = get_spectrogram(waveform)
    prediction = model(spectrogram)
    idx = np.argmax(np.array(prediction[0]))

Мы также можем сделать это с онлайн-данными в реальном времени, когда они записываются.

Вы можете найти все эти фрагменты кода и полные рабочие примеры в моем репозитории GitHub.