#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
写一个三层的BP神经网络(3,2,1),3是输入数据的维度,隐层设置节点数为2,1是因为每个观测的target都是一个标量即只有一个数;
1.随机生成两个随机矩阵作为三个层之间的连接权值,注意矩阵大小设置;设定误差阈值等参数
2.使用i=random.randint(0,len(x)-1)随机产生一个样品的输入及target
3.使用权值w1,w2,sigmoid函数、diffsigmoid函数计算隐层和输出层的输入,输出
4.利用上面的随机样品的实际输出和期望输出之差e,用e求偏导de/dwho、de/dwih
5.梯度下降法更新权值w1,w2
6.再次计算全局误差,若满足设定的误差阈值,返回当前权值;否则重算
"""
print(__doc__)
import random
from sympy import *
import numpy as np
import pandas as pd
data=pd.read_csv("wenzi.csv",header='infer')
data=np.mat(data)
x=data[:, :3]
y=data[:, 3]#激活函数
def sigmoid(x):return ( 1/(1+np.exp(-x)) )
#激活函数的导函数
def diffsigmoid(x):return (1- 1/(1+np.exp(-x)) )*( 1/(1+np.exp(-x)) )def upgrade_w1_w2(): #i是随机选取的一个样本erro=0.01 #误差n_iter=500 #迭代次数learnrate=0.1 #学习率global w1,w2,b1,b2
w1= 0.5 * np.random.rand(2,3) - 0.1
b1= 0.5 * np.random.rand(2,1) - 0.1
w2= 0.5 * np.random.rand(1,2) - 0.1
b2= 0.5 * np.random.rand(1,1) - 0.1"""
随机抽取一个样本计算两个偏导de/dwih 、de/dwoh
"""
i=random.randint(0,len(x)-1)
obs =np.array(x[i] )hidden_input_1=np.dot(w1[0],obs.T) - b1[0]
hidden_input_2=w1[1].dot(obs.T)-b1[1]hidden_output_1=sigmoid(hidden_input_1)
hidden_output_2=sigmoid(hidden_input_2)hidden_output_array=[float(hidden_output_1),float(hidden_output_2)]outlayer_input=np.dot(w2[0] ,(hidden_output_array)) - b2[0] #输出层只有一个节点
outlayer_output=sigmoid(outlayer_input)expect_output=y[i]
loss=expect_output - outlayer_output
sigma_t_k_1=-(expect_output-sigmoid(outlayer_input)) * diffsigmoid(outlayer_input)A=sigma_t_k_1 * hidden_output_array #de/dwho
print("sigma_t_k_1\n",sigma_t_k_1)
print('隐层的输出向量',hidden_output_array )
a=np.array(sum(-(sigma_t_k_1)))print("sum(-(sigma_t_k_1)* w1) * obs",a*w1[0] * obs )B1=diffsigmoid(hidden_input_1) * a* w1[0] * obsB2=diffsigmoid(hidden_input_2) * a* w1[1] * obs"""
计算全局误差
"""while True:for j in range(len(x)):obs =x[j]hidden_input_1=np.mat(w1[0]).dot(obs.T) - b1[0] #隐层第一个节点上的输入hidden_input_2=np.mat(w1[1]).dot(obs.T) - b1[1] #隐层第二个节点上的输入hidden_output_1=sigmoid(hidden_input_1) #隐层第一个节点上的输出hidden_output_2=sigmoid(hidden_input_2) #隐层第二个节点上的输出hidden_output_array=[float(hidden_output_1),float(hidden_output_2)]outlayer_input_1=w2[0].dot(hidden_output_array)-b2[0] #输出层的输入outlayer_output_1=sigmoid(outlayer_input_1) #输入层的输出expect_output=y[i] #期望输出就是每个观测的target数值totalloss= [] #建立空列表用以求和loss=expect_output - outlayer_output_1 #loss是每个观测的期望输出与实际输出的差totalloss.append(loss) #totalloss=np.array(totalloss) #把列表转化为数组才能进行点乘"""如果全局误差大于阈值就要更新权重"""if 0.5*totalloss.dot(totalloss) > erro:print("误差大于给定的阈值")new_w2_0=w2[0]-learnrate* (sigma_t_k_1 * hidden_output_array)new_w2=new_w2_0w2=new_w2new_w1_0=np.array(w1[0]-learnrate*B1)new_w1_1=np.array(w1[1]-learnrate*B2)w1=np.vstack((new_w1_0,new_w1_1))print("误差大于阈值时的全局损失; ",0.5*totalloss.dot(totalloss))print("误差大于阈值时的实际输出",sigmoid(outlayer_output_1))print("误差大于阈值时的w1权值矩阵:\n",w1)print("误差大于阈值时的w2权值矩阵:\n",w2)"""如果全局误差小于阈值就返回目前权"""if 0.5*totalloss.dot(totalloss)<= erro:print("\n误差满足要求!")w1=np.mat(w1)print("到更新的w1矩阵",w1 )print("得到更新的w2矩阵",w2)print("全局损失; ",0.5*totalloss.dot(totalloss))breakupgrade_w1_w2() #调用函数def classfier(test):obs =test[0:,:3]hi_1=np.mat(w1[0]).dot(obs.T) - b1[0]hi_2=np.mat(w1[1]).dot(obs.T) - b1[1]ho_1=sigmoid(hi_1)ho_2=sigmoid(hi_2)hidden_output_array=[float(hi_1),float(hi_2)]outlayer_input_1=w2[0].dot(hidden_output_array)-b2[0]outlayer_output_1=sigmoid(outlayer_input_1)print("经过最终神经网络训练后,输出层的实际输出:", outlayer_output_1)if outlayer_output_1>0.45:print("该测试样本和0.9代表的类别更接近")if outlayer_output_1<0.45:print("该测试样本和0.1代表的类别更接近")if outlayer_output_1==0.45:print("该测试样本可被任意归为两个类别之一")classfier(np.mat([[1.82,1.54,0]]))#这里的测试样本[[2.08,1.56,0]]是我从原先14个样本中挑选的,训练集有13个,留了1个作为测试,该样本的target的确是0.1#说明我们训练出的BP神经网络模型有可信度,训练集如下图所示,最后一列是target目标值
任何程序错误,以及技术疑问或需要解答的,请添加