数据集:鸢尾花数据
iris.csv
附上数据集:链接:https://pan.baidu.com/s/1OwpiKGctr1QDFeP42dR2Bw
提取码:htgl
实现
读取iris.csv文件处理
def get_iris():
name = ['f1', 'f2', 'f3', 'f4', 'y']
data = pd.read_csv('iris.csv', encoding='ascii', names=name)
data = data.replace('Iris-setosa', 0)
data = data.replace('Iris-versicolor', 1)
data = data.replace('Iris-virginica', 2)
data['y'].astype(int)
print(data.dtypes)
raw_data = data.to_numpy()
y = np.zeros([len(raw_data), 3])
x = np.zeros([len(raw_data), 4])
for i in range(len(raw_data)):
x[i, :] = raw_data[i, :4]
if raw_data[i, 4] == 0:
y[i, :] = np.array([1, 0, 0])
elif raw_data[i, 4] == 1:
y[i, :] = np.array([0, 1, 0])
else:
y[i, :] = np.array([0, 0, 1])
return x,y
这里我将类别Iris-setosa的鸢尾花 表示成[1,0,0],类别为Iris-versicolor的鸢尾花表示成[0,1,0],类别为Iris-virginica的鸢尾花表示成[0,0,1]。
神经网络:
import numpy as np
import pandas as pd
import os
from BP.test import get_iris
def rand(a, b):
return (b - a) * np.random.random() + a
def make_matrix(m, n, fill=0.0):
return np.full([m, n], fill)
def sigmoid(x):
return 1.0 / (1.0 + np.math.exp(-x))
def sigmoid_derivative(x):
return x * (1 - x)
class BPNN:
def __init__(self, input_num, hidden_num, output_num):
self.input_num = input_num + 1
self.hidden_num = hidden_num + 1
self.output_num = output_num
self._active_in = np.ones(self.input_num)
self._active_hidden = np.ones(self.hidden_num)
self._active_out = np.ones(self.output_num)
# 创建权重矩阵
self.weight_in = make_matrix(self.input_num, self.hidden_num)
self.weight_out = make_matrix(self.hidden_num, self.output_num)
# 对权值矩阵随机初始化初值
for i in range(self.input_num):
for j in range(self.hidden_num - 1):
self.weight_in[i][j] = rand(-0.2, 0.2)
for i in range(self.hidden_num):
for j in range(self.output_num):
self.weight_out[i][j] = rand(-0.2, 0.2)
# 误差
self._output_deltas = np.zeros(self.output_num)
self._hidden_deltas = np.zeros(self.hidden_num)
# 最后建立动量因子(矩阵)
self.ci = make_matrix(self.input_num, self.hidden_num)
self.co = make_matrix(self.hidden_num, self.output_num)
def forward_propagation(self, input):
assert len(input) == self.input_num - 1, "error"
for i in range(self.input_num - 1):
self._active_in[i] = input[i]
for j in range(self.hidden_num - 1): # 最后一个是偏执段元?
sum = 0.
for i in range(self.input_num):
sum += self._active_in[i] * self.weight_in[i][j]
self._active_hidden[j] = sigmoid(sum)
for k in range(self.output_num):
sum = 0.
for j in range(self.hidden_num):
sum += self._active_hidden[j] * self.weight_out[j][k]
self._active_out[k] = sigmoid(sum)
return self._active_out[:]
def backward_propagation(self, label, learning_rate=0.1, m=0.1):
# 计算输出层的误差
# for k in range(self.output_num):
# self._output_deltas[k]=(self._active_out[k]-label[k])*sigmoid_derivative(self._active_out[k])
# print(self._output_deltas)
self._output_deltas = (label - self._active_out) * sigmoid_derivative(self._active_out)
# 计算隐藏层的误差
for i in range(self.hidden_num - 1):
error = 0.
for j in range(self.output_num):
error += self.weight_out[i][j] * self._output_deltas[j]
self._hidden_deltas[i] = error * sigmoid_derivative(self._active_hidden[i])
i = self.hidden_num - 1
for j in range(self.output_num):
error += 1 * self._output_deltas[j]
self._hidden_deltas[i] = error * sigmoid_derivative(self._active_hidden[i])
# self._hidden_deltas = ((self.weight_out).dot(self._output_deltas) * sigmoid_derivative(self._active_hidden)).flatten()
# 更新输出层权值
for j in range(self.hidden_num - 1):
for k in range(self.output_num):
change = (self._output_deltas[k] * self._active_hidden[j])
self.weight_out[j][k] += learning_rate * change + m * self.co[j][k]
self.co[j][k] = change
j = self.hidden_num - 1
for k in range(self.output_num):
self.weight_out[j][k] += learning_rate * self._output_deltas[k] + m * self.co[j][k]
self.co[j][k] = self._output_deltas[k]
# print(self.weight_out)
# 更新输入层权值
for i in range(self.input_num - 1):
for j in range(self.hidden_num - 1):
change = (self._hidden_deltas[j] * self._active_in[i])
self.weight_in[i][j] += learning_rate * change + m * self.ci[i][j]
self.ci[i][j] = change
i = self.input_num - 1
for j in range(self.hidden_num - 1):
self.weight_in[i][j] += learning_rate * self._hidden_deltas[j] + m * self.ci[i][j]
self.ci[i][j] = self._hidden_deltas[j]
# print(self.weight_in)
error = 0.0
for o in range(len(label)):
error += 0.5 * (label[o] - self._active_out[o]) ** 2
return error
def test(self, label, target):
for i in range(len(label)):
print(target[i], '->', self.forward_propagation(label[i]))
def weights(self):
print("输入层权重")
for i in range(self.input_num):
print(self.weight_in[i])
print("输出层权重")
for i in range(self.hidden_num):
print(self.weight_out[i])
def train(self, label, target, itera=10000, lr=0.01, m=0.1):
for i in range(itera):
error = 0.0
for j in range(len(label)):
inputs = label[j]
targets = target[j]
self.forward_propagation(inputs)
error = error + self.backward_propagation(targets, lr, m)
if i % 100 == 0:
print('误差 %-.5f' % error)
def demo():
x, y = get_iris()
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(x, y, random_state=10)
# 创建神经网络,4个输入节点,10个隐藏层节点,3个输出层节点
n = BPNN(4, 10, 3)
# 训练神经网络
n.train(X_train, y_train)
# 测试神经网络
n.test(X_test, y_test)
# 查阅权重值
n.weights()
if __name__ == '__main__':
demo()
运行结果