1、关于非线性转化方程(non-linear transformation function)
sigmoid函数(S曲线)用来作为activation function
(1)双曲函数(tanh function)
双曲函数的导数:
(2)逻辑函数(logistic function)
逻辑函数的导数:
2、利用Python实现简单的神经网络算法
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:ZhengzhengLiu
import numpy as np
#定义双曲函数
def tanh(x):
return np.tanh(x)
#定义双曲函数的导数
def tanh_deriv(x):
return 1.0 - np.tanh(x)*np.tanh(x)
#定义逻辑函数
def logistic(x):
return 1 / (1 + np.exp(-x))
#定义逻辑函数的导数
def logistic_deriv(x):
return logistic(x) * (1 - logistic(x))
class NeuralNetwork:
# 构造函数,self参数:指向当前类的指针,相当于c++里面的this指针
def __init__(self,layers,activation='tanh'):
'''
:param layers: A list containing the number of units in each layer
(用一个列表包含每层的神经单元个数)should be at least two values
:param activation:The activation function to be used,can be 'logistic' or 'tanh'
非线性转化函数,在不指明时,默认情况下采用tanh
'''
if activation == 'logistic':
self.activation = logistic #将当前的非线性转化函数赋值给前面定义的logistic函数
self.activation_deriv = logistic_deriv
elif activation == 'tanh':
self.activation = tanh
self.activation_deriv = tanh_deriv
self.weights = [] #定义一个列表存放权重weight
#循环从1开始,相当于以第二层为基准,进行权重weight的初始化
for i in range(1,len(layers)-1):
#对当前神经结点的前续赋值
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)
#训练函数,X:训练集(二维矩阵),每行对应一个实例,每列对应实例特征值维度
#y:函数对实例进行分类的标记(class label),learning_rate为学习率,epochs:抽样的方法对神经网络进行更新的最大次数
def fit(self,X,y,learning_rate = 0.2,epochs = 10000):
X = np.atleast_2d(X) #确定X至少是二维数据
temp = np.ones([X.shape[0],X.shape[1]+1]) #初始化元素全为1的矩阵,行数与X相同,列数比X多1
temp[:,0:-1] = X #取X所有行,第1列至倒数第2列,进行偏向的赋值
X = temp
y = np.array(y) #将分类标记由list转换成numpy数组
for k in range(epochs): #抽样梯度下降epochs抽样
#随机抽取一行,对神经网络进行更新
# randint生成指定范围的整数,从X的行数(实例)中随机取一个整数:即随机取一行,随机取一个实例
i = np.random.randint(X.shape[0])
a = [X[i]] #随机从X中取一个实例
#完成所有的正向更新
for l in range(len(self.weights)):
# dot:內积,对应实例的值与权重乘积再求和,最后进行非线性转化
a.append(self.activation(np.dot(a[l],self.weights[l])))
error = y[i] - a[-1] #对于顶层,y[i]:真实的分类标记值,a[-1]:最后一层预测的分类标记值
deltas = [error*self.activation_deriv(a[-1])] #输出层误差
#开始反向计算误差,更新权重
for l in range(len(a)-2,0,-1): #从最后一层到第2层倒着循环
deltas.append(deltas[-1].dot(self.weights[l].T)*self.activation_deriv(a[l]))
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 predict(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