Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
42
Добавлен:
18.07.2022
Размер:
262.51 Кб
Скачать

Отчет по лабораторной работе № 1

по дисциплине «Интеллектуальные системы» на тему «Архитектура и обучение глубоких нейронных сетей»

Цель работы

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

Выполнение работы

Пункт 1

В среде Google Colab создадим новый блокнот (notebook). Импортируем необходимые для работы библиотеки и модули.

import os

os.chdir('/content/drive/MyDrive/Colab Notebooks') from tensorflow import keras

import matplotlib.pyplot as plt import numpy as np

import sklearn

Пункт 2

Загрузим набор данных MNIST, содержащий размеченные изображения рукописных

цифр.

from keras.datasets import mnist

(X_train, y_train), (X_test, y_test) = mnist.load_data()

Результат:

Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz 11493376/11490434 [==============================] - 0s 0us/step 11501568/11490434 [==============================] - 0s 0us/step

Пункт 3

Разобьем набор данных на обучающие (train) и тестовые (test) данные в соотношении 60000:10000 элементов. При разбиении параметр random_state выберем равным (4*22 – 1) = 87. Выведем размерности полученных обучающих и тестовых массивов данных.

1

# создание своего разбиения датасета

from sklearn.model_selection import train_test_split

# объединяем в один набор

X = np.concatenate((X_train, X_test)) y = np.concatenate((y_train, y_test))

# разбиваем по вариантам

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 10000,

train_size = 60000, random_state = 87)

# вывод размерностей

print('Shape of X train:', X_train.shape) print('Shape of y train:', y_train.shape) print('Shape of X test:', X_test.shape) print('Shape of y test:', y_test.shape)

Результат:

Shape of X train: (60000, 28, 28)

Shape of y train: (60000,)

Shape of X test: (10000, 28, 28)

Shape of y test: (10000,)

Пункт 4

Выведем первые 4 элемента обучающих данных (изображения и метки цифр).

Первый элемент:

# вывод изображения

plt.imshow(X_train[0], cmap=plt.get_cmap('gray')) plt.show()

# вывод метки для этого изображения print(y_train[0])

Результат:

8

Второй элемент:

# вывод изображения

plt.imshow(X_train[1], cmap=plt.get_cmap('gray')) plt.show()

# вывод метки для этого изображения print(y_train[1])

Результат:

2

6

Третий элемент:

# вывод изображения

plt.imshow(X_train[2], cmap=plt.get_cmap('gray')) plt.show()

# вывод метки для этого изображения print(y_train[2])

Результат:

8

Четвертый элемент:

# вывод изображения

plt.imshow(X_train[3], cmap=plt.get_cmap('gray')) plt.show()

# вывод метки для этого изображения print(y_train[3])

Результат:

7

Пункт 5

Проведем предобработку данных: приведем обучающие и тестовые данные к формату, пригодному для обучения нейронной сети. Входные данные должны принимать значения от 0 до 1, метки цифр должны быть закодированы по принципу «one-hot encoding». Выведем размерности предобработанных обучающих и тестовых массивов данных.

# развернем каждое изображение 28*28 в вектор 784 num_pixels = X_train.shape[1] * X_train.shape[2]

X_train = X_train.reshape(X_train.shape[0], num_pixels) / 255 X_test = X_test.reshape(X_test.shape[0], num_pixels) / 255 print('Shape of transformed X train:', X_train.shape)

Результат:

Shape of transformed X train: (60000, 784)

# переведем метки в one-hot

3

from keras.utils import np_utils

y_train = np_utils.to_categorical(y_train) y_test = np_utils.to_categorical(y_test)

print('Shape of transformed y train:', y_train.shape) num_classes = y_train.shape[1]

Результат:

Shape of transformed y train: (60000, 10)

print('Shape of transformed X test:', X_test.shape) print('Shape of transformed Y test:', y_test.shape)

Результат:

Shape of transformed X test: (10000, 784)

Shape of transformed Y test: (10000, 10)

Пункт 6

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

количество скрытых слоев: 0,

функция активации выходного слоя: softmax,

функция ошибки: categorical_crossentropy,

алгоритм обучения: sgd,

метрика качества: accuracy,

количество эпох: 100,

доля валидационных данных от обучающих: 0.1.

from keras.models import Sequential from keras.layers import Dense model = Sequential()

model.add(Dense(units=num_classes, input_dim=num_pixels, activation='softmax')) model.compile(loss='categorical_crossentropy', optimizer='sgd', metrics=['accuracy'])

# вывод информации об архитектуре модели print(model.summary())

Результат:

Model: "sequential"

_________________________________________________________________

Layer (type) Output Shape Param #

=================================================================

dense (Dense) (None, 10) 7850

=================================================================

Total params: 7,850

4

Trainable params: 7,850 Non-trainable params: 0

_________________________________________________________________

None

# Обучаем модель

H = model.fit(X_train, y_train, validation_split=0.1, epochs=100)

Результат:

Epoch 1/100

1688/1688 [==============================] - 3s 1ms/step - loss: 0.7991 - accuracy: 0.8111

-val_loss: 0.5255 - val_accuracy: 0.8667 Epoch 2/100

1688/1688 [==============================] - 2s 1ms/step - loss: 0.4629 - accuracy: 0.8795

-val_loss: 0.4364 - val_accuracy: 0.8842

Epoch 100/100

1688/1688 [==============================] - 2s 1ms/step - loss: 0.2548 - accuracy: 0.9291 - val_loss: 0.2735 - val_accuracy: 0.9253

# вывод графика ошибки по эпохам plt.plot(H.history['loss']) plt.plot(H.history['val_loss']) plt.grid()

plt.xlabel('Epochs') plt.ylabel('loss') plt.legend(['train_loss', 'val_loss']) plt.title('Loss by epochs') plt.show()

Результат:

5

Пункт 7

Применим обученную модель к тестовым данным. Выведем значение функции ошибки и значение метрики качества классификации на тестовых данных.

# Оценка качества работы модели на тестовых данных scores = model.evaluate(X_test, y_test)

print('Loss on test data:', scores[0]) print('Accuracy on test data:', scores[1])

Результат:

313/313 [==============================] - 0s 990us/step - loss: 0.2891 - accuracy: 0.9209 Loss on test data: 0.28913038969039917

Accuracy on test data: 0.9208999872207642

Пункт 8

Добавим в модель один скрытый слой и проведем обучение и тестирование при 100, 300, 500, 1000 нейронах в скрытом слое. По метрике качества классификации на тестовых данных выберем наилучшее количество нейронов в скрытом слое. В качестве функции активации нейронов в скрытом слое используем функцию sigmoid. Результаты расчета метрики качества занесем в таблицу п. 10.

Сравнивая значения метрики качества, полученные для нейронной сети без скрытых слоев (метрика качества 0,921), а также нейронных сетей со 100 (0,958), 300 (0,953), 500 (0,947), 1000 (0,940) нейронами в скрытом слое, получаем, что наибольшее значение метрики качества получено для сети со 100 нейронами.

Пункт 9

Добавим в наилучшую архитектуру (на первом слое 100 нейронов), определенную в п. 8, второй скрытый слой и проведем обучение и тестирование (повторить п. 6-7) при 50, 100, 300 нейронах во втором скрытом слое. В качестве функции активации нейронов в скрытом слое используем функцию sigmoid.

6

Пункт 10

Результаты исследования архитектуры нейронной сети занесем в таблицу:

Количество скрытых

Количество

Количество

Значение метрики

нейронов в первом

нейронов во втором

качества

слоев

скрытом слое

скрытом слое

классификации

 

 

 

 

 

0

-

-

0.9208999872207642

 

 

 

 

 

100

 

0.9581000208854675

 

 

 

 

1

300

-

0.9534000158309937

 

 

 

500

 

0.9472000002861023

 

 

 

 

 

1000

 

0.9404000043869019

 

 

 

 

 

 

50

0.960099995136261

2

100

 

 

100

0.9611999988555908

 

 

 

 

 

 

300

0.9616000056266785

 

 

 

 

Из таблицы видно, что:

1.при увеличении числа слоев значение метрики качества классификации увеличивалось;

2.при увеличении числа нейронов в скрытом слое нейронной сети с одним скрытым слоем значение метрики качества уменьшалось:

3.при увеличении числа нейронов во втором скрытом слое нейронной сети с двумя скрытыми слоями при постоянном числе нейронов в первом скрытом слое (100) значение метрики качества увеличивалось.

Сравнивая значения метрики качества, представленные в таблице, выберем в качестве нейронной сети с наилучшей архитектурой сеть с двумя скрытыми слоями: в первом слое 100 нейронов, во втором слое 300 нейронов.

Пункт 11

Для нейронной сети наилучшей архитектуры (100 нейронов в первом слое, 300 нейронов во втором слое) выведем два тестовых изображения, истинные метки и результат распознавания изображений.

# вывод тестового изображения и результата распознавания n = 87

result = model9_300.predict(X_test[n:n+1]) print('NN output:', result)

plt.imshow(X_test[n].reshape(28,28), cmap=plt.get_cmap('gray')) plt.show()

print('Real mark: ', str(np.argmax(y_test[n]))) print('NN answer: ', str(np.argmax(result)))

7

Результат:

NN output: [[2.2340394e-04 5.1248958e-04 3.0402772e-04 8.9935213e-01 4.4509859e-05 1.3898294e-02 2.3015717e-05 3.8455505e-07 8.4959544e-02 6.8225252e-04]]

Real mark: 3

NN answer: 3

result2 = model9_300.predict(X_test[n+1:n+2]) print('NN output:', result2)

plt.imshow(X_test[n+1].reshape(28,28), cmap=plt.get_cmap('gray')) plt.show()

print('Real mark: ', str(np.argmax(y_test[n+1]))) print('NN answer: ', str(np.argmax(result2)))

Результат:

NN output: [[2.6738383e-07 5.3207718e-02 2.0246504e-02 3.0528089e-01 8.3283467e-06 1.7038414e-04 3.7199155e-07 6.0480994e-01 4.9034960e-04 1.5785262e-02]]

Real mark: 3

NN answer: 7

Таким образом, из полученных результатов видно, что нейронная сеть неверно определила цифру 3, написание которой похоже на цифру 7.

Пункт 12

Создадим собственное изображение рукописной цифры, подобное представленным в наборе MNIST. Цифру выберем как остаток от деления на 10 числа своего дня рождения (3). Сохраним изображение. Загрузим, предобработаем и подадим на вход обученной нейронной сети собственное изображение. Выведем изображение и результат распознавания.

Изображение test.png:

# загрузка собственного изображения from PIL import Image

file_data = Image.open('test.png')

8

file_data = file_data.convert('L') # перевод в градации серого test_img = np.array(file_data)

# вывод собственного изображения plt.imshow(test_img, cmap=plt.get_cmap('gray')) plt.show()

Результат:

# предобработка test_img = test_img / 255

test_img = test_img.reshape(1, num_pixels)

# распознавание

result = model9_300.predict(test_img) print('I think it\'s ', np.argmax(result))

Результат:

I think it's 3

Пункт 13

Создадим копию собственного изображения, отличающуюся от оригинала поворотом на 90 градусов в любую сторону. Сохраним изображение. Загрузим, предобработаем и подадим на вход обученной нейронной сети измененное изображение. Выведем изображение и результат распознавания. Сделать выводы по результатам эксперимента.

Изображение test2.png:

#загрузка собственного изображения from PIL import Image

file_data = Image.open('test2.png')

file_data = file_data.convert('L') # перевод в градации серого test_img = np.array(file_data)

#вывод собственного изображения

plt.imshow(test_img, cmap=plt.get_cmap('gray')) plt.show()

Результат:

9

# предобработка test_img = test_img / 255

test_img = test_img.reshape(1, num_pixels)

# распознавание

result = model9_300.predict(test_img) print('I think it\'s ', np.argmax(result))

Результат:

I think it's 2

Таким образом, из результатов выполнения пунктов 12 – 13 видно, что нейронная сеть с наилучшей архитектурой верно распознала изображение цифры 3 без поворота, но неверно определила повернутое на 90 градусов изображение этой же цифры. Это можно объяснить тем, что нейронная сеть обучалась на данных из набора MNIST, где изображения цифр представлены с меньшим поворотом, то есть у сети не было информации для верного определения значения цифры, изображение которой представлено при большом угле поворота.

10

Соседние файлы в папке Лабораторные работы