Skip to content

Instantly share code, notes, and snippets.

@islamgulov
Created June 19, 2012 09:41
Show Gist options
  • Save islamgulov/2953283 to your computer and use it in GitHub Desktop.
Save islamgulov/2953283 to your computer and use it in GitHub Desktop.
#!/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()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment