Использование платформы глубокого обучения PyTorch и архитектуры CNN

Мотивация

Создайте доказательство концепции для классификации аудио, используя нейронную сеть с глубоким обучением и платформу PyTorch.

Классификация аудио – это задача машинного обучения, которая включает идентификацию и распределение аудиосигналов по различным классам или категориям. Цель классификации звука — дать машинам возможность автоматически распознавать и различать разные типы звука, например музыку, речь и звуки окружающей среды. — Бумаги с кодом

Сценарий

Учитывая звуковой клип кошки или собаки, определите, исходит ли исходное звуковое событие от собаки или кошки. Источник данных здесь. По своей сути это проблема контролируемого обучения.

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

Стратегия

После изучения различных подходов эта исследовательская статья Классификация звуков животных с использованием сверточной нейронной сети заинтриговала меня, и я начал изучать различные подходы.

Моя реализация будет:

  1. Преобразование звукового формата WAV в файлы изображений Spectrogramс помощью библиотеки librosa
    . Пакет librosa по существу фиксирует волновые сигналы и длины волн. Он измеряет амплитуду и децибелы. Это позволяет мне фиксировать особенности звуков кошек и собак для нейронной сети.
  2. Используйте сверточную нейронную сеть, чтобы классифицировать спектрограммы как кошку или собаку.

Интуиция сверточных нейронных сетей от 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%. Хотя выборка очень маленькая, это было хорошим направлением для обобщаемости нейронной сети.

Заглядывая вперед:

  1. Мне любопытно, какие другие подходы в решении этого варианта использования, такие как использование нейронной сети типа RNN, обычно используемой для последовательных данных.
  2. Настройка гиперпараметров
    . Чтобы улучшить текущую модель, я бы использовал задания по настройке гиперпараметров с помощью AWS/Azure, поскольку они предлагают параллельные запуски и функции ранней остановки.
  3. Загрузить модель в облако (AWS/Azure)
  4. Перепроектируйте CNN, используя примеры из исследовательских работ.

Ссылки/Ресурсы/Благодарности

  1. Интуиция:
    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
  2. Документация/учебники:
    - 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

СТАНЬТЕ ПИСАТЕЛЕМ на MLearning.ai Фабрики ИИ // Твой ИИ