# Отчёт по лабораторной работе №3 ### Киселёв Матвей, Мамедов Расул А-01-22 ### Вариант 6 ## Задание 1 ## 1) В среде Google Colab создать новый блокнот (notebook). Импортировать необходимые для работы библиотеки и модули. ```python # импорт модулей import os 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), где k –номер бригады. Вывести размерности полученных обучающих и тестовых массивов данных. ```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 = 23) # вывод размерностей 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() ``` ![picture](1.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]) ``` ``` 313/313 ━━━━━━━━━━━━━━━━━━━━ 2s 4ms/step - accuracy: 0.9909 - loss: 0.0257 Loss on test data: 0.02905484288930893 Accuracy on test data: 0.9904999732971191 ``` ## 7) ППодать на вход обученной модели два тестовых изображения. Вывести изображения, истинные метки и результаты распознавания. ```python # вывод двух тестовых изображений и результатов распознавания for n in [3,26]: 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)) ``` ![picture](2.png) ``` Real mark: 2 NN answer: 2 ``` ![picture](3.png) ``` Real mark: 9 NN answer: 9 ``` ## 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() ``` ``` 313/313 ━━━━━━━━━━━━━━━━━━━━ 1s 2ms/step precision recall f1-score support 0 0.99 1.00 0.99 997 1 1.00 0.99 1.00 1164 2 0.99 0.98 0.99 1030 3 0.99 0.99 0.99 1031 4 0.99 0.99 0.99 967 5 0.98 0.99 0.99 860 6 0.99 1.00 0.99 977 7 0.98 0.99 0.99 1072 8 0.99 0.98 0.99 939 9 0.99 0.98 0.98 963 accuracy 0.99 10000 macro avg 0.99 0.99 0.99 10000 weighted avg 0.99 0.99 0.99 10000 ``` ![picture](4.png) ## 9) Загрузить, предобработать и подать на вход обученной нейронной сети собственное изображение, созданное при выполнении лабораторной работы №1. Вывести изображение и результат распознавания. ```python # загрузка собственного изображения from PIL import Image for name_image in ['test3.png', 'test5.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)) ``` ![picture](5.png) ``` I think it's 3 ``` ![picture](6.png) ``` I think it's 5 ``` ## 10) Загрузить с диска модель, сохраненную при выполнении лабораторной работы №1. Вывести информацию об архитектуре модели. Повторить для этой модели п. 6. ```python model_lr1 = keras.models.load_model("model_1h100_2h50.keras") model_lr1.summary() ``` ![picture](7.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]) ``` ``` 313/313 ━━━━━━━━━━━━━━━━━━━━ 3s 5ms/step - accuracy: 0.9576 - loss: 0.1293 Loss on test data: 0.13758081197738647 Accuracy on test data: 0.9567000269889832 ``` ## 11) Сравнить обученную модель сверточной сети и наилучшую модель полносвязной сети из лабораторной работы №1 по следующим показателям: ### - количество настраиваемых параметров в сети ### - количество эпох обучения ### - качество классификации тестовой выборки. ## Сделать выводы по результатам применения сверточной нейронной сети для распознавания изображений. | Модель | Количество настраиваемых параметров | Количество эпох обучения | Качество классификации тестовой выборки | |----------|-------------------------------------|---------------------------|-----------------------------------------| | Сверточная | 34 826 | 15 | accuracy:0.991 ; loss:0.029 | | Полносвязная | 84 062 | 50 | accuracy:0.957 ; loss:0.138 | ### Вывод: сравнивая результаты применения двух сетей, можно сделать вывод, что сверточная НС лучше справляется с задачами распознования изображений, чем полносвязная. ## Задание 2 ## В новом блокноте выполнить п. 1–8 задания 1, изменив набор данных MNIST на CIFAR-10, содержащий размеченные цветные изображения объектов, разделенные на 10 классов. ## 1) Загрузить набор данных CIFAR-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), где k –номер бригады. Вывести размерности полученных обучающих и тестовых массивов данных. ```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 = 23) # вывод размерностей 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) ``` ```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() ``` ![picture](8.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() ``` ![picture](9.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]) ``` ``` 313/313 ━━━━━━━━━━━━━━━━━━━━ 3s 5ms/step - accuracy: 0.8507 - loss: 0.5097 Loss on test data: 0.4886781871318817 Accuracy on test data: 0.8521999716758728 ``` ## 6) Подать на вход обученной модели два тестовых изображения. Вывести изображения, истинные метки и результаты распознавания. ```python # вывод двух тестовых изображений и результатов распознавания for n in [1,10]: 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)) ``` ![picture](10.png) ``` Real mark: 8 NN answer: 8 ``` ![picture](11.png) ``` Real mark: 3 NN answer: 3 ``` ## 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() ``` ``` 313/313 ━━━━━━━━━━━━━━━━━━━━ 5s 9ms/step precision recall f1-score support airplane 0.86 0.88 0.87 986 automobile 0.94 0.93 0.94 971 bird 0.75 0.85 0.80 1043 cat 0.83 0.64 0.72 1037 deer 0.78 0.90 0.83 969 dog 0.78 0.75 0.76 979 frog 0.83 0.92 0.87 1025 horse 0.92 0.83 0.87 948 ship 0.93 0.93 0.93 1003 truck 0.94 0.90 0.92 1039 accuracy 0.85 10000 macro avg 0.86 0.85 0.85 10000 weighted avg 0.86 0.85 0.85 10000 ``` ![picture](12.png) ### Вывод: полученные метрики оценки качества имеют показатели около 0.85. Из этого можно сделать вывод, что сверточная модель хорошо справилась с задачей классификации датасета CIFAR-10.