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.0for 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.nofor 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.0for 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.0for k in range(self.no): error += 0.5 * (targets[k] - np.round_(self.ao[k])) ** 2 return error #用测试集输出准确率def test(self, patterns): count = 0num=0for p in patterns:target = p[1]result = self.update(p[0]) print(p[0], ':', target, '->', np.round_(result))num=0for k in range(self.no):if (target[k] == np.round_(result[k])):num +=1print(num)if num==3:count +=1print("******************",(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.0for 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.nofor 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.0for 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.0for k in range(self.no): error += 0.5 * (targets[k] - np.round_(self.ao[k])) ** 2 return error #用测试集输出准确率def test(self, patterns): count = 0num=0for p in patterns:target = p[1]result = self.update(p[0]) print(p[0], ':', target, '->', np.round_(result))num=0for k in range(self.no):if (target[k] == np.round_(result[k])):num +=1print(num)if num==3:count +=1print("******************",(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)