Обучается нейронная сеть (НС), распознающая следующие образы:
Примеры распознаваемых изображений приведены на рис. 1.
Рис. 1. Примеры распознаваемых изображений
Изображения записаны в двоичные файлы dataTrain.bin, labelsTrain.bin, dataTest.bin, labelsTest.bin, содержащие соответственно обучающие и тестовые данные.
Файлы data* содержат сведения об изображениях, а файлы labels* – соответствующие им метки (табл. 1).
Таблица 1. Классы изображений и их метки
Класс | Метка |
---|---|
Часть параболы | 0 |
Парабола | 1 |
Часть экспоненты | 2 |
Экспонента | 3 |
Прямоугольник без одной стороны | 4 |
Прямоугольник | 5 |
Фактически метка – это номер класса.
Все изображения выполнены в оттенках серого цвета на площадке размером 64*64 пикселя.
Каждый пиксель содержит число в диапазоне [0, 255].
Всего в файле с обучающими данными находятся сведения о 600-х изображениях, а в файле с тестовыми данными – о 150-и.
Прямоугольники (рис. 2) отличаются размерами и положением.
Рис. 2. Примеры прямоугольников
Обучающие данные:
Число примеров в классах 0, 1, 2, 3, 4 и 5 соответственно 105, 102, 96, 106, 85 и 106.
Тестовые данные:
Число примеров в классах 0, 1, 2, 3, 4 и 5 соответственно 16, 29, 25, 24, 25 и 31.
Для распознавания образов обучается сверточная нейронная сеть.
# Реализуется сверточная нейронная сеть
import numpy as np
import sys # Для sys.exit()
import matplotlib.pyplot as plt
import keras
import time
from keras.models import Sequential
from keras.layers import Dense, <out, Flatten
from keras.layers import Conv2D, MaxPooling2D
#
def loadData(fn, fn2):
with open(fn, 'rb') as read_binary:
data = np.fromfile(read_binary, dtype = np.uint8)
with open(fn2, 'rb') as read_binary:
labels = np.fromfile(read_binary, dtype = np.uint8)
return data, labels
#
np.random.seed(348)
fn_train = 'dataTrain.bin'
fn_train_labels = 'labelsTrain.bin'
fn_test = 'dataTest.bin'
fn_test_labels = 'labelsTest.bin'
num_classes = 6 # Число классов
w, h = 64, 64 # Ширина и высота окна вывода рисунка
categorical = True
#
print('Число классов: ' + str(num_classes))
train_data, train_labels = loadData(fn_train, fn_train_labels)
test_data, test_labels = loadData(fn_test, fn_test_labels)
n_train = int(train_data.size / (w * h)) # Число рисунков для обучения
n_test = int(test_data.size / (w * h)) # Число тестовых рисунков
#
show = False # True or False
if show:
def plotData(k, data, class_number, i):
ttl = ''
if class_number == 0:
ttl = '1/2 parab'
elif class_number == 1:
ttl = 'parab'
elif class_number == 2:
ttl = '1/2 exp'
elif class_number == 3:
ttl = 'exp'
elif class_number == 4:
ttl = 'rect -1'
elif class_number == 5:
ttl = 'rect'
plt.subplot(2, 3, k)
plt.imshow(data[i], cmap = plt.get_cmap('gray'))
plt.title(ttl)
#
show_test = False # True or False
if show_test:
n = n_test
data_show = test_data.reshape(n, w, h)
labels = test_labels
else:
n = n_train
data_show = train_data.reshape(n, w, h)
labels = train_labels
def findClass(n, class_number):
for i in range(n):
if labels[i] == class_number:
return i
k = 0
for class_number in range(num_classes):
i = findClass(n, class_number)
k += 1
plotData(k, data_show, class_number, i)
plt.subplots_adjust(hspace = 0.25) # wspace
plt.show()
sys.exit()
#
train_data = train_data.reshape(n_train, w, h, 1)
test_data = test_data.reshape(n_test, w, h, 1)
train_data = train_data.astype('float32')
test_data = test_data.astype('float32')
train_data /= 255
test_data /= 255
test_labels_0 = test_labels # Для сравнения с результатами прогноза
if categorical:
train_labels = keras.utils.to_categorical(train_labels, num_classes)
test_labels = keras.utils.to_categorical(test_labels, num_classes)
#
print(train_data.shape[0], 'обучающих образов')
print(test_data.shape[0], 'тестовых образов')
#
model = Sequential()
model.add(Conv2D(4, kernel_size = (5, 5), strides = (1, 1), padding = 'same',
activation = 'relu', input_shape = (w, h, 1)))
model.add(MaxPooling2D(pool_size = (2, 2), strides = (2, 2), padding = 'same'))
model.add(Flatten())
model.add(Dense(64, activation = 'relu'))
model.add(Dense(num_classes, activation = 'softmax'))
model.compile(loss = 'mse', optimizer = 'adam', metrics = ['accuracy']) # loss = 'categorical_crossentropy' / mse
model.summary()
#
# Обучение
print('Обучение')
start_time = time.time()
model.fit(train_data, train_labels, batch_size = 10, epochs = 5, verbose = 0)
print('Время обучения: ', (time.time() - start_time))
#
print('Тестирование')
start_time = time.time()
score = model.evaluate(test_data, test_labels, verbose = 0)
print('Время тестирования: ', (time.time() - start_time))
#
print('Потери при тестировании: ', score[0])
print('Точность при тестировании:', score[1])
#
print("Прогноз")
classes = model.predict_classes(test_data) # , batch_size = 10
# np.sum(classes == test_labels_0) вернет сумму случаев, когда classes[i] = test_labels_0[i]
acc = np.sum(classes == test_labels_0) / n_test * 100
print("Точность прогнозирования: " + str(acc) + '%')
print(classes)
print("На самом деле:")
print(test_labels_0)
if acc < 100:
show = True
for i in range(n_test):
if classes[i] != test_labels_0[i]:
print('i = ' + str(i) + '. Прогноз: ' + str(classes[i]) + '. На самом деле: ' + str(test_labels_0[i]))
if show:
show = False
plt.subplot()
plt.imshow(test_data[i].reshape(w, h), cmap = plt.get_cmap('gray'))
plt.show()
Выводятся следующие сведения:
Число классов: 6
600 обучающих образов
150 тестовых образов
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d_1 (Conv2D) (None, 64, 64, 4) 104
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 32, 32, 4) 0
_________________________________________________________________
flatten_1 (Flatten) (None, 4096) 0
_________________________________________________________________
dense_1 (Dense) (None, 64) 262208
_________________________________________________________________
dense_2 (Dense) (None, 6) 390
=================================================================
Total params: 262,702
Trainable params: 262,702
Non-trainable params: 0
_________________________________________________________________
None
Обучение
Время обучения: 21.624690771102905
Тестирование
Время тестирования: 0.5269911289215088
Потери при тестировании: 0.000704589276574552
Точность при тестировании: 1.0
Прогноз
Точность прогнозирования: 100.0%
[2 2 0 4 5 2 2 4 0 3 5 1 3 2 5 4 5 3 5 5 1 1 5 1 5 2 0 1 2 5 4 3 1 2 3 2 3 1 3 2 3 3 3 4 4 4 4 5 3 0 3 0 5 1 4 5 4 1 5 3 3 5 1 3 3 5 1 2 5 4 2 0 4 5 5 3 2 5 5 0 1 0 3 2 4 0 5 5 4 4 3 5 1 5 3 1 0 1 5 2 2 1 4 1 1 5 1 1 4 5 1 4 4 2 4 1 5 4 4 2 2 2 0 2 1 5 4 0 4 5 1 3 0 1 1 0 2 1 5 2 2 3 2 1 3 3 0 1 4 0]
На самом деле:
[2 2 0 4 5 2 2 4 0 3 5 1 3 2 5 4 5 3 5 5 1 1 5 1 5 2 0 1 2 5 4 3 1 2 3 2 3 1 3 2 3 3 3 4 4 4 4 5 3 0 3 0 5 1 4 5 4 1 5 3 3 5 1 3 3 5 1 2 5 4 2 0 4 5 5 3 2 5 5 0 1 0 3 2 4 0 5 5 4 4 3 5 1 5 3 1 0 1 5 2 2 1 4 1 1 5 1 1 4 5 4 4 2 4 1 5 4 4 2 2 2 0 2 1 5 4 0 4 5 1 3 0 1 1 0 2 1 5 2 2 3 2 1 3 3 0 1 4 0]