Использование платформы глубокого обучения PyTorch и архитектуры CNN
Мотивация
Создайте доказательство концепции для классификации аудио, используя нейронную сеть с глубоким обучением и платформу PyTorch.
Классификация аудио – это задача машинного обучения, которая включает идентификацию и распределение аудиосигналов по различным классам или категориям. Цель классификации звука — дать машинам возможность автоматически распознавать и различать разные типы звука, например музыку, речь и звуки окружающей среды. — Бумаги с кодом
Сценарий
Учитывая звуковой клип кошки или собаки, определите, исходит ли исходное звуковое событие от собаки или кошки. Источник данных здесь. По своей сути это проблема контролируемого обучения.
После заполнения блокнота результаты дают точность проверки 90 %, что весьма впечатляет, учитывая относительно небольшой набор данных.
Стратегия
После изучения различных подходов эта исследовательская статья Классификация звуков животных с использованием сверточной нейронной сети заинтриговала меня, и я начал изучать различные подходы.
Моя реализация будет:
- Преобразование звукового формата WAV в файлы изображений Spectrogramс помощью библиотеки librosa
. Пакет librosa по существу фиксирует волновые сигналы и длины волн. Он измеряет амплитуду и децибелы. Это позволяет мне фиксировать особенности звуков кошек и собак для нейронной сети. - Используйте сверточную нейронную сеть, чтобы классифицировать спектрограммы как кошку или собаку.
Интуиция сверточных нейронных сетей от StatQuest с Джошем Стармером
Блокнот
Подготовка данных
def create_spectogram(audio_file_name,source_path,save_path): x, sr = librosa.load(source_path+audio_file_name) X = librosa.stft(x) Xdb = librosa.amplitude_to_db(abs(X)) plt.figure(figsize=(14, 5)) librosa.display.specshow(Xdb, sr=sr, y_axis='hz') plt.ylabel('') plt.axis('off') file_name = audio_file_name.replace('.wav','') plt.savefig(save_path+file_name+'.jpg', bbox_inches='tight', pad_inches=0) plt.close() # Comment if you want to see the image
оригинальный код предоставлен Alessandro Bombini
Функция create_spectogram
читает аудиофайл из исходного каталога и сохраняет изображение в целевой каталог.
Построить набор данных и загрузчик данных
Загрузчики данных помогают разделить нашу записную книжку, разделив этап подготовки данных и этап обучения модели.
Используя image_location, я могу хранить изображения на диске, а не загружать все изображения в память. Во время обучения изображения передаются в нейронную сеть.
Загрузка всех изображений в память и последующая передача их в нейронную сеть увеличивает вероятность ошибки при обратном распространении.
class CatDogDataset(Dataset): """User defined class to build a datset using Pytorch class Dataset.""" def __init__(self, data, transform = None): """Method to initilaize variables.""" self.img_labels = data['target'] self.img_loc = data['image_location'] self.transform = transform def __getitem__(self, idx): img_path = os.path.join(self.img_loc.iloc[idx]) label = self.img_labels.iloc[idx] if label == 'cat': label = 0 else: label = 1 image = Image.open(img_path) if self.transform is not None: image = self.transform(image) return image, label def __len__(self): return len(self.img_labels)
Класс набора данных содержит местоположение изображения и метку звукового файла кошки/собаки. Когда изображение вызывается через функцию getitem
, объект извлекает изображение через каталог, открывает изображение, запускает преобразование и возвращает данные изображения и метку. Эти два объекта будут загружены в нашу нейронную сеть.
transform = transforms.Compose([ transforms.PILToTensor(), transforms.ConvertImageDtype(torch.float), transforms.Resize(size = (256,256)), ])
Преобразования запускаются при вызове изображения. Эти шаги преобразуют изображение в тензор, который является типом данных для нейронной сети. Тензорное представление изображений спектрограммыпозволит обучать нейронную сеть тому, какое изображение описывает звук кошки или собаки.
train_set = CatDogDataset(train_csv, transform) batch_size = 15 train_loader = DataLoader(train_set, batch_size=batch_size)
Архитектура Си-Эн-Эн
class CNN(nn.Module): def __init__(self): super(CNN, self).__init__() self.net=nn.Sequential( # C1 nn.Conv2d(in_channels = 3, out_channels = 12, kernel_size = 3, stride = 1, padding = 1), nn.ReLU(), nn.MaxPool2d(kernel_size = 2), # C2 nn.Conv2d(in_channels = 12, out_channels = 24, kernel_size = 3, stride = 1, padding = 1), nn.ReLU(), nn.MaxPool2d(kernel_size = 2), #C3 nn.Conv2d(in_channels = 24, out_channels = 12, kernel_size = 3, stride = 1, padding = 1), nn.ReLU(), nn.MaxPool2d(kernel_size = 2), # Dropout nn.Dropout(.2), nn.Flatten(), # 256/2/2/2 = 32 # FC1 nn.Linear(in_features = 32 * 32 * 12, out_features = 128), nn.ReLU(), # FC2 nn.Linear(in_features = 128, out_features = 64), nn.ReLU(), #output layer nn.Linear(in_features = 64, out_features = 1), nn.Sigmoid() ) def forward(self, X): X = self.net(X) return X
Эта архитектура CNN была адаптирована из этого примера. Он включает в себя 3 сверточных слоя, слой исключения для регуляризации, слой выравнивания для подачи в 2 полносвязных слоя и выходной слой для результирующего предсказания. Поскольку сценарий имеет только 2 выхода (кошка или собака), я решил вывести один нейрон и использовать сигмовидную функцию для возврата вероятности.
Во время прогнозирования любое значение, большее или равное 0,5, прогнозируется как звук собаки, а все меньшее присваивается метке кошки.
Обучить нейронную сеть
Гиперпараметры и оптимизация:
loss_fn = nn.BCELoss() # binary cross entropy optimizer = optim.Adam(model.parameters(), lr=0.0001) epochs = 50 current_best = 0
Сценарий обучения:
start = time.time() for epoch in range(epochs): train_loss = 0 model.train() for x, y in train_loader: # Reset the optimizer optimizer.zero_grad() # Push the data forward through the model layers output = model(x) # Get the loss loss = loss_fn(output, y.reshape(-1,1).to(torch.float32)) # Keep a running total train_loss += loss.item() # Backpropagate loss.backward() optimizer.step() if epoch % 5 == 0: metric, test_loss = eval_model(model,test_loader) if metric > current_best: best_model = model current_best = metric print(f'best accuracy so far is {current_best}') epoch_nums.append(epoch) training_loss.append(train_loss) validation_loss.append(test_loss) validation_acc.append(metric)
Обучающий сценарий подает данные изображения обучающей спектрограммы партиями за раз. С каждым пакетом нейронная сеть подвергается прямому и обратному распространению.
Градиенты хранятся в DCG и обновляют веса и параметры смещения в нейронной сети во время обратного распространения. Как правило, чем больше нейронная сеть, тем больше пакет и чем больше набор данных, тем больше времени требуется для обучения.
# function for evaluating a model's performance def eval_model(model,data_loader): model.eval() y_true_list=[] y_pred_list=[] test_loss = 0 for x,y in data_loader: outputs=model(x) # an output > .5 will round up to 1 which corresponds to dog. y_pred = torch.round(outputs) y_pred_list.extend(y_pred.clone().detach().tolist()) y_true_list.extend(y.clone().detach().tolist()) # Get the loss loss = loss_fn(outputs, y.reshape(-1,1).to(torch.float32)) # Keep a running total test_loss += loss.item() acc=classification_report(y_true_list, y_pred_list,output_dict=True)['accuracy'] return acc, test_loss
Функция оценки eval_model
вызывается через каждые 5 эпох с использованием пропущенного набора данных проверки. Установив model.eval()
, мы предотвратим текущую нейронную сеть от обратного распространения ошибки и градиентного спуска.
Оценка
В целом, это хорошие результаты, где потери при обучении и проверке неуклонно уменьшаются с каждой эпохой и показывают, что нейронная сеть способна совершенствоваться. Поскольку потери при обучении ненамного выше, чем потери при проверке, мы можем сделать вывод, что модель НЕ переоснащение.
Нейронная сеть смогла обучиться и повысить точность до 90% к 50-й эпохе!
Запуск выводов
Получение звуков кошек и собак из Интернета, таких как soundcamp и wavlist, точность составляет 80%. Хотя выборка очень маленькая, это было хорошим направлением для обобщаемости нейронной сети.
Заглядывая вперед:
- Мне любопытно, какие другие подходы в решении этого варианта использования, такие как использование нейронной сети типа RNN, обычно используемой для последовательных данных.
- Настройка гиперпараметров
. Чтобы улучшить текущую модель, я бы использовал задания по настройке гиперпараметров с помощью AWS/Azure, поскольку они предлагают параллельные запуски и функции ранней остановки. - Загрузить модель в облако (AWS/Azure)
- Перепроектируйте CNN, используя примеры из исследовательских работ.
Ссылки/Ресурсы/Благодарности
- Интуиция:
— https://cs231n.github.io/convolutional-networks/
— https://ieeexplore.ieee.org/document/8566449
- https://towardsdatascience.com/audio-deep-learning-made-simple-sound-classification-step-by-step-cebc936bbe5
- https://medium.com/ thecyphy/поезд-cnn-модель-с-pytorch-21dafb918f48 - Документация/учебники:
- https://www.kaggle.com/code/thanht02/audio-classification-cnn-864d1f
- https://www .kaggle.com/code/kanncaa1/pytorch-tutorial-for-deep-learning-lovers
— https://pytorch.org/tutorials/beginner/data_loading_tutorial.html
— https ://www.kaggle.com/code/pinocookie/pytorch-dataset-and-dataloader
- https://www.geeksforgeeks.org/converting-an-image-to-a-torch-tensor -in-python/
— https://www.tutorialspoint.com/pytorch-how-to-resize-an-image-to-a-given-size
— https: //towardsdatascience.com/logistic-regression-with-pytorch-3c8bbea594be
— https://www.kaggle.com/code/androbomb/using-cnn-to-classify-images-w-pytorch
- https://towardsdatascience.com/cnns-for-audio-classification-6244954665ab
- https://matplotlib.org/2.0.2/users/pyplot_tutorial.html
- https://pytorch.org/tutorials/beginner/basics/data_tutorial.html