Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python
- # -*- coding:utf-8 -*-
- import math
- import numpy
- def sigmoid(x):
- """вроде как лучше чем 1/(1+e^-x)"""
- return math.tanh(x)
- def dsigmoid(y):
- """лучше чем y*(1.-y)"""
- return 1. - y ** 2
- class NN:
- def __init__(self, ni, nh, no):
- """
- ni - кол-во входоов
- nh - кол-во нейронов в скрытном слое
- no - кол-во выходов
- """
- self.ni = ni + 1 # +1 смещения
- self.nh = nh + 1 # +1 смещения
- self.no = no
- # входы
- self.ai = numpy.ones(self.ni)
- self.ah = numpy.ones(self.nh)
- self.ao = numpy.ones(self.no)
- # генерим веса
- self.wi = numpy.random.random((self.ni, self.nh)) - 0.5
- self.wo = numpy.random.random((self.nh, self.no)) - 0.5
- # дельты изменения весов
- self.ci = numpy.zeros((self.ni, self.nh))
- self.co = numpy.zeros((self.nh, self.no))
- def update(self, inputs):
- if len(inputs) != self.ni - 1:
- raise ValueError, 'wrong number of inputs'
- # задаем вход
- for i in range(self.ni - 1):
- self.ai[i] = inputs[i]
- # считаем выходы в скрытном слое
- for j in range(self.nh - 1):
- total = 0.0
- for i in range(self.ni):
- total += self.ai[i] * self.wi[i][j]
- self.ah[j] = sigmoid(total)
- # считаем значение выходного слоя
- for k in range(self.no):
- total = 0.0
- for j in range(self.nh):
- total += self.ah[j] * self.wo[j][k]
- self.ao[k] = total
- return self.ao[:]
- def backpropagate(self, targets, N, M):
- "обратное распр. ошибки"
- if len(targets) != self.no:
- raise ValueError, 'wrong number of target values'
- # считаем ошибку на выходе
- output_deltas = numpy.zeros(self.no)
- for k in range(self.no):
- output_deltas[k] = targets[k] - self.ao[k]
- # считаем ошибки для скрытого слоя
- hidden_deltas = numpy.zeros(self.nh)
- for j in range(self.nh):
- error = 0.0
- for k in range(self.no):
- error += output_deltas[k] * self.wo[j][k]
- hidden_deltas[j] = dsigmoid(self.ah[j]) * error
- # обновляем выходные веса
- for j in range(self.nh):
- for k in range(self.no):
- change = output_deltas[k] * self.ah[j]
- self.wo[j][k] = self.wo[j][k] + N * change + M * self.co[j][k]
- self.co[j][k] = change
- # обновляем входные веса
- for i in range(self.ni):
- for j in range(self.nh):
- change = hidden_deltas[j] * self.ai[i]
- self.wi[i][j] = self.wi[i][j] + N * change + M * self.ci[i][j]
- self.ci[i][j] = change
- # считаем ошибку
- error = 0.0
- for k in range(len(targets)):
- error += 0.5 * ((targets[k] - self.ao[k]) ** 2)
- return error
- def test(self, patterns):
- tmp = []
- for p in patterns:
- # print p[0], ':', p[1], '->', self.update(p[0])
- print self.update(p[0])[0]
- tmp.append(self.update(p[0]))
- return tmp
- def train(self, patterns, iterations=1000, N=0.05, M=0.1):
- """N-скорость движения
- M - сглаживающий коэф"""
- for i in xrange(iterations):
- error = 0.0
- for p in patterns:
- self.update(p[0])
- tmp = self.backpropagate(p[1], N, M)
- error += tmp
- if i % 100 == 0:
- print '%i: error %-14f' % (i, error)
- else:
- print '%i: error %-14f' % (i, error)
- def demo():
- pat = [
- [[-1, -1], [2]],
- [[-0.8, -1], [2.72]],
- [[-1, -0.8], [0.92]],
- [[-0.6, -0.5], [1.03]],
- [[-0.7, -0.6], [1.1]],
- [[-0.4, -0.5], [1.43]],
- [[-0.5, -0.3], [0.77]],
- [[-0.3, -0.2], [0.94]],
- [[-0.2, -0.1], [0.95]],
- [[-0.1, 0], [0.98]],
- [[0, 0], [1]],
- [[0.1, 0], [0.98]],
- [[0.1, 0.2], [1.1]],
- [[0.2, 0.4], [1.4]],
- [[0.4, 0.6], [1.76]],
- [[0.6, 0.6], [1.36]],
- [[0.6, 0.7], [1.75]],
- [[0.7, 0.8], [1.94]],
- [[0.9, 1.], [2.38]],
- [[1., 1.], [2.]]
- ]
- #создаем персептерон с 2 входами, 2 скрыт. слоями и 1 выходом
- n = NN(2, 2, 1)
- n.train(pat)
- print "Проверка на выборке"
- n.test(pat)
- print "Тестовые примеры"
- n.test([
- ([0.15, 0.15], [1.0225]),
- ([-0.25, -0.25], [1.0625])
- ])
- if __name__ == '__main__':
- demo()
Add Comment
Please, Sign In to add comment