由于是小白,这篇bp的构建是参考了https://blog.csdn.net/huakai16/article/details/77479127#commentsedit
#!/user/bin/env python
# !-*-coding:utf-8 -*-
# !Time :2018/10/7 7:56 PM
# !Author : hyCong
# !@File : .py
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
from sklearn.datasets import load_digits # 数据集
from sklearn.preprocessing import LabelBinarizer # 标签二值化
from sklearn.cross_validation import train_test_split # 数据集分割
import numpy as np
import pylab as pl # 数据可视化
# digits = load_digits() # 导入数据,改数据集有1797张图片,每张图片有64个属性特征
# print digits.data.shape
# pl.gray() #图像灰度化
# pl.matshow(digits.images[1])
# pl.show()
def sigmoid(x): # 激活函数,隐层和输出层使用,这里使用sigmoid函数
return 1 / (1 + np.exp(-x)) # 1/(1+e的x次方)
# layers = [64, 100, 10]
# digits = load_digits()
# X = digits.data
# print np.atleast_2d(X[0])
def dsigmoid(x): # 取导数
return x * (1 - x)
class NeuralNetwork:
def __init__(self, layers): # 构造的网络现在是三层layers【64,100,10】 表示输入层 隐藏层 输出层的单元个数
# 初始化操作权值
self.V = np.random.random(
(layers[0] + 1, layers[1])) * 2 - 1 # 隐层的权值矩阵(65,100),多出来的一个是偏置值,65是64个输入层向量和一个偏置,100为隐层的神经元个数
self.W = np.random.random((layers[1], layers[2])) * 2 - 1 # (100,10) 输出层的权值矩阵,输出层神经元个数10个,输入的隐层向量是100个
def train(self, X, y, lr=0.1, epochs=10000):
# lr为学习率即步长,epochs为迭代次数
# 为数据集添加偏置
# 将X原来的shape数据集取出来并添加一列属性赋给temp,多加的一列就是偏置数,设为1
temp = np.ones([X.shape[0], X.shape[1] + 1]) # 建立一个行数和X.shape相同的矩阵,维数为X的维数+1
temp[:, 0: -1] = X
X = temp
# 通过for迭代更新权值
for n in range(epochs + 1):
i = np.random.randint(X.shape[0]) # X.shape[0]存放的是样本的个数,随机取出一个样本
x = X[i] # 取出一个样本
x = np.atleast_2d(x) # 将x一维数组转化二维数组
# 正向传播
L1 = sigmoid(np.dot(x, self.V)) # 隐层的输出,将输入层的样本矩阵和隐层的权值(已经包含了偏置)进行点乘
L2 = sigmoid(np.dot(L1, self.W)) # 输出层的数据矩阵,将隐层的输出矩阵和书橱层节点的权值矩阵(已添加偏置)进行点乘(100,10)
# 反向传播
# 根据推导出的输出层和隐藏层的误差公式进行计算
L2_delta = (y[i] - L2) * dsigmoid(
L2) # (Dk-Ok)*Ok*(1-Ok) (101*10) 输出层10个神经元,每个神经元对应这个100个隐层的神经元(和一个偏置)传来的激活值所对应的误差值
L1_delta = L2_delta.dot(self.W.T) * dsigmoid(L1) # 点乘求和 ,继续向后推算隐藏层的误差(65*100)
self.W += lr * L1.T.dot(L2_delta)
self.V += lr * x.T.dot(L1_delta)
# 每1000次预测准确率
if n % 1000 == 0:
predictions = []
for j in range(X_test.shape[0]):
out = self.predict(X_test[j]) # 使用验证集进行测试
predictions.append(np.argmax(out)) # 返回预测的结果
accuracy = np.mean(np.equal(predictions, y_test)) # 求预测结果与测试数据集的结果对比结果的平均值
print('epoch:', n, 'accuracy:', accuracy)
# 将测试数据向量x使用神经网络的两层权值进行计算输出
def predict(self, x):
# 为X添加一维
temp = np.ones(x.shape[0] + 1)
temp[0:-1] = x
x = temp
x = np.atleast_2d(x)
L1 = sigmoid(np.dot(x, self.V)) # 隐层输出
L2 = sigmoid(np.dot(L1, self.W)) # 输出层输出
return L2 # 返回输出层的输出向量
digits = load_digits() # 载入数据
X = digits.data
y = digits.target # 结果集
# 数据归一化,x=(x-x.min)/(x.max-x.min)
X = (X - X.min()) / (X.max() - X.min())
# 创建神经网络对象,设置输入层 隐层 输出层的神经元个数(特征数)
nm = NeuralNetwork([64, 100, 10])
X_train, X_test, y_train, y_test = train_test_split(X, y) # 将X和y进行随机划分为训练集和测试集
# 标签二值化
labels_train = LabelBinarizer().fit_transform(y_train)
labels_test = LabelBinarizer().fit_transform(y_test)
print "start"
nm.train(X_train, labels_train, epochs=60000)
print X_test[1]
for i in range(64):
if (X_test[1][i]) < 0.1:
print ' ',
elif (X_test[1][i])<0.2:
print '. ',
elif (X_test[1][i]) < 0.4:
print '- ',
elif (X_test[1][i])<0.9:
print '* ',
else:
print '@ ',
if (i + 1) % 8 == 0:
print '\n'
print np.argmax(nm.predict(X_test[1]))
print 'end'
使用训练之后的模型进行测试