数据集使用iris数据集
# 开发时间:2021/11/5 15:07
import numpy as np
import math
import random
import string
import matplotlib as mpl
import matplotlib.pyplot as plt
import pandas
from pandas import read_csv
from sklearn.preprocessing import LabelEncoder # 编码
from sklearn.model_selection import train_test_split
# 导入数据
iris = pandas.read_csv('http://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data', header=None)
iris.columns=['SepalLengthCm', 'SepalWidthCm', 'PetalLengthCm', 'PetalWidthCm', 'Species']
size_mapping = {'Iris-virginica': 2, # 001
'Iris-versicolor': 1, # 010
'Iris-setosa': 0} # 100
iris['Species'] = iris['Species'].map(size_mapping)
arrary = iris.values
a = arrary[:100, :]
b = arrary[100:, :]
c = arrary[:100, 4]
# 独热编码
def onehot(targets, num_out):
onehot = np.zeros((num_out, targets.shape[0]))
for idx, val in enumerate(targets.astype(int)):
onehot[val, idx] = 1.
return onehot.T
# 生成一个矩阵,大小为m*n,并且设置默认零矩阵
def makematrix(m, n, fill=0.0):
a = []
for i in range(m):
a.append([fill] * n)
return a
# 函数sigmoid(),采用tanh,
def sigmoid(x):
return math.tanh(x)
# 函数sigmoid的派生函数
def derived_sigmoid(x):
return 1.0 - x ** 2
class BPNN:
def __init__(self, num_in, num_hidden, num_out):
self.num_in = num_in+1
self.num_hidden = num_hidden+1
self.num_out = num_out
self.active_in = [1.0] * self.num_in
self.active_hidden = [1.0] * self.num_hidden
self.active_out = [1.0] * self.num_out
self.wight_in = makematrix(self.num_in, self.num_hidden)
self.wight_out = makematrix(self.num_hidden, self.num_out)
# 对权值矩阵赋初值
for i in range(self.num_in):
for j in range(self.num_hidden):
self.wight_in[i][j] = np.random.normal(0.0, pow(self.num_hidden,-0.5)) # 5x4 输出num_in行,num_hidden列权重矩阵,随机生成满足正态分布的权重
for i in range(self.num_hidden):
for j in range(self.num_out):
self.wight_out[i][j] = np.random.normal(0.0, pow(self.num_out, -0.5))
# 最后建立动量因子(矩阵)
self.ci = makematrix(self.num_in, self.num_hidden)
self.co = makematrix(self.num_hidden, self.num_out)
def update(self, inputs):
if len(inputs) != self.num_in - 1:
raise ValueError('与输入层节点数不符')
# 数据输入输入层
for i in range(self.num_in - 1):
# self.active_in[i] = sigmoid(inputs[i]) #或者先在输入层进行数据处理
self.active_in[i] = inputs[i] # active_in[]是输入数据的矩阵
# 数据在隐藏层的处理
for i in range(self.num_hidden-1):
sum = 0.0
for j in range(self.num_in):
sum = sum + self.active_in[j] * self.wight_in[j][i]
self.active_hidden[i] = sigmoid(sum) # active_hidden[]是处理完输入数据之后存储,作为输出层的输入数据
# 数据在输出层的处理
for i in range(self.num_out):
sum = 0.0
for j in range(self.num_hidden):
sum = sum + self.active_hidden[j] * self.wight_out[j][i]
self.active_out[i] = sigmoid(sum)
return self.active_out[:]
def errorbackpropagate(self, targets, lr, m): # lr是学习率, m是动量因子
if len(targets) != self.num_out:
raise ValueError('与输出层节点数不符!')
# 首先计算输出层的误差
out_deltas = [0.0] * self.num_out
for i in range(self.num_out):
error = targets[i] - self.active_out[i]
out_deltas[i] = derived_sigmoid(self.active_out[i]) * error
# 然后计算隐藏层误差
hidden_deltas = [0.0] * self.num_hidden
for i in range(self.num_hidden):
error = 0.0
for j in range(self.num_out):
error = error + out_deltas[j] * self.wight_out[i][j]
hidden_deltas[i] = derived_sigmoid(self.active_hidden[i]) * error
# 首先更新输出层权值
for i in range(self.num_hidden):
for j in range(self.num_out):
change = out_deltas[j] * self.active_hidden[i]
self.wight_out[i][j] = self.wight_out[i][j] + lr * change + m * self.co[i][j]
self.co[i][j] = change
# 然后更新输入层权值
for i in range(self.num_in):
for j in range(self.num_hidden):
change = hidden_deltas[j] * self.active_in[i]
self.wight_in[i][j] = self.wight_in[i][j] + lr * change + m * self.ci[i][j]
self.ci[i][j] = change
# 计算总误差
error = 0.0
for i in range(self.num_out):
error = error + 0.5 * (targets[i] - self.active_out[i]) ** 2
return error
def train(self, a, itera=1000, lr=0.1, m=0.1):
for i in range(itera):
error = 0.0
for j in range(100):
inputs = a[j, 0:4]
d = onehot(c, self.num_out)
targets = d[j, :]
self.update(inputs)
error = error + self.errorbackpropagate(targets, lr, m)
if i % 100 == 0:
print('误差 %-.5f' % error)
def test(self, b):
for i in range(b.shape[0]):
print(b[i, 0:4], '->', self.update(b[i, 0:4]))
# 权重
def weights(self):
print("输入层权重")
for i in range(self.num_in):
print(self.wight_in[i])
print("输出层权重")
for i in range(self.num_hidden):
print(self.wight_out[i])
def Mytrain():
a = iris.values
# 创建神经网络,4个输入节点,X个隐藏层节点,1个输出层节点
n = BPNN(4, 8, 3)
# 训练神经网络
n.train(a)
n.weights()
n.test(b)
if __name__ == '__main__':
Mytrain()