Сравнить коммиты
110 Коммитов
|
После Ширина: | Высота: | Размер: 6.8 KiB |
|
После Ширина: | Высота: | Размер: 6.6 KiB |
|
После Ширина: | Высота: | Размер: 6.8 KiB |
|
После Ширина: | Высота: | Размер: 6.6 KiB |
|
После Ширина: | Высота: | Размер: 353 B |
|
После Ширина: | Высота: | Размер: 355 B |
|
После Ширина: | Высота: | Размер: 296 B |
|
После Ширина: | Высота: | Размер: 317 B |
|
После Ширина: | Высота: | Размер: 6.9 KiB |
|
После Ширина: | Высота: | Размер: 7.0 KiB |
|
После Ширина: | Высота: | Размер: 4.6 KiB |
|
После Ширина: | Высота: | Размер: 25 KiB |
|
После Ширина: | Высота: | Размер: 25 KiB |
|
После Ширина: | Высота: | Размер: 25 KiB |
|
После Ширина: | Высота: | Размер: 24 KiB |
|
После Ширина: | Высота: | Размер: 28 KiB |
|
После Ширина: | Высота: | Размер: 28 KiB |
@ -0,0 +1,550 @@
|
||||
# Отчет по лабораторной работе №1
|
||||
Текотова Виктория, Секирин Артем, А-02-22
|
||||
|
||||
## 1. В среде GoogleColab создали блокнот(notebook.ipynb).
|
||||
```
|
||||
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()
|
||||
```
|
||||
|
||||
## 3. Разбиение набора данных на обучающие и тестовые
|
||||
```
|
||||
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=3)
|
||||
```
|
||||
|
||||
* Вывод размерностей
|
||||
```
|
||||
print('ShapeofXtrain:',X_train.shape)
|
||||
print('Shapeofytrain:',y_train.shape)
|
||||
print('ShapeofXtrain:',X_test.shape)
|
||||
print('Shapeofytrain:',y_test.shape)
|
||||
```
|
||||
|
||||
> ShapeofXtrain: (60000, 784)
|
||||
> Shapeofytrain: (60000, 10)
|
||||
> ShapeofXtrain: (10000, 784)
|
||||
> Shapeofytrain: (10000, 10)
|
||||
|
||||
## 4. Вывод элементов обучающих данных
|
||||
* Создаем subplot для 4 изображений
|
||||
```
|
||||
for i in range(4):
|
||||
plt.subplot(1, 4, i+1) # 1 строка, n столбцов
|
||||
plt.imshow(X_train[i], cmap='gray')
|
||||
plt.axis('off') # убрать оси
|
||||
plt.title(y_train[i]) # метка под картинкой
|
||||
|
||||
plt.show()
|
||||
```
|
||||
|
||||

|
||||
|
||||
## 5. Предобработка данных
|
||||
* развернем каждое изображение 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('ShapeoftransformedXtrain:',X_train.shape)
|
||||
```
|
||||
|
||||
> ShapeoftransformedXtrain: (60000, 784)
|
||||
|
||||
* переведем метки в one-hot
|
||||
```
|
||||
from keras.utils import to_categorical
|
||||
y_train=to_categorical(y_train)
|
||||
y_test=to_categorical(y_test)
|
||||
print('Shapeoftransformedytrain:',y_train.shape)
|
||||
num_classes=y_train.shape[1]
|
||||
```
|
||||
|
||||
> Shapeoftransformedytrain: (60000, 10)
|
||||
* Вывод размерностей
|
||||
```
|
||||
print('ShapeofXtrain:',X_train.shape)
|
||||
print('Shapeofytrain:',y_train.shape)
|
||||
print('ShapeofXtrain:',X_test.shape)
|
||||
print('Shapeofytrain:',y_test.shape)
|
||||
```
|
||||
> ShapeofXtrain: (60000, 784)
|
||||
> Shapeofytrain: (60000, 10)
|
||||
> ShapeofXtrain: (10000, 784)
|
||||
> Shapeofytrain: (10000, 10)
|
||||
|
||||
## 6. Реализация и обучение однослойной нейронной сети
|
||||
```
|
||||
from keras.models import Sequential
|
||||
from keras.layers import Dense
|
||||
```
|
||||
|
||||
* 6.1. создаем модель - объявляем ее объектом класса Sequential
|
||||
```
|
||||
model=Sequential()
|
||||
model.add(Dense(input_dim=num_pixels,units=num_classes,activation='softmax'))
|
||||
```
|
||||
* 6.2. компилируем модель
|
||||
```
|
||||
model.compile(loss='categorical_crossentropy',optimizer='sgd',metrics=['accuracy'])
|
||||
```
|
||||
* Вывод информации об архитектуре модели
|
||||
```
|
||||
print(model.summary())
|
||||
```
|
||||
>Model: "sequential"
|
||||
>┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
|
||||
>┃ Layer (type) ┃ Output Shape ┃ Param # ┃
|
||||
>┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
|
||||
>│ dense (Dense) │ (None, 10) │ 7,850 │
|
||||
>└─────────────────────────────────┴────────────────────────┴───────────────┘
|
||||
> Total params: 7,850 (30.66 KB)
|
||||
> Trainable params: 7,850 (30.66 KB)
|
||||
> Non-trainable params: 0 (0.00 B)
|
||||
>None
|
||||
|
||||
* Обучаем модель
|
||||
```
|
||||
H=model.fit(X_train,y_train,validation_split=0.1,epochs=50)
|
||||
```
|
||||
|
||||
* Выводим график функции ошибки
|
||||
```
|
||||
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('Lossbyepochs')
|
||||
plt.show()
|
||||
```
|
||||
|
||||

|
||||
|
||||
## 7. Применение модели к тестовым данным
|
||||
```
|
||||
scores=model.evaluate(X_test,y_test)
|
||||
print('Loss on test data:',scores[0])
|
||||
print('Accuracy on test data:',scores[1])
|
||||
```
|
||||
|
||||
> 313/313 ━━━━━━━━━━━━━━━━━━━━ 1s 2ms/step - accuracy: 0.9207 - loss: 0.2944
|
||||
> Loss on test data: 0.2864772379398346
|
||||
> Accuracy on test data: 0.9229999780654907
|
||||
|
||||
## 8. Добавили один скрытый слой и повторили п. 6-7
|
||||
* при 100 нейронах в скрытом слое
|
||||
```
|
||||
model_1h100=Sequential()
|
||||
model_1h100.add(Dense(units=100,input_dim=num_pixels,activation='sigmoid'))
|
||||
model_1h100.add(Dense(units=num_classes,activation='softmax'))
|
||||
model_1h100.compile(loss='categorical_crossentropy',optimizer='sgd',metrics=['accuracy'])
|
||||
```
|
||||
* Вывод информации об архитектуре модели
|
||||
```
|
||||
print(model_1h100.summary())
|
||||
```
|
||||
> Model: "sequential_1"
|
||||
> ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
|
||||
> ┃ Layer (type) ┃ Output Shape ┃ Param # ┃
|
||||
> ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
|
||||
> │ dense_1 (Dense) │ (None, 100) │ 78,500 │
|
||||
> ├─────────────────────────────────┼────────────────────────┼───────────────┤
|
||||
> │ dense_2 (Dense) │ (None, 10) │ 1,010 │
|
||||
> └─────────────────────────────────┴────────────────────────┴───────────────┘
|
||||
> Total params: 79,510 (310.59 KB)
|
||||
> Trainable params: 79,510 (310.59 KB)
|
||||
> Non-trainable params: 0 (0.00 B)
|
||||
> None
|
||||
|
||||
* Обучаем модель
|
||||
```
|
||||
H=model_1h100.fit(X_train,y_train,validation_split=0.1,epochs=50)
|
||||
```
|
||||
|
||||
* Выводим график функции ошибки
|
||||
```
|
||||
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('Lossbyepochs')
|
||||
plt.show()
|
||||
```
|
||||
|
||||

|
||||
* Оценка качества работы модели на тестовых данных
|
||||
```
|
||||
scores=model_1h100.evaluate(X_test,y_test)
|
||||
print('Loss on test data:',scores[0])
|
||||
print('Accuracy on test data:',scores[1])
|
||||
```
|
||||
|
||||
> 313/313 ━━━━━━━━━━━━━━━━━━━━ 1s 3ms/step - accuracy: 0.9380 - loss: 0.2142
|
||||
> Loss on test data: 0.2046738713979721
|
||||
> Accuracy on test data: 0.942799985408783
|
||||
|
||||
* при 300 нейронах в скрытом слое
|
||||
```
|
||||
model_1h300=Sequential()
|
||||
model_1h300.add(Dense(units=300,input_dim=num_pixels,activation='sigmoid'))
|
||||
model_1h300.add(Dense(units=num_classes,activation='softmax'))
|
||||
model_1h300.compile(loss='categorical_crossentropy',optimizer='sgd',metrics=['accuracy'])
|
||||
```
|
||||
* Вывод информации об архитектуре модели
|
||||
```
|
||||
print(model_1h300.summary())
|
||||
```
|
||||
> Model: "sequential_2"
|
||||
> ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
|
||||
> ┃ Layer (type) ┃ Output Shape ┃ Param # ┃
|
||||
> ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
|
||||
> │ dense_3 (Dense) │ (None, 300) │ 235,500 │
|
||||
> ├─────────────────────────────────┼────────────────────────┼───────────────┤
|
||||
> │ dense_4 (Dense) │ (None, 10) │ 3,010 │
|
||||
> └─────────────────────────────────┴────────────────────────┴───────────────┘
|
||||
> Total params: 238,510 (931.68 KB)
|
||||
> Trainable params: 238,510 (931.68 KB)
|
||||
> Non-trainable params: 0 (0.00 B)
|
||||
> None
|
||||
|
||||
* Обучаем модель
|
||||
```
|
||||
H=model_1h300.fit(X_train,y_train,validation_split=0.1,epochs=50)
|
||||
```
|
||||
|
||||
* Выводим график функции ошибки
|
||||
```
|
||||
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('Lossbyepochs')
|
||||
plt.show()
|
||||
```
|
||||
|
||||

|
||||
|
||||
* Оценка качества работы модели на тестовых данных
|
||||
```
|
||||
scores=model_1h300.evaluate(X_test,y_test)
|
||||
print('Loss on test data:',scores[0])
|
||||
print('Accuracy on test data:',scores[1])
|
||||
```
|
||||
|
||||
>313/313 ━━━━━━━━━━━━━━━━━━━━ 1s 2ms/step - accuracy: 0.9328 - loss: 0.2403
|
||||
>Loss on test data: 0.23027946054935455
|
||||
>Accuracy on test data: 0.9363999962806702
|
||||
|
||||
* при 500 нейронах в скрытом слое
|
||||
```
|
||||
model_1h500=Sequential()
|
||||
model_1h500.add(Dense(units=500,input_dim=num_pixels,activation='sigmoid'))
|
||||
model_1h500.add(Dense(units=num_classes,activation='softmax'))
|
||||
model_1h500.compile(loss='categorical_crossentropy',optimizer='sgd',metrics=['accuracy'])
|
||||
```
|
||||
* Вывод информации об архитектуре модели
|
||||
```
|
||||
print(model_1h500.summary())
|
||||
```
|
||||
>Model: "sequential_3"
|
||||
>┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
|
||||
>┃ Layer (type) ┃ Output Shape ┃ Param # ┃
|
||||
>┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
|
||||
>│ dense_5 (Dense) │ (None, 500) │ 392,500 │
|
||||
>├─────────────────────────────────┼────────────────────────┼───────────────┤
|
||||
>│ dense_6 (Dense) │ (None, 10) │ 5,010 │
|
||||
>└─────────────────────────────────┴────────────────────────┴───────────────┘
|
||||
> Total params: 397,510 (1.52 MB)
|
||||
> Trainable params: 397,510 (1.52 MB)
|
||||
> Non-trainable params: 0 (0.00 B)
|
||||
>None
|
||||
|
||||
* Обучаем модель
|
||||
```
|
||||
H=model_1h500.fit(X_train,y_train,validation_split=0.1,epochs=50)
|
||||
```
|
||||
|
||||
* Выводим график функции ошибки
|
||||
```
|
||||
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('Lossbyepochs')
|
||||
plt.show()
|
||||
```
|
||||
|
||||

|
||||
|
||||
* Оценка качества работы модели на тестовых данных
|
||||
```
|
||||
scores=model_1h500.evaluate(X_test,y_test)
|
||||
print('Loss on test data:',scores[0])
|
||||
print('Accuracy on test data:',scores[1])
|
||||
```
|
||||
>313/313 ━━━━━━━━━━━━━━━━━━━━ 1s 2ms/step - accuracy: 0.9265 - loss: 0.2585
|
||||
>Loss on test data: 0.24952808022499084
|
||||
>Accuracy on test data: 0.9307000041007996
|
||||
|
||||
Как мы видим, лучшая метрика получилась равной 0.942799985408783 при архитектуре со 100 нейронами в скрытом слое, поэтому для дальнейших пунктов используем ее.
|
||||
|
||||
## 9. Добавили второй скрытый слой
|
||||
* при 50 нейронах во втором скрытом слое
|
||||
```
|
||||
model_1h100_2h50=Sequential()
|
||||
model_1h100_2h50.add(Dense(units=100,input_dim=num_pixels,activation='sigmoid'))
|
||||
model_1h100_2h50.add(Dense(units=50,activation='sigmoid'))
|
||||
model_1h100_2h50.add(Dense(units=num_classes,activation='softmax'))
|
||||
model_1h100_2h50.compile(loss='categorical_crossentropy',optimizer='sgd',metrics=['accuracy'])
|
||||
```
|
||||
* Вывод информации об архитектуре модели
|
||||
```
|
||||
print(model_1h100_2h50.summary())
|
||||
```
|
||||
> Model: "sequential_4"
|
||||
> ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
|
||||
> ┃ Layer (type) ┃ Output Shape ┃ Param # ┃
|
||||
> ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
|
||||
> │ dense_7 (Dense) │ (None, 100) │ 78,500 │
|
||||
> ├─────────────────────────────────┼────────────────────────┼───────────────┤
|
||||
> │ dense_8 (Dense) │ (None, 50) │ 5,050 │
|
||||
> ├─────────────────────────────────┼────────────────────────┼───────────────┤
|
||||
> │ dense_9 (Dense) │ (None, 10) │ 510 │
|
||||
> └─────────────────────────────────┴────────────────────────┴───────────────┘
|
||||
> Total params: 84,060 (328.36 KB)
|
||||
> Trainable params: 84,060 (328.36 KB)
|
||||
> Non-trainable params: 0 (0.00 B)
|
||||
> None
|
||||
|
||||
* Обучаем модель
|
||||
```
|
||||
H=model_1h100_2h50.fit(X_train,y_train,validation_split=0.1,epochs=50)
|
||||
```
|
||||
|
||||
* Выводим график функции ошибки
|
||||
```
|
||||
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('Lossbyepochs')
|
||||
plt.show()
|
||||
```
|
||||
|
||||

|
||||
|
||||
* Оценка качества работы модели на тестовых данных
|
||||
```
|
||||
scores=model_1h100_2h50.evaluate(X_test,y_test)
|
||||
print('Loss on test data:',scores[0])
|
||||
print('Accuracy on test data:',scores[1])
|
||||
```
|
||||
|
||||
>313/313 ━━━━━━━━━━━━━━━━━━━━ 1s 2ms/step - accuracy: 0.9388 - loss: 0.2173
|
||||
>Loss on test data: 0.20536193251609802
|
||||
>Accuracy on test data: 0.9416000247001648
|
||||
|
||||
* при 100 нейронах во втором скрытом слое
|
||||
```
|
||||
model_1h100_2h100=Sequential()
|
||||
model_1h100_2h100.add(Dense(units=100,input_dim=num_pixels,activation='sigmoid'))
|
||||
model_1h100_2h100.add(Dense(units=50,activation='sigmoid'))
|
||||
model_1h100_2h100.add(Dense(units=num_classes,activation='softmax'))
|
||||
model_1h100_2h100.compile(loss='categorical_crossentropy',optimizer='sgd',metrics=['accuracy'])
|
||||
```
|
||||
* Вывод информации об архитектуре модели
|
||||
```
|
||||
print(model_1h100_2h100.summary())
|
||||
```
|
||||
>Model: "sequential_5"
|
||||
>┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
|
||||
>┃ Layer (type) ┃ Output Shape ┃ Param # ┃
|
||||
>┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
|
||||
>│ dense_10 (Dense) │ (None, 100) │ 78,500 │
|
||||
>├─────────────────────────────────┼────────────────────────┼───────────────┤
|
||||
>│ dense_11 (Dense) │ (None, 50) │ 5,050 │
|
||||
>├─────────────────────────────────┼────────────────────────┼───────────────┤
|
||||
>│ dense_12 (Dense) │ (None, 10) │ 510 │
|
||||
>└─────────────────────────────────┴────────────────────────┴───────────────┘
|
||||
> Total params: 84,060 (328.36 KB)
|
||||
> Trainable params: 84,060 (328.36 KB)
|
||||
> Non-trainable params: 0 (0.00 B)
|
||||
>None
|
||||
|
||||
* Обучаем модель
|
||||
```
|
||||
H=model_1h100_2h100.fit(X_train,y_train,validation_split=0.1,epochs=50)
|
||||
```
|
||||
|
||||
* Выводим график функции ошибки
|
||||
```
|
||||
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('Lossbyepochs')
|
||||
plt.show()
|
||||
```
|
||||
|
||||

|
||||
|
||||
* Оценка качества работы модели на тестовых данных
|
||||
```
|
||||
scores=model_1h100_2h100.evaluate(X_test,y_test)
|
||||
print('Loss on test data:',scores[0])
|
||||
print('Accuracy on test data:',scores[1])
|
||||
```
|
||||
|
||||
>313/313 ━━━━━━━━━━━━━━━━━━━━ 1s 3ms/step - accuracy: 0.9414 - loss: 0.2154
|
||||
>Loss on test data: 0.2049565464258194
|
||||
>Accuracy on test data: 0.9427000284194946
|
||||
|
||||
Количество Количество нейронов в Количество нейронов во Значение метрики
|
||||
скрытых слоев первом скрытом слое втором скрытом слое качества классификации
|
||||
0 - - 0.9229999780654907
|
||||
1 100 - 0.942799985408783
|
||||
1 300 - 0.9363999962806702
|
||||
1 500 - 0.9307000041007996
|
||||
2 100 50 0.9416000247001648
|
||||
2 100 100 0.9427000284194946
|
||||
|
||||
Из таблицы видно, что лучше всего справились с задачей НС с одним скрытым слоем и 100 нейронами и НС с двумя скрытыми слоями по 100 нейронов.
|
||||
Метрика точности достигла почти 95% при достаточно простой архитектуре сетей, это может быть связано с тем, что датасет MNIST имеет только 60,000 обучающих примеров - недостаточно для более сложных архитектур. Также при усложнении архитектуры сети появляется риск переобучения. В нашей задаче мы видим, что при увеличении числа нейронов в скрытых слоях метрика падает.Простая модель лучше обобщает на подобных учебных датасетах, более сложные же архитектуры стоит использовать на более сложных датасетах, например ImageNet.
|
||||
|
||||
## 11. Сохранение наилучшей модели на диск
|
||||
```
|
||||
model_1h100.save('/content/drive/MyDrive/Colab Notebooks/best_model.keras')
|
||||
```
|
||||
|
||||
## 12. Вывод тестовых изображений и результатов распознаваний
|
||||
```
|
||||
for i in range(1,3,1):
|
||||
result=model_1h100.predict(X_test[i:i+1])
|
||||
print('NNoutput:',result)
|
||||
plt.imshow(X_test[i].reshape(28,28),cmap=plt.get_cmap('gray'))
|
||||
plt.show()
|
||||
print('Realmark:',str(np.argmax(y_test[i])))
|
||||
print('NNanswer:',str(np.argmax(result)))
|
||||
```
|
||||
|
||||
> NNoutput: [[1.4195202e-03 1.1157753e-03 1.3601109e-02 1.2154530e-01 4.0756597e-04
|
||||
8.3563459e-01 2.9775328e-03 7.1576833e-05 1.9775130e-02 3.4518384e-03]]
|
||||

|
||||
>Realmark: 3
|
||||
>NNanswer: 5
|
||||
> NNoutput: [[1.1838503e-04 1.7378072e-04 4.7975280e-03 9.3888867e-01 3.9176564e-05
|
||||
3.4841071e-03 1.5808465e-06 1.6603278e-02 1.6292465e-03 3.4264266e-02]]
|
||||

|
||||
>Realmark: 3
|
||||
>NNanswer: 3
|
||||
|
||||
## 13. Тестирование на собственных изображениях
|
||||
* загрузка 1 собственного изображения
|
||||
```
|
||||
from PIL import Image
|
||||
file_data=Image.open('/content/drive/MyDrive/Colab Notebooks/2.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_1h100.predict(test_img)
|
||||
print('Ithinkit\'s',np.argmax(result))
|
||||
```
|
||||
|
||||

|
||||
> Ithinkit's 2
|
||||
|
||||
* тест 2 изображения
|
||||
```
|
||||
from PIL import Image
|
||||
file_data=Image.open('/content/drive/MyDrive/Colab Notebooks/5.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_1h100.predict(test_img)
|
||||
print('Ithinkit\'s',np.argmax(result))
|
||||
```
|
||||
|
||||

|
||||
>Ithinkit's 5
|
||||
|
||||
Сеть не ошиблась и корректно распознала обе цифры на изображениях
|
||||
|
||||
## 14. Тестирование на собственных повернутых изображениях
|
||||
```
|
||||
from PIL import Image
|
||||
file_data=Image.open('/content/drive/MyDrive/Colab Notebooks/2_1.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_1h100.predict(test_img)
|
||||
print('Ithinkit\'s',np.argmax(result))
|
||||
```
|
||||

|
||||
>Ithinkit's 5
|
||||
|
||||
```
|
||||
from PIL import Image
|
||||
file_data=Image.open('/content/drive/MyDrive/Colab Notebooks/5_1.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_1h100.predict(test_img)
|
||||
print('Ithinkit\'s',np.argmax(result))
|
||||
```
|
||||
|
||||

|
||||
>Ithinkit's 7
|
||||
|
||||
При повороте изображений сеть не распознала цифры правильно. Так как она не обучалась на повернутых изображениях.
|
||||
|
После Ширина: | Высота: | Размер: 22 KiB |
|
После Ширина: | Высота: | Размер: 41 KiB |
|
После Ширина: | Высота: | Размер: 86 KiB |
|
После Ширина: | Высота: | Размер: 69 KiB |
|
После Ширина: | Высота: | Размер: 73 KiB |
|
После Ширина: | Высота: | Размер: 108 KiB |
|
После Ширина: | Высота: | Размер: 34 KiB |
|
После Ширина: | Высота: | Размер: 85 KiB |
|
После Ширина: | Высота: | Размер: 31 KiB |
|
После Ширина: | Высота: | Размер: 62 KiB |
|
После Ширина: | Высота: | Размер: 21 KiB |
|
После Ширина: | Высота: | Размер: 28 KiB |
|
После Ширина: | Высота: | Размер: 42 KiB |
|
После Ширина: | Высота: | Размер: 21 KiB |
|
После Ширина: | Высота: | Размер: 22 KiB |
@ -0,0 +1 @@
|
||||
1.86
|
||||
|
После Ширина: | Высота: | Размер: 36 KiB |
@ -0,0 +1 @@
|
||||
0.48
|
||||
|
После Ширина: | Высота: | Размер: 33 KiB |
@ -0,0 +1 @@
|
||||
3.1
|
||||
|
После Ширина: | Высота: | Размер: 30 KiB |
|
После Ширина: | Высота: | Размер: 45 KiB |
|
После Ширина: | Высота: | Размер: 72 KiB |
|
После Ширина: | Высота: | Размер: 76 KiB |
|
После Ширина: | Высота: | Размер: 112 KiB |
|
После Ширина: | Высота: | Размер: 89 KiB |
|
После Ширина: | Высота: | Размер: 89 KiB |
|
После Ширина: | Высота: | Размер: 102 KiB |
|
После Ширина: | Высота: | Размер: 65 KiB |
|
После Ширина: | Высота: | Размер: 78 KiB |
@ -0,0 +1,5 @@
|
||||
------------Оценка качества AE2 С ПОМОЩЬЮ НОВЫХ МЕТРИК------------
|
||||
Approx = 0.44186046511627913
|
||||
Excess = 1.263157894736842
|
||||
Deficit = 0.0
|
||||
Coating = 1.0
|
||||
|
После Ширина: | Высота: | Размер: 44 KiB |
@ -0,0 +1,371 @@
|
||||
# Отчет по лабораторной работе №2
|
||||
Текотова Виктория, Секирин Артем, А-02-22
|
||||
|
||||
# Задание 1.
|
||||
## 1. В среде GoogleColab создали блокнот(notebook.ipynb).
|
||||
```python
|
||||
import os
|
||||
os.chdir('/content/drive/MyDrive/Colab Notebooks')
|
||||
```
|
||||
|
||||
* импорт модулей
|
||||
```python
|
||||
import numpy as np
|
||||
import lab02_lib as lib
|
||||
```
|
||||
|
||||
## 2. Генерация датасета
|
||||
```python
|
||||
data=lib.datagen(1,1,1000,2)
|
||||
```
|
||||

|
||||
* Вывод данных и размерности
|
||||
```python
|
||||
print('Исходные данные:')
|
||||
print(data)
|
||||
print('Размерность данных:')
|
||||
print(data.shape)
|
||||
```
|
||||
> Исходные данные:
|
||||
>
|
||||
> [[1.13623025 1.07517135]
|
||||
>
|
||||
> [1.03093312 1.06813773]
|
||||
>
|
||||
> [0.97208689 1.0748715 ]
|
||||
>
|
||||
> ...
|
||||
> [1.19215258 0.990978 ]
|
||||
>
|
||||
> [0.95942384 0.94390713]
|
||||
>
|
||||
> [1.04279375 1.03934433]]
|
||||
>
|
||||
> Размерность данных:
|
||||
>
|
||||
> (1000, 2)
|
||||
|
||||
## 3. Создание и обучение автокодировщика AE1
|
||||
```python
|
||||
patience= 10
|
||||
ae1_trained, IRE1, IREth1= lib.create_fit_save_ae(data,'out/AE1.h5','out/AE1_ire_th.txt', 50, True, patience)
|
||||
```
|
||||
> Задать архитектуру автокодировщиков или использовать архитектуру по умолчанию? (1/2): 1
|
||||
>
|
||||
> Задайте количество скрытых слоёв (нечетное число) : 3
|
||||
>
|
||||
> Задайте архитектуру скрытых слоёв автокодировщика, например, в виде 3 1 3 : 3 1 3
|
||||
>
|
||||
> Epoch 1/50
|
||||
>
|
||||
> 1/1 ━━━━━━━━━━━━━━━━━━━━ 1s 1s/step - loss: 1.7463
|
||||
>
|
||||
> Epoch 2/50
|
||||
>
|
||||
> 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 32ms/step - loss: 1.7342
|
||||
>
|
||||
> ...
|
||||
>
|
||||
> Epoch 49/50
|
||||
>
|
||||
> 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 51ms/step - loss: 1.2118
|
||||
>
|
||||
> Epoch 50/50
|
||||
>
|
||||
> 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 50ms/step - loss: 1.2019
|
||||
|
||||
|
||||
|
||||
## 4. Построение графика ошибки реконструкции обучающей выборки. Вывод порога ошибки реконструкции – порога обнаружения аномалий.
|
||||
```python
|
||||
patience= 10
|
||||
ae1_trained, IRE1, IREth1= lib.create_fit_save_ae(data,'out/AE1.h5','out/AE1_ire_th.txt', 50, True, patience)
|
||||
```
|
||||

|
||||
```python
|
||||
print("Порог ошибки реконструкции = ",IREth1)
|
||||
```
|
||||
> Порог ошибки реконструкции = 0.63
|
||||
|
||||
## 5. Создание и обучиние второго автокодировщика AE2
|
||||
```python
|
||||
patience= 100
|
||||
ae2_trained, IRE2, IREth2= lib.create_fit_save_ae(data,'out/AE2.h5','out/AE2_ire_th.txt', 1000, True, patience)
|
||||
lib.ire_plot('training', IRE2, IREth2, 'AE2')
|
||||
```
|
||||
|
||||
> Задать архитектуру автокодировщиков или использовать архитектуру по умолчанию? (1/2): 2
|
||||
>
|
||||
> Epoch 1/1000
|
||||
>
|
||||
> 1/1 ━━━━━━━━━━━━━━━━━━━━ 1s 1s/step - loss: 1.0920
|
||||
>
|
||||
> Epoch 2/1000
|
||||
>
|
||||
> 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 31ms/step - loss: 1.0838
|
||||
>
|
||||
> ...
|
||||
>
|
||||
> Epoch 454/1000
|
||||
>
|
||||
> 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 48ms/step - loss: 0.0103
|
||||
>
|
||||
> Epoch 455/1000
|
||||
>
|
||||
> 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 48ms/step - loss: 0.0103
|
||||
|
||||
## 6. Построение графика ошибки реконструкции обучающей выборки. Вывод порога ошибки реконструкции – порога обнаружения аномалий.
|
||||
```python
|
||||
lib.ire_plot('training', IRE2, IREth2, 'AE2')
|
||||
```
|
||||

|
||||
```python
|
||||
print("Порог ошибки реконструкции = ",IREth2)
|
||||
```
|
||||
> Порог ошибки реконструкции = 0.48
|
||||
|
||||
## 7. Расчет характеристик качества обучения EDCA для AE1 и AE2. Визуализация и сравнение области пространства признаков,распознаваемые автокодировщиками AE1 и AE2. Вывод о пригодности AE1 и AE2 для качественного обнаружения аномалий.
|
||||
```python
|
||||
numb_square= 20
|
||||
xx,yy,Z1=lib.square_calc(numb_square,data,ae1_trained,IREth1,'1',True)
|
||||
```
|
||||
* Качество обучения AE1
|
||||

|
||||
> amount: 19
|
||||
>
|
||||
> amount_ae: 272
|
||||

|
||||
> Оценка качества AE1
|
||||
>
|
||||
> IDEAL = 0. Excess: 13.31578947368421
|
||||
>
|
||||
> IDEAL = 0. Deficit: 0.0
|
||||
>
|
||||
> IDEAL = 1. Coating: 1.0
|
||||
>
|
||||
> summa: 1.0
|
||||
>
|
||||
> IDEAL = 1. Extrapolation precision (Approx): 0.06985294117647059
|
||||
|
||||
* Качество обучения AE2
|
||||
```python
|
||||
numb_square= 20
|
||||
xx,yy,Z2=lib.square_calc(numb_square,data,ae2_trained,IREth2,'2',True)
|
||||
```
|
||||

|
||||
> amount: 19
|
||||
>
|
||||
> amount_ae: 43
|
||||

|
||||
> Оценка качества AE2
|
||||
>
|
||||
> IDEAL = 0. Excess: 1.263157894736842
|
||||
>
|
||||
> IDEAL = 0. Deficit: 0.0
|
||||
>
|
||||
> IDEAL = 1. Coating: 1.0
|
||||
>
|
||||
> summa: 1.0
|
||||
>
|
||||
> IDEAL = 1. Extrapolation precision (Approx): 0.44186046511627913
|
||||
|
||||
```python
|
||||
lib.plot2in1(data,xx,yy,Z1,Z2)
|
||||
```
|
||||

|
||||
* Вывод: На основе проведенного сравнения можно подытожить, что автокодировщик AE2 с пятислойной архитектурой является оптимальным решением, поскольку обеспечивает минимальную ошибку реконструкции по сравнению с более простой моделью AE1.
|
||||
## 8. Создание тестовой выборки
|
||||
```python
|
||||
test_data = np.array([[1.6, 1.2], [1.2, 1], [1.1, 1], [1.5,1.5], [1, 1], [1.5, 1.5]])
|
||||
```
|
||||
|
||||
## 9. Применение обученных автокодировщиков AE1 и AE2 к тестовым данным
|
||||
* Автокодировщик AE1
|
||||
```python
|
||||
predicted_labels1, ire1 = lib.predict_ae(ae1_trained, data_test, IREth1)
|
||||
lib.anomaly_detection_ae(predicted_labels1, ire1, IREth1)
|
||||
lib.ire_plot('test', ire1, IREth1, 'AE1')
|
||||
```
|
||||
* Аномалий не обнаружено
|
||||

|
||||
```python
|
||||
predicted_labels2, ire2 = lib.predict_ae(ae2_trained, data_test, IREth2)
|
||||
lib.anomaly_detection_ae(predicted_labels2, ire2, IREth2)
|
||||
lib.ire_plot('training', IRE2, IREth2, 'AE2')
|
||||
```
|
||||
* Аномалий не обнаружено
|
||||

|
||||
## 10. Визуализация элементов обучающей и тестовой выборки в областях пространства признаков
|
||||
* Построение областей аппроксимации и точек тестового набора
|
||||
```python
|
||||
lib.plot2in1_anomaly(data, xx, yy, Z1, Z2, data_test)
|
||||
```
|
||||

|
||||
## 11. Результаты исследования
|
||||
| Модель | Количество скрытых слоев | Количество нейронов в скрытых слоях | Количество эпох обучения | Ошибка MSE_stop | Порог ошибки реконструкции | Excess | Approx | Аномалии |
|
||||
|--------|:------------------------:|:-----------------------------------:|:------------------------:|:---------------:|:--------------------------:|:------:|:--------:|:--------:|
|
||||
| AE1 | 3 | 3 1 3 | 50 | 1.2019 | 0.63 | 13.31 | 0.069 | 0 |
|
||||
| AE2 | 5 | 3 2 1 2 3 | 1000 | 0.0103 | 0.48 | 1.26 | 0.44 | 0 |
|
||||
|
||||
|
||||
## 12. Выводы о требованиях
|
||||
Вывод:
|
||||
|
||||
Критерии качественного детектирования аномалий:
|
||||
|
||||
1. Данные: двумерный формат входных данных
|
||||
|
||||
2. Архитектура: наличие bottleneck-слоя уменьшенной размерности
|
||||
|
||||
3. Обучение: увеличение эпох при росте сложности сети
|
||||
|
||||
4. Качество: MSE_stop ∈ [0,1] и минимальная ошибка реконструкции
|
||||
|
||||
5. Метрики: Excess=0, Deficit=0, Coating=1, Approx=1"
|
||||
# Задание 2.
|
||||
## 1. Описание набора реальных данных
|
||||
Исходный набор данных Letter Recognition Data Set из репозитория машинного обучения UCI представляет собой набор данных для многоклассовой классификации. Набор предназначен для распознавания черно-белых пиксельных прямоугольников как одну из 26 заглавных букв английского алфавита, где буквы алфавита представлены в 16 измерениях. Чтобы получить данные, подходящие для обнаружения аномалий, была произведена подвыборка данных из 3 букв, чтобы сформировать нормальный класс, и случайным образом их пары были объединены так, чтобы их размерность удваивалась. Чтобы сформировать класс аномалий, случайным образом были выбраны несколько экземпляров букв, которые не входят нормальный класс, и они были объединены с экземплярами из нормального класса. Процесс объединения выполняется для того, чтобы сделать обнаружение более сложным, поскольку каждый аномальный пример также будет иметь некоторые нормальные значения признаков.
|
||||
|
||||
- Количество признаков - 32
|
||||
|
||||
- Количество примеров - 1600
|
||||
|
||||
- Количество нормальных примеров - 1500
|
||||
|
||||
- Количество аномальных примеров - 100
|
||||
|
||||
## 2. Загрузка многомерной обучающей выборки
|
||||
```python
|
||||
train= np.loadtxt('letter_train.txt', dtype=float)
|
||||
test = np.loadtxt('letter_test.txt', dtype=float)
|
||||
```
|
||||
## 3. Вывод данных и размера выборки
|
||||
```python
|
||||
print('Исходные данные:')
|
||||
print(train)
|
||||
print('Размерность данных:')
|
||||
print(train.shape)
|
||||
```
|
||||
> Исходные данные:
|
||||
>
|
||||
> [[ 6. 10. 5. ... 10. 2. 7.]
|
||||
>
|
||||
> [ 0. 6. 0. ... 8. 1. 7.]
|
||||
>
|
||||
> [ 4. 7. 5. ... 8. 2. 8.]
|
||||
>
|
||||
> ...
|
||||
>
|
||||
> [ 7. 10. 10. ... 8. 5. 6.]
|
||||
>
|
||||
> [ 7. 7. 10. ... 6. 0. 8.]
|
||||
>
|
||||
> [ 3. 4. 5. ... 9. 5. 5.]]
|
||||
>
|
||||
> Размерность данных:
|
||||
>
|
||||
> (1500, 32)
|
||||
|
||||
## 4. Создание и обучение автокодировщика с подходящей для данных архитектурой.
|
||||
```python
|
||||
ae3_trained, IRE3, IREth3 = lib.create_fit_save_ae(train,'out/AE3.h5','out/AE3_ire_th.txt',
|
||||
100000, False, 20000, early_stopping_delta = 0.001)
|
||||
```
|
||||
> Задать архитектуру автокодировщиков или использовать архитектуру по умолчанию? (1/2): 1
|
||||
>
|
||||
> Задайте количество скрытых слоёв (нечетное число) : 9
|
||||
>
|
||||
> Задайте архитектуру скрытых слоёв автокодировщика, например, в виде 3 1 3 : 64 48 32 24 16 24 32 48 64
|
||||
>
|
||||
> Epoch 1000/100000
|
||||
>
|
||||
> - loss: 6.0089
|
||||
>
|
||||
> Epoch 2000/100000
|
||||
>
|
||||
> - loss: 6.0089
|
||||
>
|
||||
> ...
|
||||
>
|
||||
>Epoch 99000/100000
|
||||
>
|
||||
> - loss: 0.0862
|
||||
>
|
||||
> Epoch 100000/100000
|
||||
>
|
||||
> - loss: 0.0864
|
||||
|
||||
## 5. Построение графика ошибки реконструкции обучающей выборки. Вывод порога ошибки реконструкции – порога обнаружения аномалий.
|
||||
```python
|
||||
lib.ire_plot('training', IRE3, IREth3, 'AE3')
|
||||
```
|
||||

|
||||
```python
|
||||
print("Порог ошибки реконструкции = ",IREth3)
|
||||
```
|
||||
> Порог ошибки реконструкции = 3.1
|
||||
## 6. Загрузка многомерной тестовой выборки
|
||||
```python
|
||||
print('Исходные данные:')
|
||||
print(test)
|
||||
print('Размерность данных:')
|
||||
print(test.shape)
|
||||
```
|
||||
> Исходные данные:
|
||||
>
|
||||
> [[ 8. 11. 8. ... 7. 4. 9.]
|
||||
>
|
||||
> [ 4. 5. 4. ... 13. 8. 8.]
|
||||
>
|
||||
> [ 3. 3. 5. ... 8. 3. 8.]
|
||||
>
|
||||
> ...
|
||||
>
|
||||
> [ 4. 9. 4. ... 8. 3. 8.]
|
||||
>
|
||||
> [ 6. 10. 6. ... 9. 8. 8.]
|
||||
>
|
||||
> [ 3. 1. 3. ... 9. 1. 7.]]
|
||||
>
|
||||
> Размерность данных:
|
||||
>
|
||||
> (100, 32)
|
||||
## 7. Выввод графика ошибки реконструкции элементов тестовой выборки относительно порога
|
||||
```python
|
||||
predicted_labels3, ire3 = lib.predict_ae(ae3_trained, test, IREth3)
|
||||
lib.anomaly_detection_ae(predicted_labels3, ire3, IREth3)
|
||||
lib.ire_plot('test', ire3, IREth3, 'AE3')
|
||||
```
|
||||
> i Labels IRE IREth
|
||||
>
|
||||
> 0 [1.] [6.51] 3.1
|
||||
>
|
||||
> 1 [1.] [8.23] 3.1
|
||||
>
|
||||
> 2 [1.] [8.73] 3.1
|
||||
>
|
||||
> ...
|
||||
>
|
||||
> 98 [1.] [6.18] 3.1
|
||||
>
|
||||
> 99 [1.] [5.91] 3.1
|
||||
>
|
||||
> Обнаружено 100.0 аномалий
|
||||
|
||||

|
||||
## 8. Параметры наилучшего автокодировщика и результаты обнаружения аномалий
|
||||
| Dataset name | Количество скрытых слоев | Количество нейронов в скрытых слоях | Количество эпох обучения | Ошибка MSE_stop | Порог ошибки реконструкции | % обнаруженных аномалий |
|
||||
|--------|:------------------------:|:-----------------------------------:|:------------------------:|:---------------:|:--------------------------:|:------:|
|
||||
| Letter | 9 | 64 48 32 24 16 24 32 48 64 | 100000 | 0.0864 | 3.1 | 100.0 |
|
||||
|
||||
## 9. Вывод о требованиях
|
||||
Вывод: Для качественного обнаружения аномалий в случае высокой размерности пространства признаков необходимо следующее:
|
||||
- Данные для обучения должны быть без аномалий, чтобы автокодировщик мог рассчитать верное пороговое значение.
|
||||
|
||||
- Архитектура автокодировщика должна постепенно сужаться к бутылочному горлышку, а затем постепенно возвращаться к исходным выходным размерам; количество скрытых слоев — 7-11.
|
||||
|
||||
- Обучение: в рамках данного набора данных оптимальное количество эпох — 100000 с параметром patience 20000 эпох.
|
||||
|
||||
- Качество: оптимальная ошибка MSE_stop должна быть около 0.1 (желательно не меньше для предотвращения переобучения).
|
||||
|
||||
- Порог: значение порога не должно превышать 3.1.Ю
|
||||
|
После Ширина: | Высота: | Размер: 121 KiB |
|
После Ширина: | Высота: | Размер: 11 KiB |
|
После Ширина: | Высота: | Размер: 11 KiB |
|
После Ширина: | Высота: | Размер: 60 KiB |
|
После Ширина: | Высота: | Размер: 6.8 KiB |
|
После Ширина: | Высота: | Размер: 7.1 KiB |
|
После Ширина: | Высота: | Размер: 32 KiB |
|
После Ширина: | Высота: | Размер: 32 KiB |
|
После Ширина: | Высота: | Размер: 6.8 KiB |
|
После Ширина: | Высота: | Размер: 6.6 KiB |
@ -0,0 +1,662 @@
|
||||
# Отчёт по лабораторной работе №3
|
||||
|
||||
**Текотова В.А., Секирин А.А. — А-02-22**
|
||||
|
||||
---
|
||||
## Задание 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)=3, где k=1 –номер бригады. Вывели размерности полученных обучающих и тестовых массивов данных.
|
||||
|
||||
```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 = 3)
|
||||
# вывод размерностей
|
||||
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()
|
||||
```
|
||||
**Model: "sequential"**
|
||||
|
||||
| Layer (type) | Output Shape | Param # |
|
||||
|--------------------------------|---------------------|--------:|
|
||||
| conv2d (Conv2D) | (None, 26, 26, 32) | 320 |
|
||||
| max_pooling2d_8 (MaxPooling2D) | (None, 13, 13, 32) | 0 |
|
||||
| conv2d_1 (Conv2D) | (None, 11, 11, 64) | 18,496 |
|
||||
| max_pooling2d_9 (MaxPooling2D) | (None, 5, 5, 64) | 0 |
|
||||
| dropout (Dropout) | (None, 5, 5, 64) | 0 |
|
||||
| flatten (Flatten) | (None, 1600) | 0 |
|
||||
| dense (Dense) | (None, 10) | 16,010 |
|
||||
|
||||
**Total params:** 34,826 (136.04 KB)
|
||||
|
||||
**Trainable params:** 34,826 (136.04 KB)
|
||||
|
||||
**Non-trainable params:** 0 (0.00 B)
|
||||
|
||||
|
||||
```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)
|
||||
```
|
||||
|
||||
Epoch 1/15
|
||||
|
||||
106/106 ━━━━━━━━━━━━━━━━━━━━ 6s 34ms/step - accuracy: 0.5991 - loss: 1.2739 - val_accuracy: 0.9427 - val_loss: 0.1933
|
||||
|
||||
Epoch 2/15
|
||||
|
||||
106/106 ━━━━━━━━━━━━━━━━━━━━ 1s 12ms/step - accuracy: 0.9363 - loss: 0.2175 - val_accuracy: 0.9645 - val_loss: 0.1128
|
||||
|
||||
...
|
||||
|
||||
Epoch 15/15
|
||||
|
||||
106/106 ━━━━━━━━━━━━━━━━━━━━ 1s 12ms/step - accuracy: 0.9851 - loss: 0.0460 - val_accuracy: 0.9895 - val_loss: 0.0350
|
||||
|
||||
<keras.src.callbacks.history.History at 0x78575e329e50>
|
||||
|
||||
### 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 ━━━━━━━━━━━━━━━━━━━━ 1s 3ms/step - accuracy: 0.9867 - loss: 0.0411
|
||||
|
||||
Loss on test data: 0.04398002102971077
|
||||
|
||||
Accuracy on test data: 0.9865000247955322
|
||||
|
||||
|
||||
|
||||
### 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))
|
||||
```
|
||||
|
||||
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 332ms/step
|
||||
|
||||
NN output: [[1.9338373e-09 8.8185527e-12 4.5429974e-08 2.5885814e-04 1.7587592e-08
|
||||
9.9952632e-01 1.1317411e-08 1.5951617e-08 1.6658140e-08 2.1473359e-04]]
|
||||
|
||||

|
||||
|
||||
Real mark: 5
|
||||
|
||||
NN answer: 5
|
||||
|
||||
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 28ms/step
|
||||
|
||||
NN output: [[2.6663812e-04 5.6896381e-09 3.4766167e-04 2.4042051e-09 2.7227568e-04
|
||||
6.0989500e-08 9.9911338e-01 2.0191379e-08 4.6584045e-08 1.9427532e-08]]
|
||||
|
||||

|
||||
|
||||
Real mark: 6
|
||||
|
||||
NN answer: 6
|
||||
|
||||
|
||||
### 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 0.99 0.99 1009
|
||||
|
||||
1 0.99 1.00 1.00 1147
|
||||
|
||||
2 0.98 0.98 0.98 969
|
||||
|
||||
3 0.98 0.99 0.99 1025
|
||||
|
||||
4 0.99 0.98 0.99 939
|
||||
|
||||
5 0.98 0.98 0.98 881
|
||||
|
||||
6 0.99 0.99 0.99 1037
|
||||
|
||||
7 0.98 0.99 0.98 1001
|
||||
|
||||
8 0.99 0.98 0.98 950
|
||||
|
||||
9 0.99 0.98 0.98 1042
|
||||
|
||||
|
||||
accuracy 0.99 10000
|
||||
|
||||
macro avg 0.99 0.99 0.99 10000
|
||||
|
||||
weighted avg 0.99 0.99 0.99 10000
|
||||
```
|
||||
|
||||

|
||||
|
||||
### 9) Загрузили, предобработали и подали на вход обученной нейронной сети собственное изображение, созданное при выполнении лабораторной работы №1. Вывели изображение и результат распознавания.
|
||||
|
||||
```python
|
||||
# загрузка собственного изображения
|
||||
from PIL import Image
|
||||
|
||||
for name_image in ['цифра 3.png', 'цифра 6.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))
|
||||
```
|
||||

|
||||
|
||||
I think it's 2
|
||||
|
||||

|
||||
|
||||
I think it's 5
|
||||
|
||||
|
||||
### 10) Загрузили с диска модель, сохраненную при выполнении лабораторной работы №1. Вывели информацию об архитектуре модели. Повторили для этой модели п. 6.
|
||||
|
||||
```python
|
||||
model_lr1 = keras.models.load_model("model_1h100_2h50.keras")
|
||||
|
||||
model_lr1.summary()
|
||||
```
|
||||
**Model: "sequential_10"**
|
||||
|
||||
| Layer (type) | Output Shape | Param # |
|
||||
|------------------|-------------:|--------:|
|
||||
| dense_1 (Dense) | (None, 100) | 78,500 |
|
||||
| dense_2 (Dense) | (None, 10) | 1,010 |
|
||||
|
||||
**Total params:** 79,512 (310.60 KB)
|
||||
|
||||
**Trainable params:** 79,510 (310.59 KB)
|
||||
|
||||
**Non-trainable params:** 0 (0.00 B)
|
||||
|
||||
**Optimizer params:** 2 (12.00 B)
|
||||
|
||||
|
||||
```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 = 3)
|
||||
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 ━━━━━━━━━━━━━━━━━━━━ 1s 2ms/step - accuracy: 0.9452 - loss: 0.1976
|
||||
|
||||
Loss on test data: 0.19490210711956024
|
||||
|
||||
Accuracy on test data: 0.944599986076355
|
||||
|
||||
|
||||
### 11) Сравнили обученную модель сверточной сети и наилучшую модель полносвязной сети из лабораторной работы №1 по следующим показателям:
|
||||
### - количество настраиваемых параметров в сети
|
||||
### - количество эпох обучения
|
||||
### - качество классификации тестовой выборки.
|
||||
### Сделали выводы по результатам применения сверточной нейронной сети для распознавания изображений.
|
||||
|
||||
| Модель | Количество настраиваемых параметров | Количество эпох обучения | Качество классификации тестовой выборки |
|
||||
|----------|-------------------------------------|---------------------------|-----------------------------------------|
|
||||
| Сверточная | 34 826 | 15 | accuracy:0.986 ; loss:0.044 |
|
||||
| Полносвязная | 84 062 | 50 | accuracy:0.944 ; loss:0.195 |
|
||||
|
||||
|
||||
##### Вывод:Сравнительный анализ показывает явное преимущество свёрточной нейронной сети перед полносвязной в задачах распознавания изображений: при вдвое меньшем количестве параметров (34 826 против 79 512) и трёхкратном сокращении числа эпох обучения (15 против 50) CNN достигает более высокой точности (98,65% против 94,46%) и значительно меньшей ошибки (0,044 против 0,195).
|
||||
|
||||
## Задание 2
|
||||
|
||||
### 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)=23, где k=6 –номер бригады. Вывели размерности полученных обучающих и тестовых массивов данных.
|
||||
|
||||
```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 = 3)
|
||||
# вывод размерностей
|
||||
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()
|
||||
```
|
||||

|
||||
|
||||
### 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()
|
||||
```
|
||||
**Model: "sequential_9"**
|
||||
|
||||
| Layer (type) | Output Shape | Param # |
|
||||
|--------------------------------------------|-------------------|---------:|
|
||||
| conv2d_16 (Conv2D) | (None, 32, 32, 32) | 896 |
|
||||
| batch_normalization_12 (BatchNormalization) | (None, 32, 32, 32) | 128 |
|
||||
| conv2d_17 (Conv2D) | (None, 32, 32, 32) | 9,248 |
|
||||
| batch_normalization_13 (BatchNormalization) | (None, 32, 32, 32) | 128 |
|
||||
| max_pooling2d_10 (MaxPooling2D) | (None, 16, 16, 32) | 0 |
|
||||
| dropout_10 (Dropout) | (None, 16, 16, 32) | 0 |
|
||||
| conv2d_18 (Conv2D) | (None, 16, 16, 64) | 18,496 |
|
||||
| batch_normalization_14 (BatchNormalization) | (None, 16, 16, 64) | 256 |
|
||||
| conv2d_19 (Conv2D) | (None, 16, 16, 64) | 36,928 |
|
||||
| batch_normalization_15 (BatchNormalization) | (None, 16, 16, 64) | 256 |
|
||||
| max_pooling2d_11 (MaxPooling2D) | (None, 8, 8, 64) | 0 |
|
||||
| dropout_11 (Dropout) | (None, 8, 8, 64) | 0 |
|
||||
| conv2d_20 (Conv2D) | (None, 8, 8, 128) | 73,856 |
|
||||
| batch_normalization_16 (BatchNormalization)| (None, 8, 8, 128) | 512 |
|
||||
| conv2d_21 (Conv2D) | (None, 8, 8, 128) | 147,584 |
|
||||
| batch_normalization_17 (BatchNormalization)| (None, 8, 8, 128) | 512 |
|
||||
| max_pooling2d_12 (MaxPooling2D) | (None, 4, 4, 128) | 0 |
|
||||
| dropout_12 (Dropout) | (None, 4, 4, 128) | 0 |
|
||||
| flatten_4 (Flatten) | (None, 2048) | 0 |
|
||||
| dense_6 (Dense) | (None, 128) | 262,272 |
|
||||
| dropout_13 (Dropout) | (None, 128) | 0 |
|
||||
| dense_7 (Dense) | (None, 10) | 1,290 |
|
||||
|
||||
**Total params:** 552,362 (2.11 MB)
|
||||
|
||||
**Trainable params:** 551,466 (2.10 MB)
|
||||
|
||||
**Non-trainable params:** 896 (3.50 KB)
|
||||
|
||||
```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)
|
||||
```
|
||||
|
||||
Epoch 1/50
|
||||
|
||||
704/704 ━━━━━━━━━━━━━━━━━━━━ 25s 21ms/step - accuracy: 0.2474 - loss: 2.1347 - val_accuracy: 0.5014 - val_loss: 1.3804
|
||||
|
||||
Epoch 2/50
|
||||
|
||||
704/704 ━━━━━━━━━━━━━━━━━━━━ 7s 10ms/step - accuracy: 0.4517 - loss: 1.4843 - val_accuracy: 0.5648 - val_loss: 1.2039
|
||||
|
||||
...
|
||||
|
||||
Epoch 50/50
|
||||
|
||||
704/704 ━━━━━━━━━━━━━━━━━━━━ 9s 13ms/step - accuracy: 0.9183 - loss: 0.2363 - val_accuracy: 0.8370 - val_loss: 0.5748
|
||||
|
||||
|
||||
### 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.8535 - loss: 0.5236
|
||||
|
||||
Loss on test data: 0.5263504981994629
|
||||
|
||||
Accuracy on test data: 0.8525000214576721
|
||||
|
||||
|
||||
### 6) Подали на вход обученной модели два тестовых изображения. Вывели изображения, истинные метки и результаты распознавания.
|
||||
|
||||
```python
|
||||
# вывод двух тестовых изображений и результатов распознавания
|
||||
|
||||
for n in [3,15]:
|
||||
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))
|
||||
```
|
||||
|
||||
1/1 ━━━━━━━━━━━━━━━━━━━━ 1s 662ms/step
|
||||
|
||||
NN output: [[3.9128518e-13 3.7927967e-14 9.7535979e-10 9.2453198e-11 2.2669273e-13
|
||||
4.2581650e-13 1.0000000e+00 2.1332333e-19 5.8570602e-13 1.1833489e-11]]
|
||||
|
||||
|
||||

|
||||
|
||||
Real mark: 6
|
||||
|
||||
NN answer: 6
|
||||
|
||||
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 40ms/step
|
||||
|
||||
NN output: [[9.5250229e-08 5.8261224e-10 2.7865291e-05 2.9105169e-03 9.8321760e-01
|
||||
1.3797697e-02 2.7701269e-06 4.3220436e-05 2.0006892e-08 1.8016836e-07]]
|
||||
|
||||

|
||||
|
||||
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()
|
||||
```
|
||||
```
|
||||
313/313 ━━━━━━━━━━━━━━━━━━━━ 2s 4ms/step
|
||||
|
||||
precision recall f1-score support
|
||||
|
||||
|
||||
airplane 0.90 0.84 0.87 1007
|
||||
|
||||
automobile 0.92 0.93 0.93 1037
|
||||
|
||||
bird 0.86 0.78 0.82 1030
|
||||
|
||||
cat 0.68 0.72 0.70 990
|
||||
|
||||
deer 0.84 0.83 0.83 966
|
||||
|
||||
dog 0.77 0.79 0.78 1009
|
||||
|
||||
frog 0.78 0.94 0.86 972
|
||||
|
||||
horse 0.95 0.84 0.89 991
|
||||
|
||||
ship 0.94 0.93 0.94 990
|
||||
|
||||
truck 0.91 0.92 0.92 1008
|
||||
|
||||
|
||||
accuracy 0.85 10000
|
||||
|
||||
macro avg 0.86 0.85 0.85 10000
|
||||
|
||||
weighted avg 0.86 0.85 0.85 10000
|
||||
```
|
||||
|
||||

|
||||
|
||||
#### Сводная точность модели на тестовой выборке CIFAR-10 составила 85%, что свидетельствует о её эффективности в решении задачи классификации цветных изображений.
|
||||
|
После Ширина: | Высота: | Размер: 21 KiB |
@ -0,0 +1,321 @@
|
||||
{
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"provenance": [],
|
||||
"gpuType": "T4"
|
||||
},
|
||||
"kernelspec": {
|
||||
"name": "python3",
|
||||
"display_name": "Python 3"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
},
|
||||
"accelerator": "GPU"
|
||||
},
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# импорт модулей\n",
|
||||
"import os\n",
|
||||
"os.chdir('/content/drive/MyDrive/Colab Notebooks/is_lab4')\n",
|
||||
"\n",
|
||||
"from tensorflow import keras\n",
|
||||
"from tensorflow.keras import layers\n",
|
||||
"from tensorflow.keras.models import Sequential\n",
|
||||
"import matplotlib.pyplot as plt\n",
|
||||
"import numpy as np\n"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "mr9IszuQ1ANG"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"from google.colab import drive\n",
|
||||
"drive.mount('/content/drive')"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "f0Sa1hdp4hQd"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"import tensorflow as tf\n",
|
||||
"device_name = tf.test.gpu_device_name()\n",
|
||||
"if device_name != '/device:GPU:0':\n",
|
||||
" raise SystemError('GPU device not found')\n",
|
||||
"print('Found GPU at: {}'.format(device_name))"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "o63-lKG_RuNc"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# загрузка датасета\n",
|
||||
"from keras.datasets import imdb\n",
|
||||
"\n",
|
||||
"vocabulary_size = 5000\n",
|
||||
"index_from = 3\n",
|
||||
"\n",
|
||||
"(X_train, y_train), (X_test, y_test) = imdb.load_data(\n",
|
||||
" path=\"imdb.npz\",\n",
|
||||
" num_words=vocabulary_size,\n",
|
||||
" skip_top=0,\n",
|
||||
" maxlen=None,\n",
|
||||
" seed=3,\n",
|
||||
" start_char=1,\n",
|
||||
" oov_char=2,\n",
|
||||
" index_from=index_from\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
"# вывод размерностей\n",
|
||||
"print('Shape of X train:', X_train.shape)\n",
|
||||
"print('Shape of y train:', y_train.shape)\n",
|
||||
"print('Shape of X test:', X_test.shape)\n",
|
||||
"print('Shape of y test:', y_test.shape)"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "Ixw5Sp0_1A-w"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# создание словаря для перевода индексов в слова\n",
|
||||
"# заргузка словаря \"слово:индекс\"\n",
|
||||
"word_to_id = imdb.get_word_index()\n",
|
||||
"# уточнение словаря\n",
|
||||
"word_to_id = {key:(value + index_from) for key,value in word_to_id.items()}\n",
|
||||
"word_to_id[\"<PAD>\"] = 0\n",
|
||||
"word_to_id[\"<START>\"] = 1\n",
|
||||
"word_to_id[\"<UNK>\"] = 2\n",
|
||||
"word_to_id[\"<UNUSED>\"] = 3\n",
|
||||
"# создание обратного словаря \"индекс:слово\"\n",
|
||||
"id_to_word = {value:key for key,value in word_to_id.items()}"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "9W3RklPcZyH0"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"print(X_train[26])\n",
|
||||
"print('len:',len(X_train[26]))"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "Nu-Bs1jnaYhB"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"review_as_text = ' '.join(id_to_word[id] for id in X_train[26])\n",
|
||||
"print(review_as_text)\n",
|
||||
"print('len:',len(review_as_text))"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "JhTwTurtZ6Sp"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"print('MAX Len: ',len(max(X_train, key=len)))\n",
|
||||
"print('MIN Len: ',len(min(X_train, key=len)))"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "xJH87ISq1B9h"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# предобработка данных\n",
|
||||
"from tensorflow.keras.utils import pad_sequences\n",
|
||||
"max_words = 500\n",
|
||||
"X_train = pad_sequences(X_train, maxlen=max_words, value=0, padding='pre', truncating='post')\n",
|
||||
"X_test = pad_sequences(X_test, maxlen=max_words, value=0, padding='pre', truncating='post')"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "lrF-B2aScR4t"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"print('MAX Len: ',len(max(X_train, key=len)))\n",
|
||||
"print('MIN Len: ',len(min(X_train, key=len)))"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "81Cgq8dn9uL6"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"print(X_train[26])\n",
|
||||
"print('len:',len(X_train[26]))"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "vudlgqoCbjU1"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"review_as_text = ' '.join(id_to_word[id] for id in X_train[26])\n",
|
||||
"print(review_as_text)\n",
|
||||
"print('len:',len(review_as_text))"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "dbfkWjDI1Dp7"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# вывод данных\n",
|
||||
"print('X train: \\n',X_train)\n",
|
||||
"print('X train: \\n',X_test)\n",
|
||||
"\n",
|
||||
"# вывод размерностей\n",
|
||||
"print('Shape of X train:', X_train.shape)\n",
|
||||
"print('Shape of X test:', X_test.shape)"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "7MqcG_wl1EHI"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"embed_dim = 32\n",
|
||||
"lstm_units = 64\n",
|
||||
"\n",
|
||||
"model = Sequential()\n",
|
||||
"model.add(layers.Embedding(input_dim=vocabulary_size, output_dim=embed_dim, input_length=max_words, input_shape=(max_words,)))\n",
|
||||
"model.add(layers.LSTM(lstm_units))\n",
|
||||
"model.add(layers.Dropout(0.5))\n",
|
||||
"model.add(layers.Dense(1, activation='sigmoid'))\n",
|
||||
"\n",
|
||||
"model.summary()"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "ktWEeqWd1EyF"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# компилируем и обучаем модель\n",
|
||||
"batch_size = 64\n",
|
||||
"epochs = 3\n",
|
||||
"model.compile(loss=\"binary_crossentropy\", optimizer=\"adam\", metrics=[\"accuracy\"])\n",
|
||||
"model.fit(X_train, y_train, batch_size=batch_size, epochs=epochs, validation_split=0.2)"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "CuPqKpX0kQfP"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"test_loss, test_acc = model.evaluate(X_test, y_test)\n",
|
||||
"print(f\"\\nTest accuracy: {test_acc}\")"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "hJIWinxymQjb"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"#значение метрики качества классификации на тестовых данных\n",
|
||||
"print(f\"\\nTest accuracy: {test_acc}\")"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "Rya5ABT8msha"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"#отчет о качестве классификации тестовой выборки\n",
|
||||
"y_score = model.predict(X_test)\n",
|
||||
"y_pred = [1 if y_score[i,0]>=0.5 else 0 for i in range(len(y_score))]\n",
|
||||
"\n",
|
||||
"from sklearn.metrics import classification_report\n",
|
||||
"print(classification_report(y_test, y_pred, labels = [0, 1], target_names=['Negative', 'Positive']))"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "2kHjcmnCmv0Y"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"#построение ROC-кривой и AUC ROC\n",
|
||||
"from sklearn.metrics import roc_curve, auc\n",
|
||||
"\n",
|
||||
"fpr, tpr, thresholds = roc_curve(y_test, y_score)\n",
|
||||
"plt.plot(fpr, tpr)\n",
|
||||
"plt.grid()\n",
|
||||
"plt.xlabel('False Positive Rate')\n",
|
||||
"plt.ylabel('True Positive Rate')\n",
|
||||
"plt.title('ROC')\n",
|
||||
"plt.show()\n",
|
||||
"print('AUC ROC:', auc(fpr, tpr))"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "Kp4AQRbcmwAx"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,372 @@
|
||||
# Отчёт по лабораторной работе №4
|
||||
|
||||
**Текотова Виктория, Секирин Артем — А-02-22**
|
||||
|
||||
---
|
||||
## Задание 1
|
||||
|
||||
### 1) В среде Google Colab создали новый блокнот (notebook). Импортировали необходимые для работы библиотеки и модули. Настроили блокнот для работы с аппаратным ускорителем GPU.
|
||||
|
||||
```python
|
||||
# импорт модулей
|
||||
import os
|
||||
os.chdir('/content/drive/MyDrive/Colab Notebooks/is_lab4')
|
||||
|
||||
from tensorflow import keras
|
||||
from tensorflow.keras import layers
|
||||
from tensorflow.keras.models import Sequential
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
```
|
||||
```python
|
||||
import tensorflow as tf
|
||||
device_name = tf.test.gpu_device_name()
|
||||
if device_name != '/device:GPU:0':
|
||||
raise SystemError('GPU device not found')
|
||||
print('Found GPU at: {}'.format(device_name))
|
||||
```
|
||||
>Found GPU at: /device:GPU:0
|
||||
|
||||
### 2) Загрузили набор данных IMDb, содержащий оцифрованные отзывы на фильмы, размеченные на два класса: позитивные и негативные. При загрузке набора данных параметр seed выбрали равным значению (4k – 1)=3, где k=1 – номер бригады. Вывели размеры полученных обучающих и тестовых массивов данных.
|
||||
|
||||
```python
|
||||
# загрузка датасета
|
||||
from keras.datasets import imdb
|
||||
|
||||
vocabulary_size = 5000
|
||||
index_from = 3
|
||||
|
||||
(X_train, y_train), (X_test, y_test) = imdb.load_data(
|
||||
path="imdb.npz",
|
||||
num_words=vocabulary_size,
|
||||
skip_top=0,
|
||||
maxlen=None,
|
||||
seed=3,
|
||||
start_char=1,
|
||||
oov_char=2,
|
||||
index_from=index_from
|
||||
)
|
||||
|
||||
# вывод размерностей
|
||||
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: (25000,)
|
||||
>
|
||||
>Shape of y train: (25000,)
|
||||
>
|
||||
>Shape of X test: (25000,)
|
||||
>
|
||||
>Shape of y test: (25000,)
|
||||
|
||||
|
||||
### 3) Вывели один отзыв из обучающего множества в виде списка индексов слов. Преобразовали список индексов в текст и вывели отзыв в виде текста. Вывели длину отзыва. Вывели метку класса данного отзыва и название класса (1 – Positive, 0 – Negative).
|
||||
|
||||
```python
|
||||
# создание словаря для перевода индексов в слова
|
||||
# заргузка словаря "слово:индекс"
|
||||
word_to_id = imdb.get_word_index()
|
||||
# уточнение словаря
|
||||
word_to_id = {key:(value + index_from) for key,value in word_to_id.items()}
|
||||
word_to_id["<PAD>"] = 0
|
||||
word_to_id["<START>"] = 1
|
||||
word_to_id["<UNK>"] = 2
|
||||
word_to_id["<UNUSED>"] = 3
|
||||
# создание обратного словаря "индекс:слово"
|
||||
id_to_word = {value:key for key,value in word_to_id.items()}
|
||||
```
|
||||
```python
|
||||
print(X_train[26])
|
||||
print('len:',len(X_train[26]))
|
||||
```
|
||||
|
||||
> [1, 37, 1388, 4, 2739, 495, 94, 96, 143, 49, 2, 875, 551, 19, 195, 2210, 5, 1698, 8, 401, 4, 65, 24, 64, 1728, 21, 400, 642, 45, 77, 6, 137, 237, 207, 258, 141, 6, 1562, 1301, 1562, 737, 22, 10, 10, 4, 22, 9, 1490, 3862, 4, 744, 19, 307, 1385, 5, 2, 2, 4, 2, 2656, 2, 1669, 19, 4, 1074, 200, 4, 55, 406, 55, 3048, 5, 246, 55, 1451, 105, 688, 8, 4, 321, 177, 32, 677, 7, 4, 678, 1850, 26, 1669, 221, 5, 3921, 10, 10, 13, 386, 37, 1388, 4, 2739, 45, 6, 66, 163, 20, 15, 304, 6, 3049, 168, 33, 4, 4352, 15, 75, 70, 2, 23, 257, 85, 5, 4, 2789, 878, 21, 1305, 2, 1773, 7, 2]
|
||||
>
|
||||
> len: 130
|
||||
>
|
||||
```python
|
||||
review_as_text = ' '.join(id_to_word[id] for id in X_train[26])
|
||||
print(review_as_text)
|
||||
print('len:',len(review_as_text))
|
||||
```
|
||||
|
||||
> <START> who loves the sun works its way through some <UNK> subject matter with enough wit and grace to keep the story not only engaging but often hilarious it's been a while since i've found such a thoroughly touching thoroughly enjoyable film br br the film is gorgeous drawing the eye with beautiful scenery and <UNK> <UNK> the <UNK> imagery <UNK> wonderfully with the tension between the very human very flawed and yet very likable characters due to the excellent cast all five of the major players are wonderfully interesting and dynamic br br i recommend who loves the sun it's a really funny movie that takes a poignant look at the hurts that we can <UNK> on each other and the amazingly difficult but equally <UNK> process of <UNK>
|
||||
> len: 738
|
||||
|
||||
### 4) Вывели максимальную и минимальную длину отзыва в обучающем множестве.
|
||||
|
||||
```python
|
||||
print('MAX Len: ',len(max(X_train, key=len)))
|
||||
print('MIN Len: ',len(min(X_train, key=len)))
|
||||
```
|
||||
> MAX Len: 2494
|
||||
>
|
||||
> MIN Len: 11
|
||||
|
||||
|
||||
### 5) Провели предобработку данных. Выбрали единую длину, к которой будут приведены все отзывы. Короткие отзывы дополнили спецсимволами, а длинные обрезали до выбранной длины.
|
||||
|
||||
```python
|
||||
# предобработка данных
|
||||
from tensorflow.keras.utils import pad_sequences
|
||||
max_words = 500
|
||||
X_train = pad_sequences(X_train, maxlen=max_words, value=0, padding='pre', truncating='post')
|
||||
X_test = pad_sequences(X_test, maxlen=max_words, value=0, padding='pre', truncating='post')
|
||||
```
|
||||
|
||||
### 6) Повторили пункт 4.
|
||||
|
||||
```python
|
||||
print('MAX Len: ',len(max(X_train, key=len)))
|
||||
print('MIN Len: ',len(min(X_train, key=len)))
|
||||
```
|
||||
> MAX Len: 500
|
||||
>
|
||||
> MIN Len: 500
|
||||
|
||||
|
||||
### 7) Повторили пункт 3. Сделали вывод о том, как отзыв преобразовался после предобработки.
|
||||
```python
|
||||
print(X_train[26])
|
||||
print('len:',len(X_train[26]))
|
||||
```
|
||||
|
||||
> [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 1 37 1388 4 2739 495 94 96
|
||||
143 49 2 875 551 19 195 2210 5 1698 8 401 4 65
|
||||
24 64 1728 21 400 642 45 77 6 137 237 207 258 141
|
||||
6 1562 1301 1562 737 22 10 10 4 22 9 1490 3862 4
|
||||
744 19 307 1385 5 2 2 4 2 2656 2 1669 19 4
|
||||
1074 200 4 55 406 55 3048 5 246 55 1451 105 688 8
|
||||
4 321 177 32 677 7 4 678 1850 26 1669 221 5 3921
|
||||
10 10 13 386 37 1388 4 2739 45 6 66 163 20 15
|
||||
304 6 3049 168 33 4 4352 15 75 70 2 23 257 85
|
||||
5 4 2789 878 21 1305 2 1773 7 2]
|
||||
>
|
||||
> len: 500
|
||||
|
||||
|
||||
```python
|
||||
review_as_text = ' '.join(id_to_word[id] for id in X_train[26])
|
||||
print(review_as_text)
|
||||
print('len:',len(review_as_text))
|
||||
```
|
||||
|
||||
> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <START> who loves the sun works its way through some <UNK> subject matter with enough wit and grace to keep the story not only engaging but often hilarious it's been a while since i've found such a thoroughly touching thoroughly enjoyable film br br the film is gorgeous drawing the eye with beautiful scenery and <UNK> <UNK> the <UNK> imagery <UNK> wonderfully with the tension between the very human very flawed and yet very likable characters due to the excellent cast all five of the major players are wonderfully interesting and dynamic br br i recommend who loves the sun it's a really funny movie that takes a poignant look at the hurts that we can <UNK> on each other and the amazingly difficult but equally <UNK> process of <UNK>
|
||||
>
|
||||
> len: 2958
|
||||
|
||||
#### После обработки в начало отзыва добавилось необходимое количество токенов <PAD>, чтобы отзыв был длинной в 500 индексов.
|
||||
|
||||
|
||||
### 8) Вывели предобработанные массивы обучающих и тестовых данных и их размерности.
|
||||
|
||||
```python
|
||||
# вывод данных
|
||||
print('X train: \n',X_train)
|
||||
print('X train: \n',X_test)
|
||||
|
||||
# вывод размерностей
|
||||
print('Shape of X train:', X_train.shape)
|
||||
print('Shape of X test:', X_test.shape)
|
||||
```
|
||||
|
||||
> X train:
|
||||
>
|
||||
> [[ 0 0 0 ... 12 38 76]
|
||||
>
|
||||
> [ 0 0 0 ... 33 4 130]
|
||||
>
|
||||
> [ 0 0 0 ... 437 7 58]
|
||||
>
|
||||
> ...
|
||||
>
|
||||
> [ 0 0 0 ... 1874 1553 422]
|
||||
>
|
||||
> [ 0 0 0 ... 18 1552 234]
|
||||
>
|
||||
> [ 0 0 0 ... 7 87 1090]]
|
||||
>
|
||||
>X train:
|
||||
>
|
||||
> [[ 0 0 0 ... 6 194 717]
|
||||
>
|
||||
> [ 0 0 0 ... 30 87 292]
|
||||
>
|
||||
> [ 0 0 0 ... 495 55 73]
|
||||
>
|
||||
> ...
|
||||
>
|
||||
> [ 0 0 0 ... 7 12 908]
|
||||
>
|
||||
> [ 0 0 0 ... 61 477 2302]
|
||||
>
|
||||
> [ 0 0 0 ... 5 68 4580]]
|
||||
>
|
||||
>Shape of X train: (25000, 500)
|
||||
>
|
||||
>Shape of X test: (25000, 500)
|
||||
>
|
||||
|
||||
|
||||
### 9) Реализовали модель рекуррентной нейронной сети, состоящей из слоев Embedding, LSTM, Dropout, Dense, и обучили ее на обучающих данных с выделением части обучающих данных в качестве валидационных. Вывели информацию об архитектуре нейронной сети. Добились качества обучения по метрике accuracy не менее 0.8.
|
||||
|
||||
```python
|
||||
embed_dim = 32
|
||||
lstm_units = 64
|
||||
|
||||
model = Sequential()
|
||||
model.add(layers.Embedding(input_dim=vocabulary_size, output_dim=embed_dim, input_length=max_words, input_shape=(max_words,)))
|
||||
model.add(layers.LSTM(lstm_units))
|
||||
model.add(layers.Dropout(0.5))
|
||||
model.add(layers.Dense(1, activation='sigmoid'))
|
||||
|
||||
model.summary()
|
||||
```
|
||||
|
||||
>
|
||||
>Model: "sequential"
|
||||
>
|
||||
|
||||
| Layer (type) | Output Shape | Param # |
|
||||
|----------|-------------------------------------|---------------------------|-----------------------------------------|
|
||||
| embedding (Embedding) | (None, 500, 32) | 160,000 |
|
||||
| lstm (LSTM) | (None, 64) | 24,832 |
|
||||
| dropout (Dropout) | (None, 64) | 0 |
|
||||
| dense (Dense) | (None, 1) | 65 |
|
||||
>
|
||||
> Total params: 184,897 (722.25 KB)
|
||||
>
|
||||
> Trainable params: 184,897 (722.25 KB)
|
||||
>
|
||||
> Non-trainable params: 0 (0.00 B)
|
||||
|
||||
```python
|
||||
# компилируем и обучаем модель
|
||||
batch_size = 64
|
||||
epochs = 3
|
||||
model.compile(loss="binary_crossentropy", optimizer="adam", metrics=["accuracy"])
|
||||
model.fit(X_train, y_train, batch_size=batch_size, epochs=epochs, validation_split=0.2)
|
||||
```
|
||||
|
||||
>Epoch 1/3
|
||||
>
|
||||
>313/313 ━━━━━━━━━━━━━━━━━━━━ 12s 23ms/step - accuracy: 0.6709 - loss: 0.5808 - val_accuracy: 0.8360 - val_loss: 0.3821
|
||||
>
|
||||
>Epoch 2/3
|
||||
>
|
||||
>313/313 ━━━━━━━━━━━━━━━━━━━━ 7s 22ms/step - accuracy: 0.8632 - loss: 0.3428 - val_accuracy: 0.8552 - val_loss: 0.3822
|
||||
>
|
||||
>Epoch 3/3
|
||||
>
|
||||
>313/313 ━━━━━━━━━━━━━━━━━━━━ 6s 20ms/step - accuracy: 0.8972 - loss: 0.2699 - val_accuracy: 0.8580 - val_loss: 0.3352
|
||||
>
|
||||
><keras.src.callbacks.history.History at 0x7a52f7a673b0>
|
||||
>
|
||||
|
||||
```python
|
||||
test_loss, test_acc = model.evaluate(X_test, y_test)
|
||||
print(f"\nTest accuracy: {test_acc}")
|
||||
```
|
||||
|
||||
> 782/782 ━━━━━━━━━━━━━━━━━━━━ 6s 8ms/step - accuracy: 0.8476 - loss: 0.3551
|
||||
>
|
||||
> Test accuracy: 0.8491600155830383
|
||||
|
||||
|
||||
### 10) Оценили качество обучения на тестовых данных:
|
||||
### - вывели значение метрики качества классификации на тестовых данных
|
||||
### - вывели отчет о качестве классификации тестовой выборки
|
||||
### - построили ROC-кривую по результату обработки тестовой выборки и вычислили площадь под ROC-кривой (AUC ROC)
|
||||
|
||||
```python
|
||||
#значение метрики качества классификации на тестовых данных
|
||||
print(f"\nTest accuracy: {test_acc}")
|
||||
```
|
||||
> Test accuracy: 0.8491600155830383
|
||||
|
||||
|
||||
```python
|
||||
#отчет о качестве классификации тестовой выборки
|
||||
y_score = model.predict(X_test)
|
||||
y_pred = [1 if y_score[i,0]>=0.5 else 0 for i in range(len(y_score))]
|
||||
|
||||
from sklearn.metrics import classification_report
|
||||
print(classification_report(y_test, y_pred, labels = [0, 1], target_names=['Negative', 'Positive']))
|
||||
```
|
||||
>782/782 ━━━━━━━━━━━━━━━━━━━━ 6s 8ms/step
|
||||
>
|
||||
> precision recall f1-score support
|
||||
>
|
||||
>
|
||||
>
|
||||
> Negative 0.81 0.91 0.86 12500
|
||||
>
|
||||
> Positive 0.90 0.79 0.84 12500
|
||||
>
|
||||
>
|
||||
>
|
||||
> accuracy 0.85 25000
|
||||
>
|
||||
> macro avg 0.85 0.85 0.85 25000
|
||||
>
|
||||
>weighted avg 0.85 0.85 0.85 25000
|
||||
|
||||
|
||||
```python
|
||||
#построение ROC-кривой и AUC ROC
|
||||
from sklearn.metrics import roc_curve, auc
|
||||
|
||||
fpr, tpr, thresholds = roc_curve(y_test, y_score)
|
||||
plt.plot(fpr, tpr)
|
||||
plt.grid()
|
||||
plt.xlabel('False Positive Rate')
|
||||
plt.ylabel('True Positive Rate')
|
||||
plt.title('ROC')
|
||||
plt.show()
|
||||
print('AUC ROC:', auc(fpr, tpr))
|
||||
```
|
||||

|
||||
|
||||
> AUC ROC: 0.9323916576
|
||||
|
||||
|
||||
### 11) Сделали выводы по результатам применения рекуррентной нейронной сети для решения задачи определения тональности текста.
|
||||
|
||||
Таблица1:
|
||||
|
||||
| Модель | Количество настраиваемых параметров | Количество эпох обучения | Качество классификации тестовой выборки |
|
||||
|----------|-------------------------------------|---------------------------|-----------------------------------------|
|
||||
| Рекуррентная | 184 897 | 3 | accuracy:0.8476 ; loss:0.3551 ; AUC ROC:0.9324 |
|
||||
|
||||
|
||||
#### По результатам применения рекуррентной нейронной сети, а также по данным таблицы 1 можно сделать вывод, что модель хорошо справилась с задачей определения тональности текста. Показатель accuracy = 0.8476 превышает требуемый порог 0.8.
|
||||
#### Значение AUC ROC = 0.9324 (> 0.9) говорит о высокой способности модели различать два класса (положительные и отрицательные отзывы).
|
||||