14 KiB
ЛАБОРАТОРНАЯ РАБОТА №3
Применение многослойного персептрона. Автоассоциативная ИНС
Цель работы: знакомство с применением многослойного персептрона для решения задач сжатия данных, прогнозирования временных рядов и распознавания образов.
Задание
- Открыть файл с данными по минеральной воде, который использовался при решении задач классификации в предыдущей лабораторной работе. Построить и обучить автоассоциативные нейронные сети с 2-мя и 3-мя нейронами в скрытом слое:
а) для исходных данных из 5-ти классов;
б) для исходных данных из 4-х классов.
Провести визуализацию данных в скрытом слое каждой сети на плоскость и в 3-х мерное пространство. Проанализировать полученные результаты. Выбрать и сохранить автоассоциативные ИНС, обеспечивающие наилучшее сжатие исходных данных.
- …
- Решить задачу распознавания 9-ти изображений самолетов. Исходные данные (файлы avia1.bmp, …, avia9.bmp) необходимо предварительно преобразовать в набор векторов со значениями признаков 0 или 1. Обученная нейронная сеть должна правильно определять модель самолета и его класс (истребитель/бомбардировщик). Принадлежность модели к определенному классу выбирается студентом самостоятельно.
Импорт библиотек:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import torch
import imageio
import warnings
from torch import nn
from IPython.display import clear_output
warnings.filterwarnings('ignore')
%matplotlib inlineСодержание:
1. Подготовка данных
Сохраним в список X_data все девять изображений. Каждое из них загрузим в виде NumPy-массива, затем преобразуем данный массив в float32 и делением на 255 перемасштабируем в его диапазон [0.0, 1.0] (было [0, 255]). Само исходное изображение (по умолчанию цветное) преобразуем изображение в чёрно‑белое — для чего возьмём среднее по каналам R, G, B для каждого пикселя.
X_data = []
for i in range(1, 10):
filename = f'avia{i}.bmp'
img = imageio.imread(filename)
img = img.astype('float32') / 255.
img = np.mean(img, axis=2)
X_data.append(img)Список y_data содержит в себе ответ — принадлежит ли силуэт на каждом из девяти изображений бомбардировщику (1 если принадлежит, 0 если не принадлежит):
y_data = [0, 1, 0, 0, 1, 0, 0, 0, 1]Выведем все девять изображений и подпишем каждое из них:
fig, axes = plt.subplots(3, 3, figsize=(9, 9))
axes = axes.ravel()
for i in range(9):
axes[i].imshow(X_data[i], cmap='gray')
aircraft_type = '\nБомбардировщик' if y_data[i] == 1 else '\nИстребитель'
axes[i].set_title(aircraft_type)
axes[i].axis('off')
plt.tight_layout()
plt.show()Представим данные в виде тензоров X_data_tensor и y_data_tensor:
X_data_tensor = torch.tensor(X_data).float()
y_data_tensor = torch.tensor(y_data).reshape(-1, 1).float()Проверим размерность X_data_tensor — она показывает, что в тензоре лежат девять изображений размером 352 на 346:
X_data_tensor.shapeМногослойный персептрон всегда принимает на вход одномерные векторы. Однако в нашей задаче классификации силуэтов саолётов исходные изображения — как видно из размерности, двуомерные тензоры. И чтобы подать их на вход сети, их необходимо «развернуть» в одномерные векторы, сохранив количество объектов (пикселей) неизменным.
Такое преобразование позволяет использовать пространственную информацию пикселей как набор признаков для полносвязных слоёв персептрона.
В PyTorch это можно сделать с помощью метода .view() следующим образом:
X_data_tensor.view(X_data_tensor.size(0), -1).shapeДля проверки перемножим длину и щирину одного из изображений:
np.prod(X_data[0].shape)2. Классификация изображений
Реализуйте в классе ImageClassifier с помощью полносвязных слоёв nn.Linear многослойный персептрон. В качестве промежуточных функций активации используйте nn.ReLU(), а в качестве финальной — сигмоиду, поскольку решается задача бинарной классификации.
class ImageClassifier(nn.Module):
def __init__(self, input_size):
super().__init__()
self.seq = nn.Sequential(
# Ваш код здесь
)
def forward(self, x):
x = x.view(x.size(0), -1)
return self.seq(x)Создайте экземпляр модели:
model = ImageClassifier(input_size=# Ваш код здесь
modelПроверим, что модель при приходе данных возвращает вероятности:
model(X_data_tensor)Метрика accuracy:
def accuracy(y_pred, y_true):
return torch.sum(y_pred == y_true) / len(y_true)Задайте параметры для обучения нейронной сети:
torch.manual_seed(seed=42)
model = # Ваш код здесь
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()
print(f'Accuracy: {accuracy((y_prob > 0.5).float(), y_data_tensor).item():.3f}')Литература:
- Бородкин А.А., Елисеев В.Л. Основы и применение искусственных нейронных сетей. Сборник лабораторных работ: методическое пособие. – М.: Издательский дом МЭИ, 2017.
- MachineLearning.ru — профессиональный информационно-аналитический ресурс, посвященный машинному обучению, распознаванию образов и интеллектуальному анализу данных: http://www.machinelearning.ru
- Modern State of Artificial Intelligence — Online Masters program at MIPT: https://girafe.ai/