python实现神经网络模型算法
今天,厾罗和大家分享用Python实现神经网络模型算法,仅用于技术学习交流。
实现技巧
1.导入依赖库
主要是安装相关的依赖库。本文实现的环境为:python 3.7。
from __future__ import division
import math
import random
import pandas as pd
2.构建BP神经网络类
主要是构建三层反向传播神经网络类。
""" 三层反向传播神经网络 """
class NN:
def __init__(self, ni, nh, no):
self.ni = ni + 1 # 输入层节点
self.nh = nh + 1 # 隐藏层节点
self.no = no # 输出层种类
self.ai = [1.0] * self.ni
self.ah = [1.0] * self.nh
self.ao = [1.0] * self.no
self.wi = self.makeMatrix(self.ni, self.nh) # 输出层到隐藏层的映射矩阵
self.wo = self.makeMatrix(self.nh, self.no) # 隐藏层到输出层的映射矩阵
for i in range(self.ni):
for j in range(self.nh):
self.wi[i][j] = self.rand(-0.2, 0.2)
for j in range(self.nh):
for k in range(self.no):
self.wo[j][k] = self.rand(-2, 2)
#前向传播,激活神经网络的所有节点
def update(self, inputs):
if len(inputs) != self.ni - 1:
print(len(inputs),self.ni - 1)
raise ValueError('与输入层节点数不符!')
for i in range(self.ni - 1):
self.ai[i] = inputs[i]
for j in range(self.nh): # self.nh表示隐藏层的节点数
sum = 0.0 # 激活项a = g(z) z = Θ^T x ;sum相当于z,每次循环归零
for i in range(self.ni): #通过循环z = Θ^T x ,因为Θ、x均为向量
sum = sum + self.ai[i] * self.wi[i][j] #〖 Z〗^((2))=Θ^((1)) a^((1))
self.ah[j] = self.sigmoid(sum) # a^((2))=g(z^((2))),这里使用sigmoid()函数作为激活函数
for k in range(self.no):
sum = 0.0
for j in range(self.nh):
sum = sum + self.ah[j] * self.wo[j][k] #〖 Z〗^((3))=Θ^((2)) a^((2))
self.ao[k] = self.sigmoid(sum) # a^((3))=g(z^((3)))
return self.ao[:]
#反向传播,计算节点激活项的误差
def backPropagate(self, targets, lr): # targets为某样本实际种类分类,lr为梯度下降算法的学习率
output_deltas = [0.0] * self.no
for k in range(self.no):
error = targets[k] - np.round_(self.ao[k])
output_deltas[k] = self.dsigmoid(self.ao[k]) * error
# 计算隐藏层的误差
hidden_deltas = [0.0] * self.nh
for j in range(self.nh):
error = 0.0
for k in range(self.no):
error = error + output_deltas[k] * self.wo[j][k]
hidden_deltas[j] = self.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] + lr * 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] + lr * change
# 计算误差
error = 0.0
for k in range(self.no):
error += 0.5 * (targets[k] - np.round_(self.ao[k])) ** 2
return error
#用测试集输出准确率
def test(self, patterns):
count = 0
num=0
for p in patterns:
target = p[1]
result = self.update(p[0])
print(p[0], ':', target, '->', np.round_(result))
num=0
for k in range(self.no):
if (target[k] == np.round_(result[k])):
num +=1
print(num)
if num==3:
count +=1
print("******************",(target) == (np.round_(result)),"******************")
accuracy = int(float(count / len(patterns))*100)
print('accuracy: %-.9f' % accuracy,"%")
#输出训练过后神经网络的权重矩阵
def weights(self):
print('输入层权重:')
for i in range(self.ni):
print(self.wi[i])
print()
print('输出层权重:')
for j in range(self.nh):
print(self.wo[j])
#用训练集训练神经网络
def train(self, patterns, iterations=1000, lr=0.1):
for i in range(iterations):
error = 0.0
for p in patterns:
inputs = p[0]
targets = p[1]
self.update(inputs)
error = error + self.backPropagate(targets, lr)
if i % 100 == 0:
print("percent:",int(i/iterations*100),"%",' error: %-.9f' % error)
#生成区间[a, b)内的随机数
def rand(self, a, b):
return (b - a) * random.random() + a
# 生成大小 I*J 的矩阵,默认零矩阵
def makeMatrix(self, I, J, fill=0.0):
m = []
for i in range(I):
m.append([fill] * J)
return m
# 函数 sigmoid,bp神经网络前向传播的激活函数
def sigmoid(self, x):
return 1.0 / (1.0 + math.exp(-x))
# 函数 sigmoid 的导数,反向传播时使用
def dsigmoid(self, x):
return x * (1 - x)
3.读取数据并进行预处理
主要是读取构建分类模型的数据,并进行预处理。
data = []
raw = pd.read_csv('iris.csv')
raw_data = raw.values
raw_feature = raw_data[1:, 1:5]
for i in range(len(raw_feature)):
ele = []
ele.append(list(raw_feature[i]))
if raw_data[i][5] == 0:
ele.append([0, 0,1])
elif raw_data[i][5] == 1:
ele.append([0,1, 0])
elif raw_data[i][5] == 2:
ele.append([1, 1,1])
else:
ele.append([0, 0,0])
data.append(ele)
4.利用构建的BP神经网络预测类,创建神经网络模型
主要是用BP神经网络预测类创建神经网络类模型。
nn = NN(4, 10, 3)
5.BP分类模型训练及预测
主要是划分训练集和测试集,并进行BP分类模型训练和预测。
training = data[1:100]
test = data[101:]
nn.train(training, iterations=1000)
nn.test(test)
完整源代码
from __future__ import division
import math
import random
import pandas as pd
import numpy as np
""" 三层反向传播神经网络 """
class NN:
def __init__(self, ni, nh, no):
self.ni = ni + 1 # 输入层节点
self.nh = nh + 1 # 隐藏层节点
self.no = no # 输出层种类
self.ai = [1.0] * self.ni
self.ah = [1.0] * self.nh
self.ao = [1.0] * self.no
self.wi = self.makeMatrix(self.ni, self.nh) # 输出层到隐藏层的映射矩阵
self.wo = self.makeMatrix(self.nh, self.no) # 隐藏层到输出层的映射矩阵
for i in range(self.ni):
for j in range(self.nh):
self.wi[i][j] = self.rand(-0.2, 0.2)
for j in range(self.nh):
for k in range(self.no):
self.wo[j][k] = self.rand(-2, 2)
#前向传播,激活神经网络的所有节点
def update(self, inputs):
if len(inputs) != self.ni - 1:
print(len(inputs),self.ni - 1)
raise ValueError('与输入层节点数不符!')
for i in range(self.ni - 1):
self.ai[i] = inputs[i]
for j in range(self.nh): # self.nh表示隐藏层的节点数
sum = 0.0 # 激活项a = g(z) z = Θ^T x ;sum相当于z,每次循环归零
for i in range(self.ni): #通过循环z = Θ^T x ,因为Θ、x均为向量
sum = sum + self.ai[i] * self.wi[i][j] #〖 Z〗^((2))=Θ^((1)) a^((1))
self.ah[j] = self.sigmoid(sum) # a^((2))=g(z^((2))),这里使用sigmoid()函数作为激活函数
for k in range(self.no):
sum = 0.0
for j in range(self.nh):
sum = sum + self.ah[j] * self.wo[j][k] #〖 Z〗^((3))=Θ^((2)) a^((2))
self.ao[k] = self.sigmoid(sum) # a^((3))=g(z^((3)))
return self.ao[:]
#反向传播,计算节点激活项的误差
def backPropagate(self, targets, lr): # targets为某样本实际种类分类,lr为梯度下降算法的学习率
output_deltas = [0.0] * self.no
for k in range(self.no):
error = targets[k] - np.round_(self.ao[k])
output_deltas[k] = self.dsigmoid(self.ao[k]) * error
# 计算隐藏层的误差
hidden_deltas = [0.0] * self.nh
for j in range(self.nh):
error = 0.0
for k in range(self.no):
error = error + output_deltas[k] * self.wo[j][k]
hidden_deltas[j] = self.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] + lr * 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] + lr * change
# 计算误差
error = 0.0
for k in range(self.no):
error += 0.5 * (targets[k] - np.round_(self.ao[k])) ** 2
return error
#用测试集输出准确率
def test(self, patterns):
count = 0
num=0
for p in patterns:
target = p[1]
result = self.update(p[0])
print(p[0], ':', target, '->', np.round_(result))
num=0
for k in range(self.no):
if (target[k] == np.round_(result[k])):
num +=1
print(num)
if num==3:
count +=1
print("******************",(target) == (np.round_(result)),"******************")
accuracy = int(float(count / len(patterns))*100)
print('accuracy: %-.9f' % accuracy,"%")
#输出训练过后神经网络的权重矩阵
def weights(self):
print('输入层权重:')
for i in range(self.ni):
print(self.wi[i])
print()
print('输出层权重:')
for j in range(self.nh):
print(self.wo[j])
#用训练集训练神经网络
def train(self, patterns, iterations=1000, lr=0.1):
for i in range(iterations):
error = 0.0
for p in patterns:
inputs = p[0]
targets = p[1]
self.update(inputs)
error = error + self.backPropagate(targets, lr)
if i % 100 == 0:
print("percent:",int(i/iterations*100),"%",' error: %-.9f' % error)
#生成区间[a, b)内的随机数
def rand(self, a, b):
return (b - a) * random.random() + a
# 生成大小 I*J 的矩阵,默认零矩阵
def makeMatrix(self, I, J, fill=0.0):
m = []
for i in range(I):
m.append([fill] * J)
return m
# 函数 sigmoid,bp神经网络前向传播的激活函数
def sigmoid(self, x):
return 1.0 / (1.0 + math.exp(-x))
# 函数 sigmoid 的导数,反向传播时使用
def dsigmoid(self, x):
return x * (1 - x)
if __name__ == '__main__':
data = []
raw = pd.read_csv('iris.csv')
raw_data = raw.values
raw_feature = raw_data[1:, 1:5]
for i in range(len(raw_feature)):
ele = []
ele.append(list(raw_feature[i]))
if raw_data[i][5] == 0:
ele.append([0, 0,1])
elif raw_data[i][5] == 1:
ele.append([0,1, 0])
elif raw_data[i][5] == 2:
ele.append([1, 1,1])
else:
ele.append([0, 0,0])
data.append(ele)
nn = NN(4, 10, 3)
training = data[1:100]
test = data[101:]
nn.train(training, iterations=1000)
nn.test(test)