Сравнить коммиты

...

13 Коммитов
main ... main

Автор SHA1 Сообщение Дата
KonovalovaAlA 7b47e07dfd Добавлена ЛР4
6 дней назад
KonovalovaAlA 5bf13cc633 Добавлены исправления в отчет
1 неделю назад
KonovalovaAlA ce5268aaba ЛР3
1 неделю назад
KonovalovaAlA f9cb6106b4 Исправлен отчет
1 месяц назад
KonovalovaAlA 49c5000098 Добавлена папка с проектом автокодировщика
1 месяц назад
KonovalovaAlA d32eecc485 Небольшие правки 2.0
2 месяцев назад
KonovalovaAlA faee9c1fdb Небольшие правки
2 месяцев назад
KonovalovaAlA d5a3909506 Доделан отчет и добавлен файл .ipynb
2 месяцев назад
KonovalovaAlA faacab3cc4 Добавлены последние пункты и изображения
2 месяцев назад
KonovalovaAlA 1f049f8d3e Настроены изображения
2 месяцев назад
KonovalovaAlA 7fa4a08483 Настроены изображения
2 месяцев назад
KonovalovaAlA a336d6547a Отчет ЛР1: Добавлены изображения
2 месяцев назад
KonovalovaAlA f25fbeb16f Отчет ЛР1: Добавлены 1-11 пункты
2 месяцев назад

Двоичные данные
labworks/LW1/created_0.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 737 B

Двоичные данные
labworks/LW1/created_0_90.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 264 B

Двоичные данные
labworks/LW1/created_1.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 701 B

Двоичные данные
labworks/LW1/created_1_90.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 196 B

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Двоичные данные
labworks/LW1/plot_0_hidden_layer.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 31 KiB

Двоичные данные
labworks/LW1/plot_1_hidden_layer_100.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 31 KiB

Двоичные данные
labworks/LW1/plot_1_hidden_layer_300.jpg

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 24 KiB

Двоичные данные
labworks/LW1/plot_1_hidden_layer_500.jpg

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 24 KiB

Двоичные данные
labworks/LW1/plot_2_hidden_layer_100.jpg

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 26 KiB

Двоичные данные
labworks/LW1/plot_2_hidden_layer_50.jpg

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 26 KiB

@ -0,0 +1,416 @@
# Отчет по ЛР1
Коновалова Алёна, Ильинцева Любовь, А-01-22
## 1. Настройка созданного блокнота и импорт библиотек и модулей
Импортируем библиотеки и модули.
```py
import os
os.chdir('/content/drive/MyDrive/Colab Notebooks')
from tensorflow import keras
import matplotlib.pyplot as plt
import numpy as np
import sklearn
from keras.utils import to_categorical
#from keras.utils import np_utils
from keras.models import Sequential
from keras.layers import Dense
```
## 2. Загрузка набор данных
Загрузим набор данных MNIST, содержащий размеченные изображения рукописных цифр.
```py
from keras.datasets import mnist
(X_train, y_train), (X_test, y_test) = mnist.load_data()
```
**Вывод:**
```bash
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz
```
## 3. Разбиение набора данных на обучающие и тестовые данные и вывод размерностей полученных данных
Разобьем набор данных на обучающие и тестовые данные в соотношении 60000:10000 элементов.
```py
# создание своего разбиения датасета
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 = 31)
```
Выведем размерности.
```py
print('Shape of X train:', X_train.shape)
print('Shape of y train:', y_train.shape)
```
**Вывод:**
```bash
Shape of X train: (60000, 28, 28)
Shape of y train: (60000,)
```
## 4. Вывод 4 элементов обучающих данных
Выведем изображения и их метки.
```py
for i in range(4):
plt.imshow(X_train[i],cmap=plt.get_cmap('gray'))
plt.show()
print(y_train[i])
```
**Вывод:**
![5](train_4_5.png)
![1](train_4_1.png)
![0](train_4_0.1.png)
![0](train_4_0.2.png)
## 5. Предобработка данных
Развернем каждое входное изображение 28*28 в вектор 784, для того, чтобы их можно было подать на вход нейронной сети.
```py
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)
```
**Вывод:**
```bash
Shape of transformed X train: (60000, 784)
```
Проведем предобработку выходных данных. Переведем выходные метки по принципу one-hot.
```py
y_train = to_categorical(y_train)
y_test = to_categorical(y_test)
print('Shape of transformed y train:', y_train.shape)
num_classes = y_train.shape[1]
```
**Вывод:**
```bash
Shape of transformed y train: (60000, 10)
```
## 6. Реализация модели однослойной нейронной сети
1. Создадим модель и объявим ее объектом класса *Sequental*.
```py
model = Sequential()
```
2. Добавим выходной слой и скомпилируем модель.
```py
model.add(Dense(units=num_classes, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='sgd', metrics=['accuracy'])
```
3. Выведем информацию об архитектуре модели и обучим ее
```py
print(model.summary())
H = model.fit(X_train, y_train, validation_split=0.1, epochs=50)
```
**Вывод:**
```bash
Model: "sequential"
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ Layer (type) ┃ Output Shape ┃ Param # ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ dense (Dense) │ ? │ 0 (unbuilt) │
└─────────────────────────────────┴────────────────────────┴───────────────┘
Total params: 0 (0.00 B)
Trainable params: 0 (0.00 B)
Non-trainable params: 0 (0.00 B)
None
Epoch 1/50
1688/1688 ━━━━━━━━━━━━━━━━━━━━ 4s 2ms/step - accuracy: 0.7060 - loss: 1.1734 - val_accuracy: 0.8710 - val_loss: 0.5186
Epoch 2/50
1688/1688 ━━━━━━━━━━━━━━━━━━━━ 3s 2ms/step - accuracy: 0.8774 - loss: 0.4847 - val_accuracy: 0.8860 - val_loss: 0.4319
Epoch 3/50
1688/1688 ━━━━━━━━━━━━━━━━━━━━ 4s 2ms/step - accuracy: 0.8904 - loss: 0.4151 - val_accuracy: 0.8912 - val_loss: 0.3966
Epoch 4/50
1688/1688 ━━━━━━━━━━━━━━━━━━━━ 5s 2ms/step - accuracy: 0.8973 - loss: 0.3828 - val_accuracy: 0.8947 - val_loss: 0.3761
Epoch 5/50
1688/1688 ━━━━━━━━━━━━━━━━━━━━ 3s 2ms/step - accuracy: 0.9000 - loss: 0.3700 - val_accuracy: 0.8998 - val_loss: 0.3625
Epoch 6/50
1688/1688 ━━━━━━━━━━━━━━━━━━━━ 9s 4ms/step - accuracy: 0.9021 - loss: 0.3542 - val_accuracy: 0.9018 - val_loss: 0.3535
...
Epoch 49/50
1688/1688 ━━━━━━━━━━━━━━━━━━━━ 6s 2ms/step - accuracy: 0.9250 - loss: 0.2693 - val_accuracy: 0.9178 - val_loss: 0.2900
Epoch 50/50
1688/1688 ━━━━━━━━━━━━━━━━━━━━ 6s 2ms/step - accuracy: 0.9273 - loss: 0.2634 - val_accuracy: 0.9157 - val_loss: 0.2896
```
4. Выведем график ошибки по эпохам
```py
plt.plot(H.history['loss'])
plt.plot(H.history['val_loss'])
plt.grid()
plt.xlabel('Epochs')
plt.ylabel('loss')
plt.legend(['train_loss', 'val_loss'])
plt.title('Loss by epochs')
plt.show()
```
**Вывод:**
![График ошибки по эпохам](plot_0_hidden_layer.png)
## 7. Оценка работы модели на тестовых данных
```py
scores = model.evaluate(X_test, y_test)
print('Loss on test data:', scores[0])
print('Accuracy on test data:', scores[1])
```
**Вывод:**
```bash
313/313 ━━━━━━━━━━━━━━━━━━━━ 1s 2ms/step - accuracy: 0.9165 - loss: 0.2995
Loss on test data: 0.28918400406837463
Accuracy on test data: 0.9185000061988831
```
## 8. Обучение и тестирование модели с одним скрытым слоем
Проведем тестирование модели при 100, 300, 500 нейронов в скрытом слое. В качестве функции активации нейронов в скрытом слое будем использовать функцию sigmoid.
По метрике качества классификации выберем наилучшее количество нейронов в скрытом слое.
1. Модель со 100 нейронами в скрытом слое
![График ошибки по эпохам со 100 нейронами в скрытом слое](plot_1_hidden_layer_100.png)
```bash
Loss on test data: 0.20470060408115387
Accuracy on test data: 0.9412999749183655
```
2. Модель с 300 нейронами в скрытом слое
![График ошибки по эпохам с 300 нейронами в скрытом слое](plot_1_hidden_layer_300.jpg)
```bash
Loss on test data: 0.23246125876903534
Accuracy on test data: 0.9337999820709229
```
3. Модель с 500 нейронами в скрытом слое
![График ошибки по эпохам с 500 нейронами в скрытом слое](plot_1_hidden_layer_500.jpg)
```bash
Loss on test data: 0.24853046238422394
Accuracy on test data: 0.9283999800682068
```
По результирующим метрикам видно, что наилучшее количество нейронов - 100.
## 9. Обучение и тестирование модели с двумя скрытыми слоями
Добавим к нашей модели со 100 нейронами в первом скрытом слое второй скрытый слой. Проведем тестирование при 50 и 100 нейронах во втором скрытом слое. В качестве функции активации нейронов во втором скрытом слое будем использовать функцию sigmoid.
1. Модель с 50 нейронами в скрытом слое
![График ошибки по эпохам с 50 нейронами в скрытом слое](plot_2_hidden_layer_50.jpg)
```bash
Loss on test data: 0.19981178641319275
Accuracy on test data: 0.9387000203132629
```
2. Модель со 100 нейронами в скрытом слое
![График ошибки по эпохам со 100 нейронами в скрытом слое](plot_2_hidden_layer_100.jpg)
```bash
Loss on test data: 0.19404223561286926
Accuracy on test data: 0.9413999915122986
```
## 10. Результаты исследования
```
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┓
┃ Слои ┃ Метрика loss ┃ Accuracy ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━┩
│ 0 │ 0.28918400406837463 │ 0.9185000061988831 │
├─────────────────────────────────┼───────────────────────┼─────────────────────┤
│ 1 (100 нейронов) │ 0.20470060408115387 │ 0.9412999749183655 │
├─────────────────────────────────┼───────────────────────┼─────────────────────┤
│ 1 (300 нейронов) │ 0.23246125876903534 │ 0.9337999820709229 │
├─────────────────────────────────┼───────────────────────┼─────────────────────┤
│ 1 (500 нейронов) │ 0.24853046238422394 │ 0.9283999800682068 │
├─────────────────────────────────┼───────────────────────┼─────────────────────┤
│ 2 (100, 50 нейронов) │ 0.19981178641319275 │ 0.9387000203132629 │
├─────────────────────────────────┼───────────────────────┼─────────────────────┤
│ 2 (100, 100 нейронов) │ 0.19404223561286926 │ 0.9413999915122986 │
└─────────────────────────────────┴───────────────────────┴─────────────────────┘
```
По результатам исследования мы видим, что наилучшие результаты достигаются при архитектуре при 100 нейронах на каждом скрытом слое.
## 11. Сохранение наилучшей модели на диск
```py
filepath='/content/drive/MyDrive/Colab Notebooks/best_model.keras'
model_2_100.save(filepath)
```
## 12. Вывод тестовых изображений
```py
n = 31
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: ', str(np.argmax(y_test[n])))
print('NN answer: ', str(np.argmax(result)))
```
**Вывод:**
```bash
NN output: [[4.3196760e-06 1.3248758e-04 9.4383031e-02 2.8113697e-03 2.2433515e-04 4.0835417e-05 5.3229469e-05 8.9428437e-01 3.7515254e-04 7.6909573e-03]]
```
![alt text](test_12_7.png)
```bash
Real mark: 7
NN answer: 7
```
```py
n = 123
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: ', str(np.argmax(y_test[n])))
print('NN answer: ', str(np.argmax(result)))
```
**Вывод:**
```bash
NN output: [[4.8947215e-05 3.4176528e-03 8.6587053e-05 9.2398334e-01 5.9264214e-05
5.0175749e-02 8.9853020e-06 1.3068309e-03 7.7676596e-03 1.3145068e-02]]
```
![alt text](test_12_3.png)
```bash
Real mark: 3
NN answer: 3
```
## 13. Тестирование модели на собственных изображениях цифр
1. Создадим собственные изображения рукописных цифр "1" и "0"
![alt text](created_0.png)
![alt text](created_1.png)
2. Загрузим, предобработаем и подадим на вход обученной нейросети собственные изображения
```py
# вывод собственного изображения
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.predict(test_img)
print('I think it\'s ', np.argmax(result))
```
**Вывод:**
![alt text](result_0.png)
```bash
I think it's 0
```
![alt text](result_1.png)
```bash
I think it's 1
```
## 14. Тестирование модели на собственных изображениях цифр, повернутых на 90 градусов
**Результат тестирования:**
![alt text](result_0_90.png)
```bash
I think it's 0
```
![alt text](result_1_90.png)
```bash
I think it's 4
```
*Таким образом, нейросеть смогла определить 0 из-за простой и неизменной формы при повороте, однако подав на вход перевернутую 1, нейросеть не смогла корренто определить цифру.*

Двоичные данные
labworks/LW1/result_0.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 32 KiB

Двоичные данные
labworks/LW1/result_0_90.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 32 KiB

Двоичные данные
labworks/LW1/result_1.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 29 KiB

Двоичные данные
labworks/LW1/result_1_90.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 27 KiB

Двоичные данные
labworks/LW1/test_12_3.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 9.1 KiB

Двоичные данные
labworks/LW1/test_12_7.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 9.3 KiB

Двоичные данные
labworks/LW1/train_4_0.1.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 9.8 KiB

Двоичные данные
labworks/LW1/train_4_0.2.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 12 KiB

Двоичные данные
labworks/LW1/train_4_1.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 8.7 KiB

Двоичные данные
labworks/LW1/train_4_5.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 9.1 KiB

Двоичные данные
labworks/LW2/AE1_AE2_train_def.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 21 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 22 KiB

Двоичные данные
labworks/LW2/AE1_AE2_train_def_anomalies.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 22 KiB

Двоичные данные
labworks/LW2/AE1_train_def.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 35 KiB

Двоичные данные
labworks/LW2/AE2_train_def.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 32 KiB

Двоичные данные
labworks/LW2/IRE_testAE1.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 32 KiB

Двоичные данные
labworks/LW2/IRE_testAE2.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 33 KiB

Двоичные данные
labworks/LW2/IRE_testAE3_ideal2.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 59 KiB

Двоичные данные
labworks/LW2/IRE_testAE3_min.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 60 KiB

Двоичные данные
labworks/LW2/IRE_trainingAE1.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 60 KiB

Двоичные данные
labworks/LW2/IRE_trainingAE2.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 107 KiB

Двоичные данные
labworks/LW2/IRE_trainingAE3_ideal2.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 97 KiB

Двоичные данные
labworks/LW2/IRE_trainingAE3_min.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 85 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Двоичные данные
labworks/LW2/XtXd_1.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 87 KiB

Двоичные данные
labworks/LW2/XtXd_1_metrics.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 98 KiB

Двоичные данные
labworks/LW2/XtXd_2.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 64 KiB

Двоичные данные
labworks/LW2/XtXd_2_metrics.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 77 KiB

@ -29,12 +29,14 @@ from pandas import DataFrame
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Activation
from tensorflow.keras.callbacks import Callback
visual = True
verbose_show = False
# generate 2d classification dataset
def datagen(x_c, y_c, n_samples, n_features):
@ -91,8 +93,27 @@ class EarlyStoppingOnValue(tensorflow.keras.callbacks.Callback):
)
return monitor_value
class VerboseEveryNEpochs(Callback):
def __init__(self, every_n_epochs=1000, verbose=1):
super().__init__()
self.every_n_epochs = every_n_epochs
self.verbose = verbose
def on_epoch_end(self, epoch, logs=None):
if (epoch + 1) % self.every_n_epochs == 0:
if self.verbose:
print(f"\nEpoch {epoch + 1}/{self.params['epochs']}")
if logs:
log_str = ", ".join([f"{k}: {v:.4f}" for k, v in logs.items()])
print(f" - {log_str}")
#создание и обучение модели автокодировщика
def create_fit_save_ae(cl_train, ae_file, irefile, epohs, verbose_show, patience):
def create_fit_save_ae(cl_train, ae_file, irefile, epohs, verbose_show, patience, **kwargs):
verbose_every_n_epochs = kwargs.get('verbose_every_n_epochs', 1000)
early_stopping_delta = kwargs.get('early_stopping_delta', 0.001)
early_stopping_value = kwargs.get('early_stopping_value', 0.0001)
size = cl_train.shape[1]
#ans = '2'
@ -140,22 +161,28 @@ def create_fit_save_ae(cl_train, ae_file, irefile, epohs, verbose_show, patience
optimizer = tensorflow.keras.optimizers.Adam(learning_rate=0.001, beta_1=0.9, beta_2=0.999, amsgrad=False)
ae.compile(loss='mean_squared_error', optimizer=optimizer)
error_stop = 0.0001
epo = epohs
early_stopping_callback_on_error = EarlyStoppingOnValue(monitor='loss', baseline=error_stop)
verbose = 1 if verbose_show else 0
early_stopping_callback_on_error = EarlyStoppingOnValue(monitor='loss', baseline=early_stopping_value)
early_stopping_callback_on_improving = tensorflow.keras.callbacks.EarlyStopping(monitor='loss',
min_delta=0.0001, patience = patience,
verbose=1, mode='auto',
min_delta=early_stopping_delta, patience = patience,
verbose=verbose, mode='min',
baseline=None,
restore_best_weights=False)
restore_best_weights=True)
history_callback = tensorflow.keras.callbacks.History()
verbose = 1 if verbose_show else 0
history_object = ae.fit(cl_train, cl_train,
batch_size=cl_train.shape[0],
epochs=epo,
callbacks=[early_stopping_callback_on_error, history_callback,
early_stopping_callback_on_improving],
callbacks=[
early_stopping_callback_on_error,
history_callback,
early_stopping_callback_on_improving,
VerboseEveryNEpochs(every_n_epochs=verbose_every_n_epochs),
],
verbose=verbose)
ae_trainned = ae
ae_pred = ae_trainned.predict(cl_train)
@ -538,4 +565,4 @@ def ire_plot(title, IRE_test, IREth, ae_name):
plt.gcf().savefig('out/IRE_' + title + ae_name + '.png')
plt.show()
return
return

@ -0,0 +1,676 @@
# Отчет по ЛР2
Коновалова Алёна, Ильинцева Любовь, А-01-22
## Задание 1
## 1. Импорт необходимых библиотек и модулей
```py
import os
os.chdir('/content/drive/MyDrive/Colab Notebooks/is_lab2')
```
```py
# импорт модулей
import numpy as np
import lab02_lib as lib
```
## 2. Генерация индивидуального набора двумерных данных
Сгенерируем индивидуальный набор двумерных данных в пространстве признаков с координатами центра (k, k), где k – номер бригады, равный 8 в нашем случае.
```py
data = lib.datagen(8, 8, 1000, 2)
```
**Вывод:**
![Training set](train_set.png)
Выведем данные и размерность
```py
print('Исходные данные:')
print(data)
print('Размерность данных:')
print(data.shape)
```
**Вывод:**
```bash
Исходные данные:
[[8.14457288 7.96648176]
[8.16064924 7.98620341]
[7.93127504 7.92863959]
...
[7.95464881 7.94307035]
[8.01092703 7.90530753]
[7.81962108 7.93563874]]
Размерность данных:
(1000, 2)
```
## 3. Создание и обучение автокодировщика АЕ1
Создадим автокодировщик простой архитектуры. Обучим автокодировщик в течение 1000 эпох с параметром patience = 300. Добавим 1 скрытый слой с 5 нейронами, т.к. нам нужно добиться, чтобы MSE_stop была не меньше 1-10.
```py
patience = 300
ae1_trained, IRE1, IREth1 = lib.create_fit_save_ae(data,'out/AE1.h5','out/AE1_ire_th.txt', 1000, True, patience)
```
**Вывод:**
```bash
...
Epoch 1000/1000 - loss: 3.7394
```
Ошибка MSE_stop равна **3.7394**, что является удовлетворительным.
Пороговое значение ошибки реконструкции IREth1 - **3.07**
## 4. Построение графика ошибки реконструкции для AE1
```py
lib.ire_plot('training', IRE1, IREth1, 'AE1')
```
**Вывод:**
![IRE for training set AE1](IRE_trainingAE1.png)
Из графика видим, что нейросеть обучена оптимально и порог обнаружения аномалий адекватно описывает границу области генеральной совокупности исследуемых данных.
## 5. Создание и обучение автокодировщика АЕ1
Создадим автокодировщик с более сложной архитектурой. Будем обучать в течение 2700 эпох с параметром patience = 500. Добавим 5 скрытых слоев с архитектурой 4-3-2-3-4 нейронов на каждом слое. В случае с автокодировщиком АЕ2 нам нужно добиться ошибки MSE_stop не меньше 0.01.
```py
patience = 500
ae2_trained, IRE2, IREth2 = lib.create_fit_save_ae(data,'out/AE2.h5','out/AE2_ire_th.txt', 2700, True, patience)
```
**Вывод:**
```bash
...
Epoch 2700/2700 - loss: 0.0114
```
Ошибка MSE_stop равна **0.0114**, мы сумели достичь результата, близкого к идеалу.
Пороговое значение ошибки реконструкции IREth2 - **0.4**
## 6. Построение графика ошибки реконструкции для AE2
```py
lib.ire_plot('training', IRE2, IREth2, 'AE2')
```
**Вывод:**
![IRE for training set AE2](IRE_trainingAE2.png)
Из графика также видим, что нейросеть обучена хорошо и порог обнаружения аномалий не завышен относительно средних значений ошибки.
## 7. Расчет характеристик качества обучения EDCA
Рассчитаем характеристики для АЕ1 и АЕ2. Визуализируем области пространства признаков, распознаваемые автокодировщиками АЕ1 и АЕ2.
### 7.1. AE1
```py
numb_square = 20
xx, yy, Z1 = lib.square_calc(numb_square, data, ae1_trained, IREth1, '1', True)
```
**Вывод:**
![Class boundary AE1](AE1_train_def.png)
```bash
amount: 19
amount_ae: 280
```
![Xt Xd AE1](XtXd_1.png)
![Xt Xd metrics AE1](XtXd_1_metrics.png)
```bash
Оценка качества AE1
IDEAL = 0. Excess: 13.736842105263158
IDEAL = 0. Deficit: 0.0
IDEAL = 1. Coating: 1.0
summa: 1.0
IDEAL = 1. Extrapolation precision (Approx): 0.06785714285714287
```
### 7.2. AE2
```py
numb_square = 20
xx, yy, Z2 = lib.square_calc(numb_square, data, ae2_trained, IREth2, '2', True)
```
**Вывод:**
![Class boundary AE2](AE2_train_def.png)
```bash
amount: 19
amount_ae: 30
```
![Xt Xd AE2](XtXd_2.png)
![Xt Xd metrics AE2](XtXd_2_metrics.png)
```bash
Оценка качества AE2
IDEAL = 0. Excess: 0.5789473684210527
IDEAL = 0. Deficit: 0.0
IDEAL = 1. Coating: 1.0
summa: 1.0
IDEAL = 1. Extrapolation precision (Approx): 0.6333333333333334
```
### 7.3. Сравнение характеристик качества обучения и областей аппроксимации
```py
lib.plot2in1(data, xx, yy, Z1, Z2)
```
**Вывод:**
![Class boundary AE2](AE1_AE2_train_def.png)
По результатам подсчетов характеристик качества обучения EDCA, можно сделать вывод о непригодности автокодировщика АЕ1. Значение Excess = 13.74 значительно превышает идеальный показатель 0. АЕ1 считает нормой данные, которые находятся в 14 раз за пределами реального распределения обучающей выборки. Низкое значение Approx = 0.07 подтверждает плохую аппроксимацию исходных данных. Такой автокодировщик будет пропускать большинство аномалий и не может быть рекомендован для практического применения.
Автокодировщик АЕ2 показывает более высокие результаты. Значение Excess = 0.58 близко к идеальному, что указывает на точное определение границ нормального класса. Approx = 0.63 демонстрирует хорошую точность аппроксимации исходных данных. Данный автокодировщик пригоден для решения практических задач обнаружения аномалий.
## 8. Создание тестовой выборки
Нужно создать тестовую выборку, состояющую, как минимум, из 4 элементов, не входящих в обучающую выборку. Элементы должны быть такими, чтобы AE1 распознавал их как норму, а AE2 детектировал как аномалии.
Подберем 6 точек. Условие, чтобы точка не попала в обучающую выборку:
```py
(x < 7.7 or x > 8.3) or (y < 7.7 or y > 8.3)
```
Поскольку центр располагается в точке (8;8) и в функции для генерации датасета используется правило 3σ, где параметр cluster_std = 0.1, то точки за пределами 7.7 и 8.3 не входят в обучающую выборку с вероятностью 99.7%.
Запишем точки в массив и сохраним в файл.
```py
test_points = np.array([
[8.5, 8.5],
[7.5, 7.5],
[8.4, 7.6],
[7.6, 8.4],
[8.45, 7.55],
[7.55, 8.45]
])
np.savetxt('data_test.txt', test_points)
```
## 9. Тестирование автокодировщиков АЕ1 и АЕ2
Загрузим тестовый набор.
```py
data_test = np.loadtxt('data_test.txt', dtype=float)
```
Проведем тестирование первого автокодировщика.
```py
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')
```
**Вывод:**
```bash
i Labels IRE IREth
0 [1.] [3.43] 3.07
1 [0.] [2.03] 3.07
2 [0.] [2.71] 3.07
3 [0.] [2.85] 3.07
4 [0.] [2.72] 3.07
5 [0.] [2.88] 3.07
Обнаружено 1.0 аномалий
```
![IRE for test set AE1](IRE_testAE1.png)
Условие выполнено - 5 точек АЕ1 распознал как норму и лишь одну точку определил как аномалию. Данный автокодировщик плохо справляется с распознаванием аномалий.
Проведем тестирование второго автокодировщика.
```py
predicted_labels2, ire2 = lib.predict_ae(ae2_trained, data_test, IREth2)
lib.anomaly_detection_ae(predicted_labels2, ire2, IREth2)
lib.ire_plot('test', ire2, IREth2, 'AE2')
```
```bash
i Labels IRE IREth
0 [1.] [0.75] 0.4
1 [1.] [0.66] 0.4
2 [1.] [0.55] 0.4
3 [1.] [0.58] 0.4
4 [1.] [0.62] 0.4
5 [1.] [0.65] 0.4
Обнаружено 6.0 аномалий
```
![IRE for test set AE2](IRE_testAE2.png)
Мы видим, что условие также выполнено - все точки являются аномальными.
## 10. Визуализация элементов обучающей и тестовой выборки в областях пространства признаков
Построим области аппроксимации и точки тестового набора
```py
lib.plot2in1_anomaly(data, xx, yy, Z1, Z2, data_test)
```
![](AE1_AE2_train_def_anomalies.png)
## 11. Результаты исследования
Занесем результаты исследования в таблицу:
| Параметр | AE1 | AE2 |
|----------|-----|-----|
| **Количество скрытых слоев** | 1 | 5 |
| **Количество нейронов в скрытых слоях** | 5 | 4-3-2-3-4 |
| **Количество эпох обучения** | 1000 | 2700 |
| **Ошибка MSE_stop** | 3.7394 | 0.0114 |
| **Порог ошибки реконструкции** | 3.07 | 0.4 |
| **Значение показателя Excess** | 13.7368 | 0.5789 |
| **Значение показателя Approx** | 0.0679 | 0.6333 |
| **Количество обнаруженных аномалий** | 1 | 6 |
## 12. Общие выводы
На основе проведенного исследования автокодировщиков AE1 и AE2 были определены ключевые требования для эффективного обнаружения аномалий:
**1. Данные для обучения** должны быть репрезентативными и не содержать аномалий. Объем выборки должен быть достаточным для покрытия всей области нормального поведения объектов.
**2. Архитектура автокодировщика** должна иметь не менее 3-5 скрытых слоев с симметричной структурой, обеспечивающей плавное сжатие и восстановление данных. Простые архитектуры, как у AE1 (1 слой), не способны качественно выявлять аномалии.
**3. Количество эпох обучения** должно составлять не менее 2000-3000 для достижения удовлетворительного качества. Короткое обучение (1000 эпох у AE1) приводит к недообучению и низкой эффективности.
**4. Ошибка MSE_stop** должна находиться в диапазоне 0.01-0.05. Высокие значения ошибки (3.74 у AE1) свидетельствуют о непригодности модели для обнаружения аномалий.
**5. Порог обнаружения аномалий** должен быть строгим (0.3-0.5) для минимизации ложных пропусков. Завышенный порог (3.07 у AE1) приводит к некорректной классификации аномальных объектов как нормальных.
**6. Характеристики EDCA** должны быть близки к идеальным значениям: Excess → 0, Approx → 1. Значения AE2 (Excess=0.58, Approx=0.63) демонстрируют удовлетворительное качество, в то время как показатели AE1 (Excess=13.74, Approx=0.07) указывают на полную непригодность для практического применения.
Таким образом, для надежного обнаружения аномалий необходимо использовать сложные архитектуры автокодировщиков с продолжительным обучением и контролем качества через метрики EDCA.
## Задание 2
## 1. Описание набора реальных данных
Номер бригады k = 8. Следовательно, наш набор реальных данных - WBC.
```bash
N = k mod 3
```
Он представляет из себя 378 примеров с 30 признаками, где из 378 примеров 357 являются нормальными и относятся к доброкачественному классу, 21 - аномалиями и относятся к злокачественному классу.
## 2. Загрузка обучающей выборки
```py
train = np.loadtxt('WBC_train.txt', dtype=float)
```
## 3. Вывод полученных данных и их размерность
```py
print('Исходные данные:')
print(train)
print('Размерность данных:')
print(train.shape)
```
**Вывод:**
```bash
Исходные данные:
[[3.1042643e-01 1.5725397e-01 3.0177597e-01 ... 4.4261168e-01
2.7833629e-01 1.1511216e-01]
[2.8865540e-01 2.0290835e-01 2.8912998e-01 ... 2.5027491e-01
3.1914055e-01 1.7571822e-01]
[1.1940934e-01 9.2323301e-02 1.1436666e-01 ... 2.1398625e-01
1.7445299e-01 1.4882592e-01]
...
[3.3456387e-01 5.8978695e-01 3.2886463e-01 ... 3.6013746e-01
1.3502858e-01 1.8476978e-01]
[1.9967817e-01 6.6486304e-01 1.8575081e-01 ... 0.0000000e+00
1.9712202e-04 2.6301981e-02]
[3.6868759e-02 5.0152181e-01 2.8539838e-02 ... 0.0000000e+00
2.5744136e-01 1.0068215e-01]]
Размерность данных:
(357, 30)
```
## 4. Создание и обучение автокодировщика АЕ3
Для начала попробуем обучить автокодировщик при минимально возможных параметрах и посмотреть на порог ошибки реконструкции. То есть будем обучать в течение 50000 эпох с параметром patience = 5000, с 9 скрытыми слоями и архиектурой 15-13-11-9-7-9-11-13-15
```py
patience = 5000
ae3_trained, IRE3, IREth3 = lib.create_fit_save_ae(train,'out/AE3.h5','out/AE3_ire_th.txt', 50000, False, patience)
lib.ire_plot('training', IRE3, IREth3, 'AE3')
```
**Вывод:**
```bash
Задать архитектуру автокодировщиков или использовать архитектуру по умолчанию? (1/2): 1
Задайте количество скрытых слоёв (нечетное число) : 9
Задайте архитектуру скрытых слоёв автокодировщика, например, в виде 3 1 3 : 15 13 11 9 7 9 11 13 15
Epoch 1000/50000
- loss: 0.0020
Epoch 2000/50000
- loss: 0.0013
Epoch 3000/50000
- loss: 0.0012
Epoch 4000/50000
- loss: 0.0012
Epoch 5000/50000
- loss: 0.0011
Epoch 6000/50000
- loss: 0.0010
```
MSE_stop = **0.001**
## 5. График ошибки реконструкции
Построим график ошибки реконструкции и выведем порог ошибки реконструкции.
![IRE for training set. AE3](IRE_trainingAE3_min.png)
IREth3 = **0.84**
## 6. Вывод о пригодности обученного автокодировщика
Обученный автокодировщик демонстрирует удовлетворительные результаты для обнаружения аномалий. Модель со архитектурой 15-13-11-9-7-9-11-13-15 успешно прошла обучение, достигнув MSE = 0.001 за 6000 эпох. Стабильное снижение функции потерь свидетельствует о корректной работе алгоритма.
Установленный порог IREth = 0.84 является разумным для разделения нормальных и аномальных образцов. Узкое горлышко из 7 нейронов обеспечивает необходимое сжатие данных для выделения ключевых признаков.
Модель можно считать пригодной для практического использования при условии, что тестирование подтвердит достижение целевых 70% обнаружения аномалий.
## 7. Загрузка тестовой выборки
```py
test = np.loadtxt('WBC_test.txt', dtype=float)
```
```py
print('Исходные данные:')
print(test)
print('Размерность данных:')
print(test.shape)
```
**Вывод:**
```bash
Исходные данные:
[[0.18784609 0.3936422 0.19425057 0.09654295 0.632572 0.31415251
0.24461106 0.28175944 0.42171717 0.3946925 0.04530147 0.23598833
0.05018141 0.01899148 0.21589557 0.11557064 0.0655303 0.19643872
0.08003602 0.07411246 0.17467094 0.62153518 0.18332586 0.08081007
0.79066235 0.23528442 0.32132588 0.48934708 0.2757737 0.26905418]
[0.71129727 0.41224214 0.71460162 0.56776246 0.48451747 0.53990553
0.57357076 0.74602386 0.38585859 0.24094356 0.3246424 0.07507514
0.32059558 0.23047901 0.0769963 0.19495599 0.09030303 0.27865126
0.10269038 0.10023078 0.70188545 0.36727079 0.72010558 0.50181872
0.38453411 0.35044775 0.3798722 0.83573883 0.23181549 0.20136429]
..............
[0.32367836 0.49983091 0.33542948 0.1918982 0.57389185 0.45616833
0.31794752 0.33593439 0.61363636 0.47198821 0.13166757 0.25808876
0.10446214 0.06023183 0.27082979 0.27268904 0.08777778 0.30611858
0.23158102 0.21074997 0.28744219 0.5575693 0.27685642 0.14815179
0.71471967 0.35830641 0.27004792 0.52268041 0.41119653 0.41492851]]
Размерность данных:
(21, 30)
```
## 8. Тестирование обученного автокодировщика
```py
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')
```
**Вывод:**
```bash
i Labels IRE IREth
0 [0.] [0.27] 0.84
1 [0.] [0.8] 0.84
2 [0.] [0.32] 0.84
3 [0.] [0.53] 0.84
4 [0.] [0.55] 0.84
5 [0.] [0.68] 0.84
6 [0.] [0.53] 0.84
7 [1.] [0.95] 0.84
8 [0.] [0.31] 0.84
9 [0.] [0.47] 0.84
10 [0.] [0.44] 0.84
11 [1.] [1.07] 0.84
12 [0.] [0.25] 0.84
13 [0.] [0.45] 0.84
14 [0.] [0.27] 0.84
15 [0.] [0.58] 0.84
16 [0.] [0.53] 0.84
17 [0.] [0.27] 0.84
18 [1.] [1.29] 0.84
19 [1.] [0.93] 0.84
20 [0.] [0.24] 0.84
Обнаружено 4.0 аномалий
```
![IRE for test set. AE3](IRE_testAE3_min.png)
При текущих параметрах было достигнуто лишь 19% выявленных аномалий, что свидетельствует о непригодности данного автокодировщика.
## 9. Подбор подходящих параметров
Мы провели несколько тестов и путем подбора пришли к архитектуре, удовлетворяющей условие пригодности автокодировщика - не менее 70% выявления аномалий.
Для этого мы установили параметр early_stopping_delta = 0.00001 и увеличили параметр patience до 20000. Однако критерием останова в нашем случае являлся параметр early_stopping_value, который мы также изменили до 0.00007.
Количество эпох мы оставили прежним - 50000.
Помимо этого, мы установили оптимальную архитектуру - 9 скрытых слоев с 24-22-20-17-15-17-20-22-24 нейронами.
```py
patience = 20000
ae3_trained, IRE3, IREth3 = lib.create_fit_save_ae(train,'out/AE3.h5','out/AE3_ire_th.txt', 50000, False, patience, early_stopping_delta = 0.00001, early_stopping_value = 0.00007)
lib.ire_plot('training', IRE3, IREth3, 'AE3')
```
**Вывод:**
```bash
Задать архитектуру автокодировщиков или использовать архитектуру по умолчанию? (1/2): 1
Задайте количество скрытых слоёв (нечетное число) : 9
Задайте архитектуру скрытых слоёв автокодировщика, например, в виде 3 1 3 : 24 22 20 17 15 17 20 22 24
Epoch 1000/50000
- loss: 0.000864
Epoch 2000/50000
- loss: 0.000545
Epoch 3000/50000
- loss: 0.000415
Epoch 4000/50000
- loss: 0.000303
Epoch 5000/50000
- loss: 0.000226
Epoch 6000/50000
- loss: 0.000217
Epoch 7000/50000
- loss: 0.000207
Epoch 8000/50000
- loss: 0.000186
Epoch 9000/50000
- loss: 0.000167
Epoch 10000/50000
- loss: 0.000113
Epoch 11000/50000
- loss: 0.000102
Epoch 12000/50000
- loss: 0.000095
Epoch 13000/50000
- loss: 0.000090
Epoch 14000/50000
- loss: 0.000088
Epoch 15000/50000
- loss: 0.000086
Epoch 16000/50000
- loss: 0.000079
Epoch 17000/50000
- loss: 0.000078
```
![](IRE_trainingAE3_ideal2.png)
Пороговое значение IREth3 = 0.11 является оптимальным, т.к. позволяет обнаруживать даже слабые аномалии, при этом сам по себе не слишком строгий.
```py
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 [0.] [0.1] 0.11
1 [1.] [0.5] 0.11
2 [0.] [0.05] 0.11
3 [1.] [0.15] 0.11
4 [1.] [0.27] 0.11
5 [1.] [0.39] 0.11
6 [1.] [0.16] 0.11
7 [1.] [0.61] 0.11
8 [0.] [0.07] 0.11
9 [1.] [0.21] 0.11
10 [1.] [0.22] 0.11
11 [1.] [0.57] 0.11
12 [0.] [0.11] 0.11
13 [1.] [0.21] 0.11
14 [1.] [0.12] 0.11
15 [1.] [0.32] 0.11
16 [1.] [0.29] 0.11
17 [0.] [0.1] 0.11
18 [1.] [0.87] 0.11
19 [1.] [0.52] 0.11
20 [0.] [0.11] 0.11
Обнаружено 15.0 аномалий
```
![](IRE_testAE3_ideal2.png)
Тестирование модели продемонстрировало превосходные результаты - обнаружено 15 из 21 аномалий, что соответствует 71.4% точности и превышает целевую метрику в 70%.
## 10. Результаты исследования
Занесем результаты исследования в таблицу:
| Параметр | Значение |
|----------|----------|
| **Dataset name** | WBC |
| **Количество скрытых слоев** | 9 |
| **Количество нейронов в скрытых слоях** | 24-22-20-17-15-17-20-22-24 |
| **Количество эпох обучения** | 50000 |
| **Ошибка MSE_stop** | 0.000078 |
| **Порог ошибки реконструкции** | 0.11 |
| **% обнаруженных аномалий** | 71.4 |
## 11. Общие выводы
На основе проведенного исследования автокодировщиков AE1 и AE2 были определены ключевые требования для эффективного обнаружения аномалий:
**1. Данные для обучения** должны быть тщательно отобраны и содержать только репрезентативные нормальные образцы. Для 30-мерного пространства признаков объем выборки должен составлять не менее 300-500 объектов для адекватного покрытия области нормального поведения.
**2. Архитектура автокодировщика** должна иметь глубокую симметричную структуру с 7-9 скрытыми слоями. Оптимальная конфигурация 24-22-20-17-15-17-20-22-24 нейронов обеспечивает плавное сжатие 30-мерного пространства до 15 нейронов в горлышке с последующим восстановлением, что позволяет эффективно выделять существенные признаки.
**3. Количество эпох обучения** должно составлять не менее 15000-20000 для достижения высокого качества реконструкции. Продолжительное обучение необходимо для сложных высокоразмерных данных.
**4. Ошибка MSE_stop** должна достигать значений 0.00007-0.0001. Столь низкий порог обусловлен высокой размерностью данных и необходимостью точной реконструкции многочисленных признаков.
**5. Порог обнаружения аномалий** должен быть строгим (0.1-0.15) для надежного выявления аномалий в сложном многомерном пространстве. Низкое значение IREth компенсирует высокую размерность данных и обеспечивает чувствительность к слабым отклонениям.
Таким образом, для качественного обнаружения аномалий в высокоразмерных данных необходимы глубокие архитектуры автокодировщиков с продолжительным обучением до достижения экстремально низких значений ошибки реконструкции.

Двоичные данные
labworks/LW2/train_set.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 44 KiB

Двоичные данные
labworks/LW3/0.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 282 B

Двоичные данные
labworks/LW3/1.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 248 B

Двоичные данные
labworks/LW3/best_model.keras

Двоичный файл не отображается.

Двоичные данные
labworks/LW3/images/cifar_25_samples.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 119 KiB

Двоичные данные
labworks/LW3/images/img_15_1.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 6.7 KiB

Двоичные данные
labworks/LW3/images/img_15_3.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 7.1 KiB

Двоичные данные
labworks/LW3/images/img_17_1.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 32 KiB

Двоичные данные
labworks/LW3/images/img_19_0.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 6.5 KiB

Двоичные данные
labworks/LW3/images/img_19_2.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 6.4 KiB

Двоичные данные
labworks/LW3/images/img_44_1.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 12 KiB

Двоичные данные
labworks/LW3/images/img_44_3.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 20 KiB

Двоичные данные
labworks/LW3/images/img_46_1.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 59 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

@ -0,0 +1,587 @@
# Отчёт по лабораторной работе №3
**Ильинцева Л.В. Коновалова А.А. — А-01-22**
## Задание 1
### 1. Подготовили рабочую среду в Google Colab, создав новый блокнот. Выполнили импорт требуемых библиотек и модулей для дальнейшей работы.
```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)=31, где k=8 соответствует номеру нашей бригады. Отобразили размерности полученных массивов данных.
```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 = 31)
# вывод размерностей
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 (MaxPooling2D) | (None, 13, 13, 32) | 0 |
| conv2d_1 (Conv2D) | (None, 11, 11, 64) | 18,496 |
| max_pooling2d_1 (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)
```
### 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.9873 - loss: 0.0396
Loss on test data: 0.03962046653032303
Accuracy on test data: 0.9872999787330627
```
### 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))
```
![Тестовое изображение MNIST 1](images/img_15_1.png)
```
Real mark: 7
NN answer: 7
```
![Тестовое изображение MNIST 2](images/img_15_3.png)
```
Real mark: 4
NN answer: 4
```
### 8. Сформировали детальный отчет о качестве классификации на тестовой выборке, включая матрицу ошибок (confusion matrix).
```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 1.00 0.99 0.99 967
1 1.00 0.99 0.99 1107
2 0.98 0.99 0.99 970
3 0.99 0.98 0.99 1023
4 1.00 0.99 0.99 1008
5 0.98 0.99 0.98 866
6 0.99 0.99 0.99 965
7 0.98 0.98 0.98 1070
8 0.98 0.99 0.99 943
9 0.98 0.98 0.98 1081
accuracy 0.99 10000
macro avg 0.99 0.99 0.99 10000
weighted avg 0.99 0.99 0.99 10000
```
![Матрица ошибок для MNIST](images/img_17_1.png)
### 9. Загрузили собственные изображения, подготовленные в рамках лабораторной работы №1. После предобработки передали их на вход обученной модели и получили результаты распознавания.
```python
# загрузка собственного изображения
from PIL import Image
for name_image in ['0.png', '1.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))
```
![Собственное изображение цифры 0](images/img_19_0.png)
```
I think it's 0
```
![Собственное изображение цифры 1](images/img_19_2.png)
```
I think it's 1
```
### 10. Загрузили ранее сохраненную модель из лабораторной работы №1. Изучили ее архитектуру и провели оценку качества на тестовых данных аналогично пункту 6.
```python
model_lr1 = keras.models.load_model("best_model.keras")
model_lr1.summary()
```
**Model: "sequential_10"**
| Layer (type) | Output Shape | Param # |
|------------------|-------------:|--------:|
| dense_22 (Dense) | (None, 100) | 78,500 |
| dense_23 (Dense) | (None, 50) | 5,050 |
| dense_24 (Dense) | (None, 10) | 510 |
**Total params:** 84,062 (328.37 KB)
**Trainable params:** 84,060 (328.36 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 = 31)
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 ━━━━━━━━━━━━━━━━━━━━ 2s 3ms/step - accuracy: 0.9440 - loss: 0.1897
Loss on test data: 0.18974457681179047
Accuracy on test data: 0.9440000057220459
```
### 11. Выполнили сравнительный анализ сверточной нейронной сети и лучшей полносвязной модели из лабораторной работы №1. Сравнение проводилось по трем критериям:
### - число обучаемых параметров модели
### - количество эпох, необходимое для обучения
### - итоговое качество классификации на тестовой выборке
### На основе полученных результатов сформулировали выводы об эффективности применения сверточных нейронных сетей для задач распознавания изображений.
Таблица1:
| Модель | Количество настраиваемых параметров | Количество эпох обучения | Качество классификации тестовой выборки |
|----------|-------------------------------------|---------------------------|-----------------------------------------|
| Сверточная | 34 826 | 15 | accuracy:0.987 ; loss:0.040 |
| Полносвязная | 84 062 | 50 | accuracy:0.944 ; loss:0.190 |
##### Проведенный сравнительный анализ, результаты которого представлены в таблице 1, наглядно демонстрирует превосходство сверточной нейронной сети над полносвязной архитектурой в задачах классификации изображений.
**Эффективность по параметрам:** Сверточная сеть содержит в 2.4 раза меньше обучаемых параметров (34 826 против 84 062), что свидетельствует о более эффективном использовании вычислительных ресурсов благодаря механизму разделения весов в сверточных слоях.
**Скорость обучения:** Сверточная модель достигает оптимального качества за 15 эпох, в то время как полносвязная требует 50 эпох. Это указывает на более быструю сходимость алгоритма обучения благодаря индуктивным смещениям, заложенным в архитектуру сверточных сетей.
**Качество классификации:** Сверточная сеть демонстрирует значительно более высокую точность (98.7% против 94.4%) и существенно меньшие потери (0.040 против 0.190). Разница в точности составляет более 4 процентных пунктов, что является существенным улучшением для задачи распознавания рукописных цифр.
**Выводы:** Полученные результаты подтверждают, что использование сверточных слоев позволяет эффективно извлекать иерархические пространственные признаки из изображений, что критически важно для задач компьютерного зрения. Инвариантность к сдвигам и способность выявлять локальные паттерны делают сверточные нейронные сети предпочтительным выбором для работы с изображениями по сравнению с полносвязными архитектурами.
## Задание 2
### В отдельном блокноте повторили этапы 2–8 из задания 1, заменив датасет MNIST на CIFAR-10, который содержит цветные изображения объектов, распределенные по 10 категориям.
### Особенности выполнения:
### - разделение на обучающую и тестовую выборки выполнено в пропорции 50 000:10 000
### - после разделения данных (между этапами 3 и 4) визуализировали 25 примеров из обучающей выборки с указанием соответствующих классов
### - при тестировании на двух изображениях (этап 7) одно должно быть распознано верно, а второе – с ошибкой
### 1. Произвели загрузку датасета CIFAR-10, включающего цветные изображения, распределенные по 10 категориям: самолет, автомобиль, птица, кошка, олень, собака, лягушка, лошадь, корабль, грузовик.
```python
# загрузка датасета
from keras.datasets import cifar10
(X_train, y_train), (X_test, y_test) = cifar10.load_data()
```
### 2. Осуществили разделение датасета на обучающую и тестовую части в соотношении 50 000:10 000. Для обеспечения воспроизводимости установили random_state = 31, что соответствует формуле (4k – 1) при k=8 (номер нашей бригады). Отобразили размерности сформированных массивов.
```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 = 31)
# вывод размерностей
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()
```
![25 примеров из датасета CIFAR-10](images/cifar_25_samples.png)
### 3. Выполнили предобработку данных для обучения сверточной нейронной сети. Нормализовали значения пикселей в диапазон [0, 1] и преобразовали метки классов в формат one-hot encoding. Показали размерности обработанных массивов.
```python
# Зададим параметры данных и модели
num_classes = 10
input_shape = (32, 32, 3)
# Приведение входных данных к диапазону [0, 1]
X_train = X_train / 255
X_test = X_test / 255
print('Shape of transformed X train:', X_train.shape)
print('Shape of transformed X test:', X_test.shape)
# переведем метки в one-hot
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)
print('Shape of transformed y train:', y_train.shape)
print('Shape of transformed y test:', y_test.shape)
```
```
Shape of transformed X train: (50000, 32, 32, 3)
Shape of transformed X test: (10000, 32, 32, 3)
Shape of transformed y train: (50000, 10)
Shape of transformed y test: (10000, 10)
```
### 4. Построили архитектуру сверточной нейронной сети и провели обучение на обучающей выборке с использованием части данных для валидации. Представили детальную структуру модели.
```python
# создаем модель
model = Sequential()
# Блок 1
model.add(layers.Conv2D(32, (3, 3), padding="same",
activation="relu", input_shape=input_shape))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(32, (3, 3), padding="same", activation="relu"))
model.add(layers.BatchNormalization())
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Dropout(0.25))
# Блок 2
model.add(layers.Conv2D(64, (3, 3), padding="same", activation="relu"))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(64, (3, 3), padding="same", activation="relu"))
model.add(layers.BatchNormalization())
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Dropout(0.25))
# Блок 3
model.add(layers.Conv2D(128, (3, 3), padding="same", activation="relu"))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(128, (3, 3), padding="same", activation="relu"))
model.add(layers.BatchNormalization())
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Dropout(0.4))
model.add(layers.Flatten())
model.add(layers.Dense(128, activation='relu'))
model.add(layers.Dropout(0.5))
model.add(layers.Dense(num_classes, activation="softmax"))
model.summary()
```
**Model: "sequential_9"**
| Layer (type) | Output Shape | Param # |
|--------------------------------------------|-------------------|---------:|
| conv2d_41 (Conv2D) | (None, 32, 32, 32) | 896 |
| batch_normalization_6 (BatchNormalization) | (None, 32, 32, 32) | 128 |
| conv2d_42 (Conv2D) | (None, 32, 32, 32) | 9,248 |
| batch_normalization_7 (BatchNormalization) | (None, 32, 32, 32) | 128 |
| max_pooling2d_26 (MaxPooling2D) | (None, 16, 16, 32) | 0 |
| dropout_24 (Dropout) | (None, 16, 16, 32) | 0 |
| conv2d_43 (Conv2D) | (None, 16, 16, 64) | 18,496 |
| batch_normalization_8 (BatchNormalization) | (None, 16, 16, 64) | 256 |
| conv2d_44 (Conv2D) | (None, 16, 16, 64) | 36,928 |
| batch_normalization_9 (BatchNormalization) | (None, 16, 16, 64) | 256 |
| max_pooling2d_27 (MaxPooling2D) | (None, 8, 8, 64) | 0 |
| dropout_25 (Dropout) | (None, 8, 8, 64) | 0 |
| conv2d_45 (Conv2D) | (None, 8, 8, 128) | 73,856 |
| batch_normalization_10 (BatchNormalization)| (None, 8, 8, 128) | 512 |
| conv2d_46 (Conv2D) | (None, 8, 8, 128) | 147,584 |
| batch_normalization_11 (BatchNormalization)| (None, 8, 8, 128) | 512 |
| max_pooling2d_28 (MaxPooling2D) | (None, 4, 4, 128) | 0 |
| dropout_26 (Dropout) | (None, 4, 4, 128) | 0 |
| flatten_9 (Flatten) | (None, 2048) | 0 |
| dense_17 (Dense) | (None, 128) | 262,272 |
| dropout_27 (Dropout) | (None, 128) | 0 |
| dense_18 (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)
```
### 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 ━━━━━━━━━━━━━━━━━━━━ 5s 15ms/step - accuracy: 0.8549 - loss: 0.5139
Loss on test data: 0.5139228701591492
Accuracy on test data: 0.8549000024795532
```
### 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))
```
![Тестовое изображение CIFAR-10 1](images/img_44_1.png)
```
Real mark: 3
NN answer: 3
```
![Тестовое изображение CIFAR-10 2](images/img_44_3.png)
```
Real mark: 5
NN answer: 2
```
### 7. Сформировали подробный отчет о результатах классификации тестовой выборки и построили матрицу ошибок (confusion matrix).
```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 ━━━━━━━━━━━━━━━━━━━━ 4s 13ms/step
precision recall f1-score support
airplane 0.81 0.91 0.86 1004
automobile 0.85 0.97 0.91 985
bird 0.79 0.80 0.80 998
cat 0.76 0.70 0.73 985
deer 0.85 0.84 0.85 992
dog 0.82 0.77 0.79 968
frog 0.86 0.93 0.89 1010
horse 0.91 0.86 0.89 1020
ship 0.97 0.86 0.91 1002
truck 0.93 0.90 0.91 1036
accuracy 0.85 10000
macro avg 0.86 0.85 0.85 10000
weighted avg 0.86 0.85 0.85 10000
```
![Матрица ошибок для CIFAR-10](images/img_46_1.png)
#### Анализ результатов классификации датасета CIFAR-10 показал, что разработанная сверточная нейронная сеть с архитектурой, включающей три блока сверточных слоев с batch normalization и dropout, успешно справилась с задачей классификации цветных изображений.
**Общая производительность:** Достигнутая точность классификации составляет 85.49%, что является хорошим результатом для данного датасета, учитывая его сложность (малый размер изображений 32×32, высокая вариативность объектов, наличие фоновых элементов).
**Анализ по классам:** Модель демонстрирует различную эффективность для разных категорий объектов:
- **Высокая точность (≥90%):** ship (precision 0.97, recall 0.86), truck (precision 0.93, recall 0.90), horse (precision 0.91, recall 0.86) - объекты с четкими геометрическими формами и характерными признаками
- **Средняя точность (80-90%):** automobile (precision 0.85, recall 0.97), airplane (precision 0.81, recall 0.91), deer (precision 0.85, recall 0.84), frog (precision 0.86, recall 0.93), dog (precision 0.82, recall 0.77) - объекты с более сложной структурой
- **Пониженная точность (<80%):** bird (precision 0.79, recall 0.80), cat (precision 0.76, recall 0.70) - объекты с высокой внутриклассовой вариативностью и схожестью между классами
**Особенности классификации:** Наибольшие трудности модель испытывает при классификации кошек (precision 0.76, recall 0.70), что связано с высокой вариативностью этого класса и схожестью с собаками. При этом модель демонстрирует сбалансированные метрики precision и recall для большинства классов, что указывает на отсутствие систематических смещений в предсказаниях. Интересно отметить, что для некоторых классов (automobile, airplane, frog) recall выше precision, что говорит о склонности модели чаще предсказывать эти классы.
**Выводы:** Полученные результаты подтверждают эффективность применения сверточных нейронных сетей с batch normalization и dropout для классификации цветных изображений. Архитектура успешно извлекает пространственные признаки различного уровня абстракции, что позволяет достигать высокого качества классификации даже на сложных наборах данных с ограниченным разрешением изображений.

@ -0,0 +1,6 @@
tensorflow>=2.10.0
matplotlib>=3.5.0
numpy>=1.21.0
scikit-learn>=1.0.0
Pillow>=9.0.0

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Двоичные данные
labworks/LW4/output.png

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 20 KiB

@ -0,0 +1,338 @@
# Отчёт по лабораторной работе №4
**Ильинцева Л.В., Коновалова А.А. — А-01-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)=31, где k=8 – номер бригады. Вывели размеры полученных обучающих и тестовых массивов данных.
```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=31,
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, 13, 805, 8, 40, 14, 1179, 40, 13, 353, 8, 358, 32, 1179, 108, 13, 384, 3091, 2, 1849, 19, 6, 117, 1006, 5, 49, 836, 89, 70, 25, 140, 355, 21, 2, 13, 104, 9, 35, 463, 7, 15, 2063, 170, 355, 4, 293, 1834, 9, 4, 527, 116, 7, 4, 293, 289, 539, 15, 2, 56, 11, 4, 313, 12, 16, 17, 48, 36, 71, 467, 2, 5, 12, 2230, 72, 39, 126, 397, 928, 11, 68, 4598, 4, 22, 2, 18, 836, 5, 2, 21, 4, 34, 4, 1396, 458, 2, 12, 7, 148, 5, 889, 4, 20, 184, 753, 45, 6, 902, 88, 48, 4, 20, 16, 128, 2142, 12, 62, 28, 28, 77, 2, 4, 65, 5, 105, 26, 184, 948, 5, 50, 26, 49, 465, 5, 2, 1984, 388, 7, 4347, 200, 4, 452, 4, 539, 5, 4, 577, 11, 4, 154, 313, 225, 49, 52, 1006, 5, 2552, 2, 2, 43, 24, 195, 8, 202, 4, 22, 4, 1968, 12, 887, 4, 1962, 9, 184, 2509, 5, 2, 5, 127, 202, 4, 22, 6, 194, 2, 21, 1038, 94, 99, 117, 99, 522, 38, 11, 61, 652, 31, 8, 798, 894, 25, 66, 119, 3720, 1179, 108, 225, 6, 1257, 1166, 7, 986, 21, 4, 22, 1545, 99, 117, 8, 30, 2640]
len: 220
```
```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))
print('Label:', y_train[26], '(', 'Positive' if y_train[26] == 1 else 'Negative', ')')
```
```
<START> i tried to like this slasher like i try to enjoy all slasher films i mean mindless <UNK> mixed with a little nudity and some suspense how can you go wrong but <UNK> i think is an example of that formula going wrong the main issue is the horrible acting of the main three girls that <UNK> up in the house it was as if they were under <UNK> and it stopped me from ever getting interested in their plight the film <UNK> for suspense and <UNK> but the by the numbers direction <UNK> it of those and leaves the movie pretty dull it's a shame because if the movie was better executed it would have have been <UNK> the story and characters are pretty creepy and there are some dark and <UNK> humorous moments of interaction between the mother the girls and the daughter in the old house there's some good nudity and occasional <UNK> <UNK> just not enough to give the film the kick it needed the finale is pretty twisted and <UNK> and does give the film a big <UNK> but sadly its too little too late so in my opinion one to avoid unless you really love obscure slasher films there's a fair amount of potential but the film delivers too little to be worthwhile
len: 1159
Label: 0 ( Negative )
```
### 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 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 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 4 78
46 304 39 2 7 968 2 295 209 101 147 65 10 10
2643 2 497 8 30 6 147 284 5 996 174 10 10 11
4 130 4 2 4979 11 2 10 10 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> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <PAD> <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> the bad out takes from <UNK> of fire <UNK> together without any real story br br dean <UNK> tries to be a real actor and fails again br br in the end the <UNK> quit in <UNK> br br <UNK>
len: 2947
```
#### После обработки в начало отзыва добавилось необходимое количество токенов <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 ... 2 4050 2]
[ 0 0 0 ... 721 90 180]
[ 0 0 0 ... 1114 2 174]
...
[ 1 1065 2022 ... 7 1514 2]
[ 0 0 0 ... 6 879 132]
[ 0 0 0 ... 12 152 157]]
X test:
[[ 0 0 0 ... 10 342 158]
[ 0 0 0 ... 2 67 12]
[ 0 0 0 ... 1242 1095 1095]
...
[ 0 0 0 ... 4 2 136]
[ 0 0 0 ... 14 31 591]
[ 0 0 0 ... 7 3923 212]]
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_4 (Embedding) | (None, 500, 32) | 160,000 |
| lstm_4 (LSTM) | (None, 64) | 24,832 |
| dropout_4 (Dropout) | (None, 64) | 0 |
| dense_4 (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 = 5
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/5
313/313 ━━━━━━━━━━━━━━━━━━━━ 61s 184ms/step - accuracy: 0.8464 - loss: 0.3649 - val_accuracy: 0.8366 - val_loss: 0.3726
Epoch 2/5
313/313 ━━━━━━━━━━━━━━━━━━━━ 58s 184ms/step - accuracy: 0.8838 - loss: 0.2931 - val_accuracy: 0.8692 - val_loss: 0.3221
Epoch 3/5
313/313 ━━━━━━━━━━━━━━━━━━━━ 59s 188ms/step - accuracy: 0.9015 - loss: 0.2519 - val_accuracy: 0.8652 - val_loss: 0.3294
Epoch 4/5
313/313 ━━━━━━━━━━━━━━━━━━━━ 58s 185ms/step - accuracy: 0.9151 - loss: 0.2225 - val_accuracy: 0.8636 - val_loss: 0.3255
Epoch 5/5
313/313 ━━━━━━━━━━━━━━━━━━━━ 82s 184ms/step - accuracy: 0.9162 - loss: 0.2174 - val_accuracy: 0.8660 - val_loss: 0.3360
```
```python
test_loss, test_acc = model.evaluate(X_test, y_test)
print(f"\nTest accuracy: {test_acc}")
```
```
782/782 ━━━━━━━━━━━━━━━━━━━━ 38s 49ms/step - accuracy: 0.8659 - loss: 0.3349
Test accuracy: 0.865880012512207
```
### 10. Оценили качество обучения на тестовых данных:
### - вывели значение метрики качества классификации на тестовых данных
### - вывели отчет о качестве классификации тестовой выборки
### - построили ROC-кривую по результату обработки тестовой выборки и вычислили площадь под ROC-кривой (AUC ROC)
```python
#значение метрики качества классификации на тестовых данных
print(f"\nTest accuracy: {test_acc}")
```
```
Test accuracy: 0.865880012512207
```
```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']))
```
```
precision recall f1-score support
Negative 0.91 0.82 0.86 12500
Positive 0.83 0.92 0.87 12500
accuracy 0.87 25000
macro avg 0.87 0.87 0.87 25000
weighted avg 0.87 0.87 0.87 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))
```
![ROC кривая](output.png)
```
AUC ROC: 0.9420113727999999
```
### 11. Сделали выводы по результатам применения рекуррентной нейронной сети для решения задачи определения тональности текста.
Таблица1:
| Модель | Количество настраиваемых параметров | Количество эпох обучения | Качество классификации тестовой выборки |
|----------|-------------------------------------|---------------------------|-----------------------------------------|
| Рекуррентная | 184 897 | 5 | accuracy:0.8659 ; loss:0.3349 ; AUC ROC:0.9420 |
#### По результатам применения рекуррентной нейронной сети, а также по данным таблицы 1 можно сделать вывод, что модель хорошо справилась с задачей определения тональности текста. Показатель accuracy = 0.8659 превышает требуемый порог 0.8.
#### Значение AUC ROC = 0.9420 (> 0.9) говорит о высокой способности модели различать два класса (положительные и отрицательные отзывы). Модель показала хорошие результаты по метрикам precision и recall: для негативных отзывов precision = 0.91, recall = 0.82; для позитивных отзывов precision = 0.83, recall = 0.92.
Загрузка…
Отмена
Сохранить