Лабораторные работы / intel_lab3
.pdfЗадание 2
1) В новом блокноте выполним п. 1-8 задания 1, изменив набор данных MNIST на CIFAR-10, содержащий размеченные цветные изображения объектов, разделенные на 10 классов.
Импортируем необходимые для работы библиотеки и модули.
import os
os.chdir('/content/drive/MyDrive/Colab Notebooks/IS_LR3')
# импорт модулей
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
Загрузим набор данных CIFAR-10, содержащий размеченные цветные изображения объектов, разделенные на 10 классов.
# загрузка датасета
from keras.datasets import cifar10
(X_train, y_train), (X_test, y_test) = cifar10.load_data()
Разобьем набор данных на обучающие (train) и тестовые (test) данные в соотношении 50000:10000 элементов. При разбиении параметр random_state выберем равным 87. Выведем размерности полученных обучающих и тестовых массивов данных.
# создание своего разбиения датасета
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 = 50000, random_state = 87)
11
# вывод размерностей
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 изображений из обучающей выборки с подписями классов.
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()
12
Результат:
Проведем предобработку данных: приведем обучающие и тестовые данные к формату, пригодному для обучения сверточной нейронной сети. Входные данные должны принимать значения от 0 до 1, метки цифр должны быть закодированы по принципу «one-hot encoding». Выведем размерности предобработанных обучающих и тестовых массивов данных.
#Зададим параметры данных и модели 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)
13
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)
Реализуем модель сверточной нейронной сети и обучим ее на обучающих данных с выделением части обучающих данных в качестве валидационных. Выведем информацию об архитектуре нейронной сети.
# создаем модель 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.Conv2D(128, 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(128, activation='relu'))
model.add(layers.Dense(num_classes, activation="softmax")) model.summary()
Результат:
Model: "sequential_3"
_________________________________________________________________
Layer (type) |
Output Shape |
Param # |
=================================================================
conv2d_9 (Conv2D) |
(None, 30, 30, 32) |
896 |
14
max_pooling2d_9 (MaxPooling (None, 15, 15, 32) |
0 |
|||
2D) |
|
|
|
|
conv2d_10 (Conv2D) |
(None, 13, 13, 64) |
18496 |
||
max_pooling2d_10 (MaxPoolin (None, 6, 6, 64) |
|
0 |
||
g2D) |
|
|
|
|
conv2d_11 (Conv2D) |
(None, 4, 4, 128) |
|
73856 |
|
max_pooling2d_11 (MaxPoolin (None, 2, 2, 128) |
|
0 |
||
g2D) |
|
|
|
|
dropout_3 (Dropout) |
(None, 2, 2, 128) |
0 |
|
|
flatten_3 (Flatten) |
(None, 512) |
0 |
|
|
dense_6 (Dense) |
(None, 128) |
65664 |
|
|
dense_7 (Dense) |
(None, 10) |
1290 |
|
|
=================================================================
Total params: 160,202 Trainable params: 160,202 Non-trainable params: 0
_________________________________________________________________
batch_size = 128 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 15/15
352/352 [==============================] - 52s 148ms/step - loss: 0.7663 - accuracy: 0.7301 - val_loss: 0.8061 - val_accuracy: 0.7164
Оценим качество обучения на тестовых данных. Выведем значение функции ошибки и значение метрики качества классификации на тестовых данных.
15
# Оценка качества работы модели на тестовых данных scores = model.evaluate(X_test, y_test)
print('Loss on test data:', scores[0]) print('Accuracy on test data:', scores[1])
Результат:
313/313 [==============================] - 4s 12ms/step - loss: 0.7931 - accuracy: 0.7214
Loss on test data: 0.7931023836135864 Accuracy on test data: 0.7214000225067139
Подадим на вход обученной модели два тестовых изображения. Выведем изображения, истинные значения и результаты распознавания.
# вывод тестового изображения и результата распознавания n = 89
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: ', class_names[np.argmax(y_test[n])]) print('NN answer: ', class_names[np.argmax(result)])
NN output: [[2.2425503e-04 4.0672859e-03 1.0446576e-02 1.2536058e-02 1.8755463e-04 1.0585570e-03 9.7064710e-01 6.5645945e-05 1.5527129e-04 6.1161834e-04]]
Real: frog
NN answer: frog
16
# вывод тестового изображения и результата распознавания n = 90
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: ', class_names[np.argmax(y_test[n])]) print('NN answer: ', class_names[np.argmax(result)])
NN output: [[0.00179091 0.00101446 0.05114046 0.183351 0.4820556 0.06516942 0.02695126 0.18641347 0.00098148 0.00113203]]
Real: cat
NN answer: deer
Выведем отчет о качестве классификации тестовой выборки и матрицу ошибок для тестовой выборки.
# истинные метки классов 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)
# красивая отрисовка матрицы ошибок в виде "тепловой карты" make_confusion_matrix(conf_matrix, categories=class_names, percent=False, figsize=(10,10))
17
Результат:
precision recall f1-score support
airplane |
|
0.78 |
|
0.74 |
0.76 |
1042 |
||
automobile |
|
0.91 |
0.79 |
|
0.85 |
990 |
||
bird |
|
0.73 |
|
0.47 |
|
0.57 |
964 |
|
cat |
0.46 |
0.69 |
0.55 |
978 |
||||
deer |
|
0.72 |
|
0.65 |
0.68 |
1017 |
||
dog |
|
0.67 |
|
0.61 |
0.64 |
1030 |
||
frog |
|
0.81 |
|
0.73 |
0.77 |
988 |
||
horse |
|
0.76 |
|
0.78 |
0.77 |
990 |
||
ship |
|
0.74 |
|
0.90 |
0.82 |
993 |
||
truck |
|
0.78 |
|
0.84 |
0.81 |
1008 |
||
accuracy |
|
|
|
|
0.72 |
10000 |
||
macro avg |
|
0.74 |
0.72 |
|
0.72 |
10000 |
||
weighted avg |
0.74 |
0.72 |
0.72 10000 |
18
2) Выводы.
Из полученных результатов видно, что значение метрики качества сверточной сети равно 0,721 и не слишком близко к идеальному, равному единице; значение ошибки на тестовых данных равно 0,793 и сильно отличается от идеального, равного нулю. Одно из двух тестовых изображений сеть распознала неверно. Значения параметров Precision, Recall, F1-score, рассчитанные для каждого из 10 классов, не слишком близки к идеальному (единице). Невзвешенное среднее и взвешенное среднее значения этих параметров также не близки к идеальным. Значение ошибки на валидационных данных достаточно велико: 0,8061. Следовательно, полученная сверточная нейронная сеть будет распознавать изображения с не слишком высокой точностью.
19