1
0
ответвлено от main/neurocomputers-python
Files
neurocomputers-python/lab3/3.1_autoencoder.ipynb

22 KiB

ЛАБОРАТОРНАЯ РАБОТА №3

Применение многослойного персептрона. Автоассоциативная ИНС

Цель работы: знакомство с применением многослойного персептрона для решения задач сжатия данных, прогнозирования временных рядов и распознавания образов.

Задание

  1. Открыть файл с данными по минеральной воде, который использовался при решении задач классификации в предыдущей лабораторной работе. Построить и обучить автоассоциативные нейронные сети с 2-мя и 3-мя нейронами в скрытом слое:
    а) для исходных данных из 5-ти классов;
    б) для исходных данных из 4-х классов.
    Провести визуализацию данных в скрытом слое каждой сети на плоскость и в 3-х мерное пространство. Проанализировать полученные результаты. Выбрать и сохранить автоассоциативные ИНС, обеспечивающие наилучшее сжатие исходных данных.

  2. Решить задачу распознавания 9-ти изображений самолетов. Исходные данные (файлы avia1.bmp, …, avia9.bmp) необходимо предварительно преобразовать в набор векторов со значениями признаков 0 или 1. Обученная нейронная сеть должна правильно определять модель самолета и его класс (истребитель/бомбардировщик). Принадлежность модели к определенному классу выбирается студентом самостоятельно.

Импорт библиотек:

import numpy as np
import pandas as pd
import seaborn as sns
import torch
import matplotlib.pyplot as plt
from IPython.display import clear_output
from mpl_toolkits.mplot3d import Axes3D

from torch import nn

%matplotlib inline

Содержание:

1. Подготовка данных
2. Автоассоциативная нейронная сеть на полных данных
3. Автоассоциативная нейронная сеть на неполных данных

1. Подготовка данных

Загрузим в датафрейм data данные о сорока образцах минеральной воды, хранящиеся в файле min_water.txt.

data = pd.read_csv('min_water.csv')
data.head(n=5)

Вынесем в отдельные переменные:

  • y_binary — выходной признак для задачи бинарной классификации (первый столбец датафрейма);
  • y_multiclass — выходной признак для задачи многоклассовой классификации (второй столбец датафрейма);
  • X_data — входные признаки (оставшиеся столбцы).
y_binary = data.iloc[:, 0]
y_multiclass = data.iloc[:, 1]

X_data = data.iloc[:, 2:]

Выпишите в список features отобранные в прошлой лабораторной работе признаки (формат: features = ['VAR1', 'VAR2']):

features = # Ваш код здесь

Датафрейм с отобранными входными признаками X_data_filtered:

X_data_filtered = X_data.loc[:, features]
X_data_filtered.head(n=5)

Произведите нормализацию или стандартизацию (на выбор) отобранных входных данных X_data_filtered. Результат сохраните в переменную X_data_preprocessed, которую затем представьте в виде тензора X_data_tensor:

# Ваш код здесь

X_data_preprocessed = # Ваш код здесь

X_data_tensor = # Ваш код здесь

2. Автоассоциативная нейронная сеть на полных данных

Автоассоциативная сеть (или автоассоциативная память) — тип нейронной сети, способный восстанавливать полный шаблон данных по его частичному или зашумлённому представлению.

Типичная автоассоциативная сеть содержит как минимум три скрытых слоя:

  • первый скрытый слой выполняет нелинейное кодирование входных данных (энкодер);
  • средний слой («узкое горло» или «бутылочное горло») формирует сжатое представление данных — в результате обучения выдаёт компактное кодирование;
  • последний скрытый слой служит декодером: восстанавливает исходные данные из сжатого представления.

Цель обучения: в процессе минимизации ошибки воспроизведения сеть стремится сделать выходной сигнал максимально близким к входному. Это эквивалентно оптимальному кодированию в «узком горле» сети.

Допишите класс Autoencoder структурами энкодера и декодера на основе полносвязных слоёв nn.Linear. В качестве функций активации используйте nn.ReLU(). При этом на выходе энкодера функцию активации можно не применять — это позволит сохранить отрицательные значения в кодированном представлении.

class Autoencoder(nn.Module):
    def __init__(self, n_inputs, n_hiddens, bottleneck_size):
        super().__init__()
        self.encoder = nn.Sequential(
            # Ваш код здесь
        )
        self.decoder = nn.Sequential(
            # Ваш код здесь
        )

    def forward(self, x):
        encoded = self.encoder(x)
        decoded = self.decoder(encoded)
        return decoded

Создайте экземпляр модели с двумя нейронами в «узком горле»:

model_2 = Autoencoder(# Ващ код здесь
print(model_2)

Пропустим данные через эту модель для её проверки:

model_2(X_data_tensor[:3])

Удостоверимся, что размерность её выхода совпадает с размерностью её входа:

assert X_data_tensor[:3].shape == model_2(X_data_tensor[:3]).shape

Проверим, как модель обучается. Зададим оптимизатор и среднеквадратическую функцию потерь:

optimizer = torch.optim.SGD(model_2.parameters(), lr=1.5)
criterion = nn.MSELoss()

Рассчитаем значение функции потерь:

decoded = model_2(X_data_tensor)

loss = criterion(decoded, X_data_tensor)
loss

Выполните несколько раз эту и предыдущую ячейку, чтобы убедиться в уменьшении ошибки:

loss.backward()
optimizer.step()
optimizer.zero_grad()

Задайте параметры для обучения автоассоциативной сети с двумя нейронами в «узком горле»:

torch.manual_seed(seed=42)

model_2 = # Ваш код здесь

epochs = # Ваш код здесь

learning_rate = # Ваш код здесь
momentum = # Ваш код здесь

optimizer = # Ваш код здесь
criterion = # Ваш код здесь

Обучение нейронной сети:

loss_history = []

for epoch in range(epochs):
    # Ваш код здесь

    if (epoch + 1) % 5 == 0:

        clear_output(True)
        plt.plot(range(1, epoch+2), loss_history, label='Loss')
        plt.title(f'Epoch: {epoch + 1}, Loss: {loss_history[-1]:.6f}')
        plt.grid(True, alpha=0.3)
        plt.legend(loc='best')
        plt.show()

После обучения сети получим двумерные данные с выхода энкодера:

encoded_2d = model_2.encoder(X_data_tensor).detach().numpy()
print(encoded_2d[:3])

Построим двумерную диаграмму рассеяния и отметим классы с помощью y_multiclass:

scatter = plt.scatter(x=encoded_2d[:, 0], y=encoded_2d[:, 1], c=y_multiclass, cmap='viridis')
plt.grid(True, alpha=0.3)

# Код для легенды
handles, labels = scatter.legend_elements(prop='colors')
plt.legend(handles, labels, loc='best', title='Classes')

plt.show()

По аналогии обучите автоассоциативную сеть с тремя нейронами в «узком горле»:

torch.manual_seed(seed=42)

model_3 = # Ваш код здесь

# Ваш код здесь
# Ваш код здесь

После обучения сети получите трёхмерные данные с выхода энкодера:

encoded_3d = # Ваш код здесь

Построим трёхмерную диаграмму рассеяния:

fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111, projection='3d')

scatter = ax.scatter(
    xs=encoded_3d[:, 0],
    ys=encoded_3d[:, 1],
    zs=encoded_3d[:, 2],
    c=y_multiclass,
    cmap='viridis',
    s=50
)

ax.grid(True, alpha=0.3)

handles, labels = scatter.legend_elements(prop='colors', alpha=0.8)
ax.legend(handles, labels, loc='best', title='Classes')

# Настраиваем угол обзора:
# elev — высота, azim — азимут
ax.view_init(elev=20, azim=45)

plt.show()

Сохраним в бинарные файлы .npy выходы энкодеров обеих моделей — для следующей лабораторной работы:

np.save('encoded_2d.npy', encoded_2d)
np.save('encoded_3d.npy', encoded_3d)

3. Автоассоциативная нейронная сеть на неполных данных

Выберите класс, который нужно исключить:

label_to_exclude = # Ваш код здесь

Создадим маску для исключения данных этого класса:

mask_to_exclude = y_multiclass != label_to_exclude

Данные исключены:

X_data_tensor[mask_to_exclude].shape

По аналогии с предыдущим пунктом реализуйте обучение автоассоциативных сетей с двумя и тремя нейронами в «узком горле» на неполных данных (т.е. на каждой эпохе вместо полных данных X_data_tensor на модель нужно подавать неполные данные X_data_tensor[mask_to_exclude]).

Результаты выходов энкодеров в обоих случаях также сохраните в отдельные бинарные файлы.

# Ваш код здесь
# Ваш код здесь
# Ваш код здесь

Литература:

  1. Бородкин А.А., Елисеев В.Л. Основы и применение искусственных нейронных сетей. Сборник лабораторных работ: методическое пособие. – М.: Издательский дом МЭИ, 2017.
  2. MachineLearning.ru — профессиональный информационно-аналитический ресурс, посвященный машинному обучению, распознаванию образов и интеллектуальному анализу данных: http://www.machinelearning.ru
  3. Modern State of Artificial Intelligence — Online Masters program at MIPT: https://girafe.ai/