# Отчёт по лабораторной работе №1 **Кобзев Александр, Кирсанов Егор — А-01-22** ## 1. В среде Google Colab создан новый блокнот. Импортированы необходимые библиотеки и модули. ```python from google.colab import drive drive.mount('/content/drive') ``` ```python from tensorflow import keras import matplotlib.pyplot as plt import numpy as np import sklearn from keras.datasets import mnist from sklearn.model_selection import train_test_split from tensorflow.keras.utils import to_categorical from keras.models import Sequential from keras.layers import Dense from PIL import Image ``` --- ## 2. Загрузили набора данных MNIST с изображениями рукописных цифр. ```python (X_train, y_train), (X_test, y_test) = mnist.load_data() ``` --- ## 3. Разбили данные на обучающую и тестовую выборки 60 000:10 000. При объединении исходных выборок и последующем разбиении был использован параметр `random_state = 4*k - 1`, где *k* – номер бригады (k = 10). Такой фиксированный seed обеспечивает воспроизводимость разбиения. ```python # объединяем исходные обучающие и тестовые данные в один массив X = np.concatenate((X_train, X_test)) y = np.concatenate((y_train, y_test)) # выполняем разбиение на обучающую (60000) и тестовую (10000) выборки X_train, X_test, y_train, y_test = train_test_split( X, y, train_size=60000, test_size=10000, random_state=4*10 - 1 ) # вывод размерностей полученных массивов print('Shape of X train:', X_train.shape) print('Shape of y test:', y_test.shape) ``` ``` Shape of X train: (60000, 28, 28) Shape of y train: (60000,) ``` --- ## 4. Вывели первые 4 элемента обучающих данных (изображения и метки цифр). ```python # вывод изображения fig, axes = plt.subplots(1, 4, figsize=(10, 3)) for i in range(4): axes[i].imshow(X_train[i], cmap=plt.get_cmap('gray')) axes[i].set_title(y_train[i]) axes[i].axis('off') plt.show() ``` ![Примеры изображений](images_for_report/1.png) --- ## 5. Провели предобработку данных: привели обучающие и тестовые данные к формату, пригодному для обучения нейронной сети. Входные данные должны принимать значения от 0 до 1, метки цифр должны быть закодированы по принципу «one-hot encoding». Вывели размерности предобработанных обучающих и тестовых массивов данных. ```python # развернем каждое изображение 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.0 X_test = X_test.reshape(X_test.shape[0], num_pixels) / 255.0 print('Shape of transformed X train:', X_train.shape) ``` ``` Shape of transformed X train: (60000, 784) ``` ```python # переведем метки в one-hot from tensorflow.keras.utils import to_categorical y_train = to_categorical(y_train) y_test = to_categorical(y_test) ``` ``` Shape of transformed y train: (60000, 10) ``` --- ## 6. Реализовали и обученили однослойную нейронную сеть. **Архитектура и параметры:** - количество скрытых слоёв: 0 - функция активации выходного слоя: `softmax` - функция ошибки: `categorical_crossentropy` - алгоритм обучения: `sgd` - метрика качества: `accuracy` - количество эпох: 50 - доля валидационных данных от обучающих: 0.1 ```python model = Sequential() model.add(Dense(units=10, input_dim=num_pixels, activation='softmax')) model.compile(loss='categorical_crossentropy', optimizer='sgd', metrics=['accuracy']) model.summary() ``` ![архитектура модели](images_for_report/2.png) ```python #обучение H1 = model.fit(X_train, y_train, batch_size=256, validation_split=0.1, epochs=150) ``` ```python # вывод графика ошибки по эпохам plt.plot(H1.history['loss']) plt.plot(H1.history['val_loss']) plt.grid() plt.xlabel('Epochs') plt.ylabel('loss') plt.legend(['train_loss', 'val_loss']) plt.title('Loss by epochs') plt.show() ``` ![граффик обучения](images_for_report/3.png) --- ## 7. Применили обученную модель к тестовым данным. ```python # Оценка качества работы модели на тестовых данных scores = model.evaluate(X_test, y_test) print('Loss on test data:', scores[0]) print('Accuracy on test data:', scores[1]) ``` ``` Loss on test data: 0.32417795062065125 Accuracy on test data: 0.9110999703407288 ``` ## 8. Добавили в модель один скрытый слой и провели обучение и тестирование (повторить п. 6–7) при 100, 300, 500 нейронах в скрытом слое. По метрике качества классификации на тестовых данных выбрали наилучшее количество нейронов в скрытом слое. В качестве функции активации нейронов в скрытом слое использовали функцию sigmoid. ### При 100 нейронах: ```python model_100 = Sequential () model_100.add(Dense(units=100,input_dim=num_pixels, activation='sigmoid')) model_100.add(Dense(units=num_classes, activation='softmax')) model_100.compile(loss='categorical_crossentropy', optimizer='sgd', metrics=['accuracy']) print(model_100.summary()) ``` ![архитектура модели](images_for_report/4.png) ```python #обучение H_100 = model_100.fit(X_train, y_train, batch_size=256, validation_split=0.1, epochs=150) ``` ```python # вывод графика ошибки по эпохам plt.plot(H_100.history['loss']) plt.plot(H_100.history['val_loss']) plt.grid() plt.xlabel('Epochs') plt.ylabel('loss') plt.legend(['train_loss', 'val_loss']) plt.title('Loss by epochs') plt.show() ``` ![граффик обучения](images_for_report/5.png) ```python # Оценка качества работы модели на тестовых данных scores = model_100.evaluate(X_test, y_test) print('Loss on test data:', scores[0]) print('Accuracy on test data:', scores[1]) ``` ``` Loss on test data: 0.2998492121696472 Accuracy on test data: 0.9138000011444092 ``` ### При 300 нейронах: ```python model_300 = Sequential () model_300.add(Dense(units=300,input_dim=num_pixels, activation='sigmoid')) model_300.add(Dense(units=num_classes, activation='softmax')) model_300.compile(loss='categorical_crossentropy', optimizer='sgd', metrics=['accuracy']) print(model_300.summary()) ``` ![архитектура модели](images_for_report/6.png) ```python H_300 = model_300.fit(X_train, y_train, batch_size=256, validation_split=0.1, epochs=150) ``` ```python # вывод графика ошибки по эпохам plt.plot(H_300.history['loss']) plt.plot(H_300.history['val_loss']) plt.grid() plt.xlabel('Epochs') plt.ylabel('loss') plt.legend(['train_loss', 'val_loss']) plt.title('Loss by epochs') plt.show() ``` ![граффик обучения](images_for_report/7.png) ```python # Оценка качества работы модели на тестовых данных scores = model_300.evaluate(X_test, y_test) print('Loss on test data:', scores[0]) print('Accuracy on test data:', scores[1]) ``` ``` Loss on test data: 0.31299835443496704 Accuracy on test data: 0.9107999801635742 ``` ### При 500 нейронах: ```python model_500 = Sequential() model_500.add(Dense(units=500, input_dim=num_pixels, activation='sigmoid')) model_500.add(Dense(units=num_classes, activation='softmax')) model_500.compile(loss='categorical_crossentropy', optimizer='sgd', metrics=['accuracy']) print(model_500.summary()) ``` ![архитектура модели](images_for_report/8.png) ```python H_500 = model_500.fit(X_train, y_train, batch_size=256, validation_split=0.1, epochs=150) ``` ```python # вывод графика ошибки по эпохам plt.plot(H_500.history['loss']) plt.plot(H_500.history['val_loss']) plt.grid() plt.xlabel('Epochs') plt.ylabel('loss') plt.legend(['train_loss', 'val_loss']) plt.title('Loss by epochs') plt.show() ``` ![граффик обучения](images_for_report/9.png) ```python # Оценка качества работы модели на тестовых данных scores = model_500.evaluate(X_test, y_test) print('Loss on test data:', scores[0]) print('Accuracy on test data:', scores[1]) ``` ``` Loss on test data: 0.31795090436935425 Accuracy on test data: 0.909600019454956 ``` Мы видим что лучший результат показала модель со 100 нейронами в скрытом слое(Accuracy = 0.9138). ## 9. Добавили в наилучшую архитектуру, определенную в п. 8, второй скрытый слой и провели обучение и тестирование при 50 и 100 нейронах во втором скрытом слое. В качестве функции активации нейронов в скрытом слое использовали функцию sigmoid. ### При 50 нейронах в 2-м слое: ```python model_100_50 = Sequential() model_100_50.add(Dense(units=100, input_dim=num_pixels, activation='sigmoid')) model_100_50.add(Dense(units=50, activation='sigmoid')) model_100_50.add(Dense(units=num_classes, activation='softmax')) model_100_50.compile(loss='categorical_crossentropy', optimizer='sgd', metrics=['accuracy']) print(model_100_50.summary()) ``` ![архитектура модели](images_for_report/10.png) ```python H_100_50 = model_100_50.fit(X_train, y_train, batch_size=256, validation_split=0.1, epochs=150) ``` ```python # вывод графика ошибки по эпохам plt.plot(H_100_50.history['loss']) plt.plot(H_100_50.history['val_loss']) plt.grid() plt.xlabel('Epochs') plt.ylabel('loss') plt.legend(['train_loss', 'val_loss']) plt.title('Loss by epochs') plt.show() ``` ![граффик обучения](images_for_report/11.png) ```python # Оценка качества работы модели на тестовых данных scores = model_100_50.evaluate(X_test, y_test) print('Loss on test data:', scores[0]) print('Accuracy on test data:', scores[1]) ``` ``` Loss on test data: 0.3216394782066345 Accuracy on test data: 0.9085999727249146 ``` ### При 100 нейронах во 2-м слое:\ ```python model_100_100 = Sequential() model_100_100.add(Dense(units=100, input_dim=num_pixels, activation='sigmoid')) model_100_100.add(Dense(units=100, activation='sigmoid')) model_100_100.add(Dense(units=num_classes, activation='softmax')) model_100_100.compile(loss='categorical_crossentropy', optimizer='sgd', metrics=['accuracy']) print(model_100_100.summary()) ``` ![архитектура модели](images_for_report/12.png) ```python H_100_100 = model_100_100.fit(X_train, y_train, batch_size=256, validation_split=0.1, epochs=150) ``` ```python # вывод графика ошибки по эпохам plt.plot(H_100_100.history['loss']) plt.plot(H_100_100.history['val_loss']) plt.grid() plt.xlabel('Epochs') plt.ylabel('loss') plt.legend(['train_loss', 'val_loss']) plt.title('Loss by epochs') plt.show() ``` ![граффик обучения](images_for_report/13.png) ```python # Оценка качества работы модели на тестовых данных scores = model.evaluate(X_test, y_test) print('Loss on test data:', scores[0]) print('Accuracy on test data:', scores[1]) ``` ``` Loss on test data: 0.31788304448127747 Accuracy on test data: 0.9128000140190125 ``` ## 10. Сравнили качество классификации на тестовых данных всех построенных моделей. Сделали выводы. | Кол-во слоёв | Нейронов в 1-м | Нейронов во 2-м | Accuracy | |---------------|----------------|-----------------|-----------| | 0 | – | – | 0.9111 | | 1 | 100 | – | 0.9138 | | 1 | 300 | – | 0.9108 | | 1 | 500 | – | 0.9096 | | 2 | 100 | 50 | 0.9086 | | 2 | 100 | 100 | 0.9128 | **Вывод:** наилучшей оказалась архитектура с одним скрытым слоем и 100 нейронами в нём. Увеличение числа нейронов в скрытом слое или добавление второго слоя не улучшило качество классификации, а в некоторых случаях даже ухудшило его. Вероятно, это связано с переобучением модели из-за избыточного количества параметров при относительно небольшом объёме обучающих данных. --- ## 11. Сохранили наилучшую модель на диск. ```python model_100.save("/content/drive/MyDrive/Colab Notebooks/best_model_100.keras") ``` --- ## 12. Для нейронной сети с наилучшей архитектурой вывели 2 тестовых изображения и истинные метки, а также предсказанные моделью метки. ```python n = 333 result = model_100.predict(X_test[n:n+1]) print('NNoutput:',result) plt.imshow(X_test[n].reshape(28,28),cmap=plt.get_cmap('gray')) plt.show() print('Realmark:',str(np.argmax(y_test[n]))) print('NNanswer:',str(np.argmax(result))) ``` ![Пример 1](images_for_report/14.png) ```python n = 234 result = model_100.predict(X_test[n:n+1]) print('NNoutput:',result) plt.imshow(X_test[n].reshape(28,28),cmap=plt.get_cmap('gray')) plt.show() print('Realmark:',str(np.argmax(y_test[n]))) print('NNanswer:',str(np.argmax(result))) ``` ![Пример 2](images_for_report/15.png) --- ## 13. Создали собственные изображения рукописных цифр, подобное представленным в наборе MNIST. Цифру выбрали как остаток от деления на 10 числа своего дня рождения (14 июля → 14 mod 10 = 4, 7 ноября → 7 mod 10 = 7). Сохранили изображения. Загрузили, предобработали и подали на вход обученной нейронной сети собственные изображения. Вывели изображения и результаты распознавания. ### Для 7: ![Изображение "7"](IS_lab_7.png) ```python #вывод собственного изображения 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=model_100.predict(test_img) print('I think it\'s',np.argmax(result)) ``` ![Отображение "7"](images_for_report/16.png) ### Для 4: ![Мое изображение "4"](IS_lab_4.png) ```python from PIL import Image file_data_4=Image.open('/content/drive/MyDrive/Colab Notebooks/IS_lab_4.png') file_data_4=file_data_4.convert('L') test_img_4=np.array(file_data_4) #вывод собственного изображения plt.imshow(test_img_4,cmap=plt.get_cmap('gray')) plt.show() #предобработка test_img_4=test_img_4/255 test_img_4=test_img_4.reshape(1,num_pixels) #распознавание result=model_100.predict(test_img_4) print('I think it\'s',np.argmax(result)) ``` ![Отображение "4"](images_for_report/17.png) --- ## 14. Создать копию собственного изображения, отличающуюся от оригинала поворотом на 90 градусов в любую сторону. Сохранили изображения. Загрузили, предобработали и подали на вход обученной нейронной сети измененные изображения. Вывели изображения и результаты распознавания. Сделали выводы по результатам эксперимента. ```python from PIL import Image file_data=Image.open('/content/drive/MyDrive/Colab Notebooks/IS_lab_7_90.png') 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=model_100.predict(test_img) print('Ithinkit\'s',np.argmax(result)) ``` ![Отображение "7 повернутой"](images_for_report/18.png) ```python from PIL import Image file_data_4=Image.open('/content/drive/MyDrive/Colab Notebooks/IS_lab_4_90.png') file_data_4=file_data_4.convert('L') test_img_4=np.array(file_data_4) #выводсобственногоизображения plt.imshow(test_img_4,cmap=plt.get_cmap('gray')) plt.show() #предобработка test_img_4=test_img_4/255 test_img_4=test_img_4.reshape(1,num_pixels) #распознавание result=model_100.predict(test_img_4) print('Ithinkit\'s',np.argmax(result)) ``` ![Отображение "4 повернутой"](images_for_report/19.png) **Вывод:** модель неустойчива к повороту изображений, так как не обучалась на повернутых данных. --- ## Заключение Изучены принципы построения и обучения нейронных сетей в Keras на примере распознавания цифр MNIST. Лучшая точность достигнута простой моделью с одним скрытым слоем из 100 нейронов. При усложнении архитектуры наблюдается переобучение. Сеть корректно классифицирует собственные изображения, но ошибается на повернутых.