Список работ

Простая нейронная сеть на Python

Содержание

Введение

Нейронная сеть (НС), решающая, болен человек сахарным диабетом или нет, реализуется на Питоне с применением библиотеки TensorFlow с оболочкой Keras. Вывод графиков потерь и точности осуществлен средствами matplotlib.
Установка TensorFlow, Keras и прочих библиотек выполняется в командном окне, которое в Windows открывается после нажатия Win + X.
Установка обычной или GPU-версий Tensorflow [1]:

<path>/Scripts/pip3 install --upgrade tensorflow
<path>/Scripts/pip3 install --upgrade tensorflow-gpu

Например, установка matplotlib:

C:/Users/HP/AppData/Local/Programs/Python/Python36/Scripts/pip3 install matplotlib

Установка обычной и GPU-версий Keras:

<path>/Scripts/pip3 install keras

Обучение проводится по следующим данным:

Примеры данных приведены на рис. 1.

Диагностика диабета

Рис. 1. Диагностические данные

Всего в таблице 768 строк. Данные разбиваются на две части: обучающую и для тестирования. Каждая часть, в свою очередь, разбивается на матрицу с данными и вектор с выходными данными (последний столбец исходной таблицы). В обучающую выборку (массивы trainData и trainOutput) включаются первые 3/4 строк исходной таблицы, последующие строки попадают в выборку для проверки сети (массивы testData и testOutput).
Данные находятся в csv-файле и описаны в [2]. В качестве разделителя используется точка с запятой.

Структура сети

Взята полносвязная нейронная сеть с тремя скрытыми слоями. Структура сети приведена в табл. 1:

Таблица 1. Структура НС

СлойФункция активацииЧисло нейронов
Входной
Первый скрытый слойReLU16 
Второй скрытый слойТа же32 
Третий скрытый слойТа же16 
ВыходнойSigmoid

Графики функций активации ReLU и Sigmoid показаны на рис. 2.

RelU и Sigmoid

Рис. 2. Функции активации RelU и Sigmoid

На рис. 3, а показаны схема перцептрона (для иллюстрации идеи архитектуры НС) и архитектура полносвязной НС (б) с одним скрытым слоем.

Архитектура полносвязной НС

Рис. 3. Архитектура полносвязной НС: а – перцептрон; б – полносвязная НС; в – пороговая функция перцептрона

Перцептрон (рис. 3, а) обеспечивает бинарную классификацию – все объекты будут отнесены перцептроном к одному из двух классов; h – пороговая функция (рис. 3, в). Перцептрон можно рассматривать как модель искусственного нейрона, построенную по аналогии с моделью биологического нейрона (рис. 4).

Биологический нейрон

Рис. 4. Модель биологического нейрона

Биологический нейрон передает информацию с помощью электрических и химических сигналов. Нейрон состоит из тела нейрона и отростков: дендритов и аксона, которые связывают нейроны в нейронную сеть. Дендриты отвечают за приём сигналов от других нейронов, а аксон – за передачу сигналов. Аксон заканчивается концевой ветвью (терминалью), которая образует с дендритами другого нейрона соединение – синапс. Синапс способен менять форму при изменении разности потенциалов. Изменение формы влияет на силу передачи сигналов. Выход нейрона распределяется по многим синапсам на множество нейронов и наоборот на данный нейрон сходятся синапсы от множества источников [3].
Дендритами искусственного нейрона являются его связи с другими нейронами или входными данными, которые выражаются в числовом векторе w1, w2, …, wn, называемым вектором весов. Он определяет силу синаптической связи с другими нейронами или входными данными.

Реализация

import sys, os, numpy, keras
import matplotlib.pyplot as plt
from tkinter import messagebox # Вывод сообщений
from keras.models import Sequential # Модель полносвязной НС
from keras.layers import Dense # Добавление слоя
from keras import optimizers
#
class LossHistory(keras.callbacks.Callback):
    def on_train_begin(self, logs={}):
        self.losses = []
        self.acc = []
    def on_batch_end(self, batch, logs={}):
        self.losses.append(logs.get('loss'))
        self.losses.append(logs.get('acc'))
#
file = "G:/python/SimpleNN/pima_indians_diabetes.csv"
if os.path.exists(file):
    print ("Файл найден")
else:
    print ("Файл не найден")
    exit()
# Задание затравки датчика случайных чисел обеспечит повторяемость результата
numpy.random.seed(348)
# Загружаем диагностические данные для обучения сети
# Файл с данными - это таблица из 8 столбцов; в последнем стобце 0, если нет диабета, или 1 - в противном случае
allData = numpy.loadtxt(file, delimiter = ";")
# allData[0, 0]) - первый элемент матрицы
# trainData - матрица параметров (диагностические данные, первые 8 столбцов в табл. рис. 1);
# trainOutput - выход сети (0 или 1, см. последний столбец в табл. на рис. 1)
allDataLen = len(allData[:, 0])
print(allDataLen) # 768
# Размер порция тренировочных данные (обучающей данных)
trainDataLen = int(3 * allDataLen / 4)
# Тренировочные и проверочные данные
trainData, trainOutput = allData[0:trainDataLen, :7], allData[0:trainDataLen, 8]
testData, testOutput = allData[trainDataLen + 1:, :7], allData[trainDataLen + 1:, 8]
# Создаем НС
model = Sequential()
# Для входного слоя необходимо указать input_dim - число входных данных
# 12 - число выходов первого слоя
# relu - функция активации нейрона
actFun = 'relu'
actFun2 = 'sigmoid'
model.add(Dense(16, input_dim = 7, activation = actFun))
# 32 - число выходов второго слоя; число входов равно числу выходов предшествующего слоя
model.add(Dense(32, activation = actFun))
model.add(Dense(16, activation = actFun))
# sigmoid - функция активация нейрона последнего слоя
model.add(Dense(1, activation = actFun2))
# Компиляция НС с функцией потерь cross entropy
# и использованием алгоритма Adam для обновления весов НС
lossFun = 'mean_absolute_error'
# Виды функцции потерь:
# mean_squared_error; mean_absolute_error; mean_absolute_percentage_error
# mean_squared_logarithmic_error; squared_hinge; hinge;
# categorical_hinge; logcosh; categorical_crossentropy;
# sparse_categorical_crossentropy; binary_crossentropy;
# kullback_leibler_divergence; cosine_proximity
# optKind = 'Adam'
# Виды методов оптимизации:
# SGD; RMSprop; Adagrad; Adadelta; Adam; Adamax; Nadam; TFOptimizer
# Вариант задания метода оптимизации
# optKind = optimizers.SGD(lr = 0.01, decay = 1e-6, momentum = 0.9, nesterov = True)
optKind = 'Adamax'
model.compile(loss = lossFun, optimizer = optKind, metrics = ['accuracy'])
#
# Обучение нейронной сети
print('\nОбучение')
# epochs - число обучающих эпох
# batch_size - параметр, определяющий форму входного массива
# В случае 2D (это наш случай), на входе сети будет массив формы (batch_size, input_dim)
# CallBack
history = LossHistory()
model.fit(trainData, trainOutput, epochs = 6, batch_size = 30, verbose = 2, callbacks = [history])
#
# Оценка результата
print('\nТестирование')
scores = model.evaluate(testData, testOutput, verbose = 2)
#scores = model.evaluate(trainData, trainOutput)
print("%s: %.2f%%" % (model.metrics_names[0], scores[0]*100)) # loss (потери)
print("%s: %.2f%%" % (model.metrics_names[1], scores[1]*100)) # acc (точность)
# messagebox.showinfo(title = "Done", message = "Готово")
#
# Графики изменения потерь и точности в процессе обучения
#print(history.losses)
rng = numpy.arange(len(history.losses))
#
# Вариант 1
fig, ax = plt.subplots(figsize = (8, 4))
ax.scatter(rng, history.losses, marker = 'o', c = 'red', edgecolor = 'black', label = 'Losses')
ax.scatter(rng, history.acc, marker = 'o', c = 'blue', edgecolor = 'black', label = 'Accuracy')
ax.set_title('Losses, Accuracy while training')
ax.legend(loc = 'upper left')
ax.set_ylabel('Losses, Accuracy')
ax.set_xlabel('Step')
ax.set_xlim([0, len(history.losses)])
ax.set_ylim([0, 1])
fig.show()
#
# Другой вариант вывода графиков потерь и точности
"""
plt.title('Losses, Accuracy while training')
plt.scatter(rng, history.losses, marker = 'o', c = 'r', edgecolor = 'black', label = 'Losses')
plt.scatter(rng, history.acc, marker = 'o', c = 'b', edgecolor = 'black', label = 'Accuracy')
plt.legend(loc = 'upper left')
plt.xlim([0, len(history.losses)])
plt.ylim([0, 1])
plt.ylabel('Losses, Accuracy')
plt.xlabel('Step')
plt.show()
"""

По ходу обучения выводятся следующие сведения:

Using TensorFlow backend.
Файл найден
768

Обучение
Epoch 1/6
- 1s - loss: 0.5036 - acc: 0.4913
Epoch 2/6
- 0s - loss: 0.3438 - acc: 0.6563
Epoch 3/6
- 0s - loss: 0.3431 - acc: 0.6562
Epoch 4/6
- 0s - loss: 0.3429 - acc: 0.6580
Epoch 5/6
- 0s - loss: 0.3428 - acc: 0.6580
Epoch 6/6
- 0s - loss: 0.3429 - acc: 0.6580

Тестирование
loss: 36.65%
acc: 63.35%

Потери и точность на каждом шаге обучения показаны на рис. 5.

Потери и точность

Рис. 5. Графики изменения потерь и точности на этапе обучения сети

Для вывода графиков потерь и точности, иллюстрирующих процесс обучения, создан класс LossHistory.
Экземпляр history этого класса использован в качестве callBack-параметра метода model.fit.
Свойства losses и acc рассматриваемого класса являются массивами, в которых накапливаются потери и точность, вычисляемые в процессе обучения, продолжительность которого определяется параметром batch_size.

Заключение

Приведен пример употребления полносвязной нейронной сети. Использована оболочка Keras, обеспечивающая доступ к TensorFlow. Невысокая точность классификации объясняется непродолжительным обучением, малым размером обучающих данных и неподходящей архитектурой НС.

Литература

  1. TensorFlow. [Электронный ресурс] URL: https://www.tensorflow.org/install/install_windows (Дата обращения: 27.05.2018).
  2. Pima Indians Diabetes Database. [Электронный ресурс] URL: https://www.kaggle.com/uciml/pima-indians-diabetes-database/data (Дата обращения: 27.05.2018).
  3. Шеперд Г. Нейробиология: В 2-х т. Т. 1. Пер. с англ. – М.: Мир, 1987. 454 с.

Список работ

Рейтинг@Mail.ru