|
Пример использования ООП (нейронная сеть)
На этом занятии мы применим наши знания ООП в Python и реализуем
простую нейронную сеть. Пару слов, о том что это такое. Нейронная
сеть представляет собой вот такую распределенную структуру. Здесь у нас имеется
входной слой, далее несколько скрытых слоев нейронов и затем, выходной слой.
Принцип
ее работы такой. На вход подаются данные, представленные в виде вещественных
чисел от 0 до 1. Далее, эти числа проходят по связям между нейронами с разной
степенью затухания, определяемой множителем w_ij.
На входе каждого нейрона следующего слоя эти сигналы суммируются с учетом этих
весов и на основе этой суммы формируется выходной сигнал соответствующего
нейрона. Далее, эти сигналы подаются на нейроны следующего уровня, и так до
последнего выходного слоя. По этим выходным числовым значениям делается вывод о
свойствах входного сигнала. Разумеется, чтобы нейронная сеть работала, она
должна быть обучена, то есть, веса ее связей должны быть должным образом
настроены. Этот этап останется за рамками нашего занятия. Мы здесь лишь
реализуем построение нейронной сети со случайными весами связей, а внутри
каждого нейрона суммарный сигнал будет преобразовываться в выходной с помощью
вот такой сигмоидальной функции:
Здесь
z – это входной суммарный взвешенный сигнал, а y – выходное значение нейрона. Как видите, входной сигнал z из диапазона (-∞; +∞) масштабируется в диапазон (0;1).
Поэтому эту функцию еще называют масштабирующей. Она гарантирует, что выходные
значения всегда будут вещественными числами от 0 до 1.
Итак,
реализуем такую нейронную сеть, схематично она представлена вот в таком виде. И
начнем с описания класса нейронов.
Для
этого создадим отдельный файл, в котором будет класс Neuro:
import math
class Neuro:
def __init__(self, list_in, list_out):
self.__in = list_in
self.__out = list_out
self.value = 0 # выходной сигнал с нейрона
@property
def list_in(self):
return self.__in
@list_in.setter
def list_in(self, lst):
self.__in = lst
@property
def list_out(self):
return self.__out
@list_out.setter
def list_out(self, lst):
self.__out = lst
def act(self, x):
return 1/(1+math.exp(-x))
Далее,
создадим модуль для связей между нейронами:
class Link:
def __init__(self, n_in, n_out, w = 0):
self.__in = n_in
self.__out = n_out
self.__w = w
@property
def n_in(self):
return self.__in
@property
def n_out(self):
return self.__out
@property
def w(self):
return self.__w
И,
наконец, класс, описывающий создание и работы НС:
import random
from neuro import Neuro
from link import Link
class Network:
def __init__(self, *args):
self.__nlayers = len(args) # число слоев
self.__neuros = args # число нейронов в кажом слое
self.__layers = []
#создаем нейроны в каждом слое
for i in range( self.__nlayers ):
self.__layers.append( [Neuro([], []) for n in range(self.__neuros[i])] )
#создаем связи между нейронами
for i in range( self.__nlayers ):
for neuro in self.__layers[i]: # перебираем нейроны i-го слоя
list_in = 0 if i == 0 else [ Link(n_in, neuro, random.random()) for n_in in self.__layers[i-1] ]
list_out = 0 if i == self.__nlayers-1 else [Link(neuro, n_out, random.random()) for n_out in self.__layers[i+1]]
neuro.list_in = list_in
neuro.list_out = list_out
def run(self, v):
# подаем на вход нейронов сигнал v
for neuro, inp in zip(self.__layers[0], v):
neuro.value = neuro.list_in = inp
# проводим сигнал по нейронной сети
for i in range(1, self.__nlayers):
for neuro in self.__layers[i]: # перебираем нейроны i-го слоя
v = [ (link.n_in.value*link.w) for link in neuro.list_in ]
neuro.value = neuro.act( sum(v) )
def output(self):
return [ neuro.value for neuro in self.__layers[-1] ]
Все
это мы можем использовать, например, так:
from network import Network
net = Network(10, 5, 5)
net.run([1, 0.5, 0.1, 0.2, 0.7, 0.9, 1, 0.6, 0.3, 0.1])
out = net.output()
print( out )
Все, нейронная сеть готова!
|