81 lines
2.4 KiB
Python
81 lines
2.4 KiB
Python
|
#!/usr/bin/env python3
|
|||
|
# coding: utf-8
|
|||
|
import numpy as np
|
|||
|
|
|||
|
|
|||
|
# 计算tanh的值,激活函数
|
|||
|
def tanh(x):
|
|||
|
return np.tanh(x)
|
|||
|
|
|||
|
|
|||
|
# 求tanh的导数
|
|||
|
def tanh_deriv(x):
|
|||
|
return 1.0 - np.tanh(x)*np.tanh(x)
|
|||
|
|
|||
|
|
|||
|
# 逻辑函数
|
|||
|
def logistic(x):
|
|||
|
return 1.0/(1.0 + np.exp(-x))
|
|||
|
|
|||
|
|
|||
|
# 逻辑函数求导
|
|||
|
def logistic_deriv(x):
|
|||
|
return logistic(x)*(1.0 - logistic(x))
|
|||
|
|
|||
|
|
|||
|
class NeuralNetwork:
|
|||
|
def __init__(self, layers, activation='tanh'):
|
|||
|
"""
|
|||
|
:param layers: A list
|
|||
|
"""
|
|||
|
if activation == 'logistic':
|
|||
|
self.activation = logistic
|
|||
|
self.activation_deriv = logistic_deriv
|
|||
|
elif activation == 'tanh':
|
|||
|
self.activation = tanh
|
|||
|
self.activation_deriv = tanh_deriv
|
|||
|
|
|||
|
self.weights = []
|
|||
|
for i in range(1, len(layers) - 1):
|
|||
|
# 初始化 权值范围 [-0.25,0.25)
|
|||
|
# [0,1) * 2 - 1 => [-1,1) => * 0.25 => [-0.25,0.25)
|
|||
|
self.weights.append((2*np.random.random((layers[i - 1] + 1, layers[i] + 1))-1)*0.25)
|
|||
|
self.weights.append((2*np.random.random((layers[i] + 1, layers[i+1]))-1)*0.25)
|
|||
|
|
|||
|
def fit(self, x, y, learning_rate=0.2, epochs=10000):
|
|||
|
x = np.atleast_2d(x)
|
|||
|
temp = np.ones([x.shape[0], x.shape[1] + 1])
|
|||
|
temp[:, 0:-1] = x
|
|||
|
x = temp
|
|||
|
y = np.array(y)
|
|||
|
for k in range(epochs):
|
|||
|
i = np.random.randint(x.shape[0])
|
|||
|
a = [x[i]]
|
|||
|
|
|||
|
# 正向计算
|
|||
|
for l in range(len(self.weights)):
|
|||
|
a.append(self.activation(np.dot(a[l], self.weights[l])))
|
|||
|
# 反向传播
|
|||
|
error = y[i] - a[-1]
|
|||
|
deltas = [error*self.activation_deriv(a[-1])]
|
|||
|
|
|||
|
# 开始反向计算,从倒数第二层开始计算
|
|||
|
for j in range(len(a)-2, 0, -1):
|
|||
|
deltas.append(deltas[-1].dot(self.weights[j].T)*self.activation_deriv(a[j]))
|
|||
|
deltas.reverse()
|
|||
|
|
|||
|
# 更新权值
|
|||
|
for i in range(len(self.weights)):
|
|||
|
layer = np.atleast_2d(a[i])
|
|||
|
delta = np.atleast_2d(deltas[i])
|
|||
|
self.weights[i] += learning_rate * layer.T.dot(delta)
|
|||
|
|
|||
|
def predit(self, x):
|
|||
|
x = np.array(x)
|
|||
|
temp = np.ones(x.shape[0] + 1)
|
|||
|
temp[0:-1] = x
|
|||
|
a = temp
|
|||
|
for l in range(0, len(self.weights)):
|
|||
|
a = self.activation(np.dot(a, self.weights[l]))
|
|||
|
return a
|