备战数学建模十三之BP神经网络

两段代码展示了BP神经网络的实现,分别处理逻辑运算和加或逻辑问题。第一段代码定义了激活函数、前向传播、反向传播和权重更新,并通过迭代优化权重。第二段代码为一个简单的两层神经网络,用于解决与或逻辑问题,通过sigmoid函数和梯度下降法更新权重,随着训练次数增加,损失函数逐渐减小。

话不多说,直接上代码,反正都不是自己的东西,稍微改了改,让代码能用了

# encoding:utf-8
# ********* 导入相应的模块***********
import math
import numpy as np
from numpy import *

#**********设定模型所需的激活函数,运行此代码时,带'*'部分请删除*********
# 激活函数
def sigmoids(z):
    #Sigmoid函数是一个在生物学中常见的S型函数,也称为S型生长曲线。1/(1+e^(-x))
    # Sigmoid函数常被用作神经网络的激活函数,将变量映射到0,1之间。
    a = []
    for each in z:
        b = 1/(1+math.exp(-each[0]))
        a.append(b)
    return a

# **********设定前向传播过程,即模型的设定部分,此处均根据模型第3部分的模型设定部分的公式编写对应的代码*********

# 前向传播,返回预测值
def forwordmd(X,W,V,B1,B2):
    net1 = W.T*X+B1
    H = matrix(sigmoids(np.array(net1))).T # 隐藏层单元
    net2 = V.T*H+B2
    pred_y = matrix(sigmoids(np.array(net2))).T # 预测值
    return pred_y,H,net1,net2

#**********设定模型反向传播,按照步骤4的公式编辑*********
# 反向传播,更新权重
def Bpaugorith(Y,pred_y,H,V,aph,W):
    Errorterm = 0.5*(Y-pred_y).T*(Y-pred_y)# 给出误差公式
    # 计算输出单元的误差项
    a1 = multiply(pred_y-Y,pred_y) # 矩阵对应元素相乘,即逐元素相乘
    a2 = multiply(a1,1-pred_y)
    Verror = H*a2.T
    # 计算隐藏单元的误差项
    Werror = X*(multiply(multiply(H,1-H),(V*a2))).T
    # 更新权重
    Vupdate = V - aph*Verror
    Wupdate = W - aph*Werror
    return Vupdate,Wupdate,Errorterm

#**********主程序部分,此处设定了步骤1中的参数初始化和输入值及输出值的真实值,及步骤5中设置迭代次数和设置阈值停止迭代的代码*********

if __name__ =='__main__':
    X = matrix([0.05,0.10]).T#训练数据
    Y = matrix([0.01,0.99]).T
    # # 给出初始权重
    # W = matrix([[0.15,0.20],[0.25,0.30]])
    # B1 = matrix([0.1,0.1]).T
    # V = matrix([[0.40,0.45],[0.50,0.55]])
    # B2 = matrix([0.2,0.2]).T

    # ***********初始权重亦可随机生成***********
    # 随机生成参数
    np.random.seed(0)
    W = matrix(np.random.normal(0,1,[2,2]))
    B1 = matrix(np.random.normal(0, 1, [1, 2]))
    V = matrix(np.random.normal(0, 1, [2, 2]))
    B2 = matrix(np.random.normal(0, 1, [1, 2]))
    # ***********随机生成参数部分,若有自己设定,将此部分注释*********
    aph = 0.1 # 学习率,梯度下降法的步长,太小容易局部最小值,太大误差大跳过最优解
    #*********从此处为迭代次数设置部分***********
    # 迭代10次
    n = 100000 # 迭代次数
    for i in range(n):
        # 激活前向算法
        pred_y, H,net1,net2 = forwordmd(X,W,V,B1,B2)  # 得到预测值和隐藏层值
        # 更新权重
        Vupdate, Wupdate,Errorvalue = Bpaugorith(Y,pred_y,H,V,aph,W)  # 得到更新的权重
        W,V = Wupdate,Vupdate

    X2=matrix([0.6,0.8]).T
    y,a,b,c=forwordmd(X2,W,V,B1,B2)
    print("预测值2",y)
    print ('损失函数e:%.2f'%e)
    print ('预测值:')
    print (pred_y)
    print ('更新的权重V:')
    print (Vupdate)
    print ('更新的权重W:')
    print (Wupdate)
    print ('损失值:')
    print (Errorvalue)

    # 阈值E,可根据需要自行更改,若需要运行此部分,请将迭代次数部分注释后运行
    # 阈值E
    # e,m = 0.19,1
    # pred_y, H, net1, net2 = forwordmd(X,W,V,B1,B2)  # 得到预测值和隐藏层值
    # 更新权重
    # Vupdate, Wupdate, Errorvalue = Bpaugorith(Y,pred_y,H,V,net1,net2,aph,W)  # 得到更新的权重
    # W,V = Wupdate,Vupdate
    # while Errorvalue>e:
        # 激活前向算法
        # pred_y, H, net1, net2 = forwordmd(X,W,V,B1,B2)  # 得到预测值和隐藏层值
        # 更新权重
        # Vupdate, Wupdate, Errorvalue = Bpaugorith(Y,pred_y,H,V,net1,net2,aph,W)  # 得到更新的权重
        # W, V = Wupdate, Vupdate
        # m = m+1
    # print ('迭代次数:%d'%n)
    # print ('更新权重:%d次'% m)
    # print ('预测值:')
    # print (pred_y)
    # print ('更新的权重V:')
    # print (Vupdate)
    # print ('更新的权重W:')
    # print (Wupdate)
    # print ('损失值:')
    # print (Errorvalue)
# ​
#
#     #*********阈值设置部分结束***********
#
# ​

运行结果

预测值2 [[0.0068899 ]
 [0.99291294]]
损失函数e:2.72
预测值:
[[0.01094523]
 [0.98905563]]
更新的权重V:
[[-2.07238957  2.15949174]
 [-3.14612034  2.73716063]]
更新的权重W:
[[1.78677904 0.4463306 ]
 [1.02419138 2.33323999]]
损失值:
[[8.92654732e-07]]

进程已结束,退出代码0

在加一个与或逻辑的BP神经网络的代码

import numpy as np
import matplotlib.pyplot as plt
# 输入数据,输入二维,中间十个神经元,输出是一维
X = np.array([[0,0],[0,1], [1,0],[1,1]])
# 标签,也就是输出值的实际值,这个例子仿佛是与或非之类的东西
T = np.array([[0],[1],[1],[0]])
# 定义一个2层的神经网络:2-10-1
# 输入层2个神经元,隐藏层10个神经元,输出层1个神经元
# 输入层到隐藏层的权值初始化,2行10列
W1 = np.random.random([2,10])
# 隐藏层到输出层的权值初始化,10行1列
W2 = np.random.random([10,1])
# 初始化偏置值,偏置值的初始化一般可以取0,或者一个比较小的常数,如0.1
# 隐藏层的10个神经元偏置
b1 = np.zeros([10])
# 输出层的1个神经元偏置
b2 = np.zeros([1])
# 学习率设置
lr = 0.1
# 定义训练周期数
epochs = 100001
# 定义测试周期数
test = 5000
# 定义sigmoid函数
def sigmoid(x):
 return 1/(1+np.exp(-x))
# 定义sigmoid函数导数
def dsigmoid(x):
 return x*(1-x)
# 更新权值和偏置值
def update():
 global X,T,W1,W2,lr,b1,b2
 # 隐藏层输出
 L1 = sigmoid(np.dot(X,W1) + b1)
 # 输出层输出
 L2 = sigmoid(np.dot(L1,W2) + b2)
 # 根据公式4.41,求输出层的学习信号
 delta_L2 = (T - L2) *dsigmoid(L2)
 # 根据公式4.42,求隐藏层的学习信号
 delta_L1 = delta_L2.dot(W2.T) *dsigmoid(L1)
 # 根据公式4.44,求隐藏层到输出层的权值改变
 # 由于一次计算了多个样本,所以需要求平均
 delta_W2 =lr*L1.T.dot(delta_L2) /X.shape[0]
# 根据公式4.45,求输入层到隐藏层的权值改变
# 由于一次计算了多个样本,所以需要求平均
 delta_W1 =lr*X.T.dot(delta_L1) / X.shape[0]
 # 更新权值
 W2 =W2 + delta_W2
 W1 =W1 + delta_W1
 # 改变偏置值
 # 由于一次计算了多个样本,所以需要求平均
 b2 =b2 +lr*np.mean(delta_L2, axis=0)
 b1 =b1 +lr*np.mean(delta_L1, axis=0)
# 定义空list用于保存loss
loss = []
# 训练模型
for i in range(epochs):
 # 更新权值
    update()
 # 每训练5000次计算一次loss值
    if i %test == 0:
 # 隐藏层输出
       L1 = sigmoid(np.dot(X,W1) + b1)
 # 输出层输出
       L2 =sigmoid(np.dot(L1,W2) + b2)
 # 计算loss值
       print('epochs:',i,'loss:',np.mean(np.square(T - L2) / 2))
 # 保存loss值
       loss.append(np.mean(np.square(T - L2) / 2))
# 画图训练周期数与loss的关系图
plt.plot(range(0,epochs,test),loss)
plt.xlabel('epochs')
plt.ylabel('loss')
plt.show()
# 隐藏层输出
L1 = sigmoid(np.dot(X,W1) + b1)
# 输出层输出
L2 = sigmoid(np.dot(L1,W2) + b2)
print('output:')
print(L2)
# 因为最终的分类只有0和1,所以我们可以把
# 大于等于0.5的值归为1类,小于0.5的值归为0类
def predict(x):
 if x>=0.5:
  return 1
 else:
  return 0
# map会根据提供的函数对指定序列做映射
# 相当于依次把L2中的值放到predict函数中计算
# 然后打印出结果
print ('predict:')
for  i in map(predict,L2):
 print(i)

输出结果为

 

epochs: 0 loss: 0.22163212148744935
epochs: 5000 loss: 0.11741534349499161
epochs: 10000 loss: 0.07103471018518064
epochs: 15000 loss: 0.01857399836442719
epochs: 20000 loss: 0.006409280131915647
epochs: 25000 loss: 0.0033496302930681445
epochs: 30000 loss: 0.002149399523007848
epochs: 35000 loss: 0.0015422805098843926
epochs: 40000 loss: 0.0011852096578871705
epochs: 45000 loss: 0.0009535961890505724
epochs: 50000 loss: 0.00079275000040673
epochs: 55000 loss: 0.0006753101872422451
epochs: 60000 loss: 0.0005862188584680112
epochs: 65000 loss: 0.0005165657747824863
epochs: 70000 loss: 0.00046076940594204114
epochs: 75000 loss: 0.00041516911394270175
epochs: 80000 loss: 0.00037727163060337517
epochs: 85000 loss: 0.00034532421602544156
epochs: 90000 loss: 0.00031806116869898503
epochs: 95000 loss: 0.0002945471401239939
epochs: 100000 loss: 0.0002740769052514572
Can't find filter element
Can't find filter element
output:
[[0.02483329]
 [0.97753863]
 [0.97770082]
 [0.02396155]]
predict:
0
1
1
0

进程已结束,退出代码0

 

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值