Список работ

Распознавание графиков элементарных функций и простых 2d-фигур

Содержание

Введение

Обучается нейронная сеть (НС), распознающая следующие образы:

Примеры распознаваемых изображений приведены на рис. 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
print(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) вернет сумму случаев, когда classes[i] = test_labels[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]

Список работ

Рейтинг@Mail.ru