81 lines
2.4 KiB
Python
Executable File
81 lines
2.4 KiB
Python
Executable File
#!/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
|