# Отчёт по лабораторной работе №3 Артюшина Валерия, Хохлов Кирилл, А-01-22 # Задание 1 ## 1) В среде Google Colab создали новый блокнот (notebook). Импортировали необходимые для работы библиотеки и модули. ```python # импорт модулей import os os.mkdir('/content/drive/MyDrive/Colab Notebooks/is_lab3') os.chdir('/content/drive/MyDrive/Colab Notebooks/is_lab3') from tensorflow import keras from tensorflow.keras import layers from tensorflow.keras.models import Sequential import matplotlib.pyplot as plt import numpy as np from sklearn.metrics import classification_report, confusion_matrix from sklearn.metrics import ConfusionMatrixDisplay ``` ## 2) Загрузили набор данных MNIST, содержащий размеченные изображения рукописных цифр. ```python # загрузка датасета from keras.datasets import mnist (X_train, y_train), (X_test, y_test) = mnist.load_data() ``` ## 3) Разбили набор данных на обучающие и тестовые данные в соотношении 60 000:10 000 элементов. Параметр random_state выбрали равным (4k – 1) = 15, где k = 4 – номер бригады. Вывели размерности полученных обучающих и тестовых массивов данных. ```python # создание своего разбиения датасета 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 = 15) # вывод размерностей 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) Провели предобработку данных: привели обучающие и тестовые данные к формату, пригодному для обучения сверточной нейронной сети. Входные данные принимают значения от 0 до 1, метки цифр закодированы по принципу «one-hot encoding». Вывели размерности предобработанных обучающих и тестовых массивов данных. ```python # Зададим параметры данных и модели num_classes = 10 input_shape = (28, 28, 1) # Приведение входных данных к диапазону [0, 1] X_train = X_train / 255 X_test = X_test / 255 # Расширяем размерность входных данных, чтобы каждое изображение имело # размерность (высота, ширина, количество каналов) X_train = np.expand_dims(X_train, -1) X_test = np.expand_dims(X_test, -1) print('Shape of transformed X train:', X_train.shape) print('Shape of transformed X test:', X_test.shape) # переведем метки в one-hot y_train = keras.utils.to_categorical(y_train, num_classes) y_test = keras.utils.to_categorical(y_test, num_classes) print('Shape of transformed y train:', y_train.shape) print('Shape of transformed y test:', y_test.shape) ``` ``` Shape of transformed X train: (60000, 28, 28, 1) Shape of transformed X test: (10000, 28, 28, 1) Shape of transformed y train: (60000, 10) Shape of transformed y test: (10000, 10) ``` ## 5) Реализовали модель сверточной нейронной сети и обучили ее на обучающих данных с выделением части обучающих данных в качестве валидационных. Вывели информацию об архитектуре нейронной сети. ```python # создаем модель model = Sequential() model.add(layers.Conv2D(32, kernel_size=(3, 3), activation="relu", input_shape=input_shape)) model.add(layers.MaxPooling2D(pool_size=(2, 2))) model.add(layers.Conv2D(64, kernel_size=(3, 3), activation="relu")) model.add(layers.MaxPooling2D(pool_size=(2, 2))) model.add(layers.Dropout(0.5)) model.add(layers.Flatten()) model.add(layers.Dense(num_classes, activation="softmax")) model.summary() ``` ![alt text](p5.png) ```python # компилируем и обучаем модель batch_size = 512 epochs = 15 model.compile(loss="categorical_crossentropy", optimizer="adam", metrics=["accuracy"]) model.fit(X_train, y_train, batch_size=batch_size, epochs=epochs, validation_split=0.1) ``` ## 6) Оценили качество обучения на тестовых данных. Вывели значение функции ошибки и значение метрики качества классификации на тестовых данных. ```python # Оценка качества работы модели на тестовых данных scores = model.evaluate(X_test, y_test) print('Loss on test data:', scores[0]) print('Accuracy on test data:', scores[1]) ``` ``` accuracy: 0.9895 loss: 0.0345 Loss on test data: 0.035905033349990845 Accuracy on test data: 0.988099992275238 ``` ## 7) Подали на вход обученной модели два тестовых изображения. Вывели изображения, истинные метки и результаты распознавания. ```python # вывод двух тестовых изображений и результатов распознавания for n in [15, 16]: result = model.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: ', np.argmax(y_test[n])) print('NN answer: ', np.argmax(result)) ``` ![alt text](p7_1.png) ``` Real mark: 1 NN answer: 1 ``` ![alt text](p7_2.png) ``` Real mark: 0 NN answer: 0 ``` ## 8) Вывели отчет о качестве классификации тестовой выборки и матрицу ошибок для тестовой выборки. ```python # истинные метки классов true_labels = np.argmax(y_test, axis=1) # предсказанные метки классов predicted_labels = np.argmax(model.predict(X_test), axis=1) # отчет о качестве классификации print(classification_report(true_labels, predicted_labels)) # вычисление матрицы ошибок conf_matrix = confusion_matrix(true_labels, predicted_labels) # отрисовка матрицы ошибок в виде "тепловой карты" display = ConfusionMatrixDisplay(confusion_matrix=conf_matrix) display.plot() plt.show() ``` ``` precision recall f1-score support 0 0.99 0.99 0.99 994 1 0.99 0.99 0.99 1194 2 0.98 0.99 0.98 975 3 0.99 0.99 0.99 1031 4 0.98 0.99 0.99 967 5 0.99 0.99 0.99 937 6 0.99 0.99 0.99 964 7 0.99 0.99 0.99 998 8 0.98 0.98 0.98 965 9 0.99 0.98 0.98 975 accuracy 0.99 10000 macro avg 0.99 0.99 0.99 10000 weighted avg 0.99 0.99 0.99 10000 ``` ![alt text](p8.png) ## 9) Загрузили, предобработали и подали на вход обученной нейронной сети собственное изображение, созданное при выполнении лабораторной работы №1. Вывели изображение и результат распознавания. ```python # загрузка собственного изображения from PIL import Image for name_image in ['1.png', '2.png']: file_data = Image.open(name_image) 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 = np.reshape(test_img, (1,28,28,1)) # распознавание result = model.predict(test_img) print('I think it\'s', np.argmax(result)) ``` ![alt text](p9_1.png) ``` I think it's 1 ``` ![alt text](p9_2.png) ``` I think it's 2 ``` ## 10) Загрузили с диска модель, сохраненную при выполнении лабораторной работы №1. Вывели информацию об архитектуре модели. Повторили для этой модели п. 6. ```python model_lr1 = keras.models.load_model("best_model.keras") model_lr1.summary() ``` ![alt text](p10.png) ```python # развернем каждое изображение 28*28 в вектор 784 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 10000, train_size = 60000, random_state = 23) 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) print('Shape of transformed X train:', X_test.shape) # переведем метки в one-hot y_train = keras.utils.to_categorical(y_train, num_classes) y_test = keras.utils.to_categorical(y_test, num_classes) print('Shape of transformed y train:', y_train.shape) print('Shape of transformed y test:', y_test.shape) ``` ``` Shape of transformed X train: (60000, 784) Shape of transformed X train: (10000, 784) Shape of transformed y train: (60000, 10) Shape of transformed y test: (10000, 10) ``` ```python # Оценка качества работы модели на тестовых данных scores = model_lr1.evaluate(X_test, y_test) print('Loss on test data:', scores[0]) print('Accuracy on test data:', scores[1]) ``` ``` accuracy: 0.9474 loss: 0.1746 Loss on test data: 0.18537543714046478 Accuracy on test data: 0.9453999996185303 ``` ## 11) Сравнили обученную модель сверточной сети и наилучшую модель полносвязной сети из лабораторной работы №1 по следующим показателям: ## - количество настраиваемых параметров в сети ## - количество эпох обучения ## - качество классификации тестовой выборки. ## Сделали выводы по результатам применения сверточной нейронной сети для распознавания изображений. Таблица 1: | Модель | Количество настраиваемых параметров | Количество эпох обучения | Качество классификации тестовой выборки | |----------|-------------------------------------|---------------------------|-----------------------------------------| | Сверточная | 34 826 | 15 | accuracy:0.988 ; loss:0.036 | | Полносвязная | 79,512 | 50 | accuracy:0.9454 ; loss:0.185 | ## Вывод По результатам применения сверточной НС, а также по результатам таблицы 1 делаем выводы, что сверточная НС лучше справляется с задачами распознования изображений, чем полносвязная - имеет меньше настраиваемых параметров, быстрее обучается, имеет лучшие показатели качества. # Задание 2 В новом блокноте выполнили п. 2–8 задания 1, изменив набор данных MNIST на CIFAR-10, содержащий размеченные цветные изображения объектов, разделенные на 10 классов. При этом: * в п. 3 разбиение данных на обучающие и тестовые произвели в соотношении 50 000:10 000 * после разбиения данных (между п. 3 и 4) вывели 25 изображений из обучающей выборки с подписями классов * в п. 7 одно из тестовых изображений должно распознаваться корректно, а другое – ошибочно. ## 1) Загрузили набор данных CIFAR-10, содержащий цветные изображения размеченные на 10 классов: самолет, автомобиль, птица, кошка, олень, собака, лягушка, лошадь, корабль, грузовик. ```python # загрузка датасета from keras.datasets import cifar10 (X_train, y_train), (X_test, y_test) = cifar10.load_data() ``` ## 2) Разбили набор данных на обучающие и тестовые данные в соотношении 50 000:10 000 элементов. Параметр random_state выбрали равным (4k – 1)=15, где k=4 –номер бригады. Вывели размерности полученных обучающих и тестовых массивов данных. ```python # создание своего разбиения датасета # объединяем в один набор 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 = 50000, random_state = 15) # вывод размерностей 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: (50000, 32, 32, 3) Shape of y train: (50000, 1) Shape of X test: (10000, 32, 32, 3) Shape of y test: (10000, 1) ``` ## Вывели 25 изображений из обучающей выборки с подписью классов. ```python class_names = ['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck'] plt.figure(figsize=(10,10)) for i in range(25): plt.subplot(5,5,i+1) plt.xticks([]) plt.yticks([]) plt.grid(False) plt.imshow(X_train[i]) plt.xlabel(class_names[y_train[i][0]]) plt.show() ``` ![alt text](2_p2.png) ## 3) Провели предобработку данных: привели обучающие и тестовые данные к формату, пригодному для обучения сверточной нейронной сети. Входные данные принимают значения от 0 до 1, метки цифр закодированы по принципу «one-hot encoding». Вывели размерности предобработанных обучающих и тестовых массивов данных. ```python # Зададим параметры данных и модели num_classes = 10 input_shape = (32, 32, 3) # Приведение входных данных к диапазону [0, 1] X_train = X_train / 255 X_test = X_test / 255 print('Shape of transformed X train:', X_train.shape) print('Shape of transformed X test:', X_test.shape) # переведем метки в one-hot y_train = keras.utils.to_categorical(y_train, num_classes) y_test = keras.utils.to_categorical(y_test, num_classes) print('Shape of transformed y train:', y_train.shape) print('Shape of transformed y test:', y_test.shape) ``` ``` Shape of transformed X train: (50000, 32, 32, 3) Shape of transformed X test: (10000, 32, 32, 3) Shape of transformed y train: (50000, 10) Shape of transformed y test: (10000, 10) ``` ## 4) Реализовали модель сверточной нейронной сети и обучили ее на обучающих данных с выделением части обучающих данных в качестве валидационных. Вывели информацию об архитектуре нейронной сети. ```python # создаем модель model = Sequential() # Блок 1 model.add(layers.Conv2D(32, (3, 3), padding="same", activation="relu", input_shape=input_shape)) model.add(layers.BatchNormalization()) model.add(layers.Conv2D(32, (3, 3), padding="same", activation="relu")) model.add(layers.BatchNormalization()) model.add(layers.MaxPooling2D((2, 2))) model.add(layers.Dropout(0.25)) # Блок 2 model.add(layers.Conv2D(64, (3, 3), padding="same", activation="relu")) model.add(layers.BatchNormalization()) model.add(layers.Conv2D(64, (3, 3), padding="same", activation="relu")) model.add(layers.BatchNormalization()) model.add(layers.MaxPooling2D((2, 2))) model.add(layers.Dropout(0.25)) # Блок 3 model.add(layers.Conv2D(128, (3, 3), padding="same", activation="relu")) model.add(layers.BatchNormalization()) model.add(layers.Conv2D(128, (3, 3), padding="same", activation="relu")) model.add(layers.BatchNormalization()) model.add(layers.MaxPooling2D((2, 2))) model.add(layers.Dropout(0.4)) model.add(layers.Flatten()) model.add(layers.Dense(128, activation='relu')) model.add(layers.Dropout(0.5)) model.add(layers.Dense(num_classes, activation="softmax")) model.summary() ``` ![alt text](2_p4.png) ```python # компилируем и обучаем модель batch_size = 64 epochs = 50 model.compile(loss="categorical_crossentropy", optimizer="adam", metrics=["accuracy"]) model.fit(X_train, y_train, batch_size=batch_size, epochs=epochs, validation_split=0.1) ``` ## 5) Оценили качество обучения на тестовых данных. Вывели значение функции ошибки и значение метрики качества классификации на тестовых данных. ```python # Оценка качества работы модели на тестовых данных scores = model.evaluate(X_test, y_test) print('Loss on test data:', scores[0]) print('Accuracy on test data:', scores[1]) ``` ``` accuracy: 0.8587 loss: 0.5093 Loss on test data: 0.5083962678909302 Accuracy on test data: 0.857200026512146 ``` ## 6) Подали на вход обученной модели два тестовых изображения. Вывели изображения, истинные метки и результаты распознавания. ```python # вывод двух тестовых изображений и результатов распознавания for n in [2,3]: result = model.predict(X_test[n:n+1]) print('NN output:', result) plt.imshow(X_test[n].reshape(32,32,3), cmap=plt.get_cmap('gray')) plt.show() print('Real mark: ', np.argmax(y_test[n])) print('NN answer: ', np.argmax(result)) ``` ![alt text](2_p6_1.png) ``` Real mark: 8 NN answer: 2 ``` ![alt text](2_p6_2.png) ``` Real mark: 4 NN answer: 4 ``` ## 7) Вывели отчет о качестве классификации тестовой выборки и матрицу ошибок для тестовой выборки. ```python # истинные метки классов true_labels = np.argmax(y_test, axis=1) # предсказанные метки классов predicted_labels = np.argmax(model.predict(X_test), axis=1) # отчет о качестве классификации print(classification_report(true_labels, predicted_labels, target_names=class_names)) # вычисление матрицы ошибок conf_matrix = confusion_matrix(true_labels, predicted_labels) # отрисовка матрицы ошибок в виде "тепловой карты" fig, ax = plt.subplots(figsize=(6, 6)) disp = ConfusionMatrixDisplay(confusion_matrix=conf_matrix,display_labels=class_names) disp.plot(ax=ax, xticks_rotation=45) # поворот подписей по X и приятная палитра plt.tight_layout() # чтобы всё влезло plt.show() ``` ``` precision recall f1-score support airplane 0.90 0.83 0.86 1015 automobile 0.94 0.94 0.94 933 bird 0.85 0.79 0.82 1010 cat 0.78 0.67 0.72 1025 deer 0.79 0.89 0.84 998 dog 0.77 0.82 0.79 1006 frog 0.83 0.94 0.88 1010 horse 0.94 0.84 0.89 1005 ship 0.90 0.93 0.91 1001 truck 0.89 0.94 0.92 997 accuracy 0.86 10000 macro avg 0.86 0.86 0.86 10000 weighted avg 0.86 0.86 0.86 10000 ``` ![alt text](2_p7.png) ## Вывод По результатам классификации датасета CIFAR-10 созданной сверточной моделью можно сделать вывод, что она довольно неплохо справилась с задачей. Полученные метрики оценки качества имеют показатели в районе 0.85.