使用numpy实现两层神经网络

1. 网络结构及实现思路

以下为次此依赖的的网络结构,并且后边的所有思路及编程都将遵循这个结构给出。
在这里插入图片描述
其中隐藏层、激活函数(采用Relu函数)、输出层的内容如下:

  • h = x w 1 h=xw_1 h=xw1
  • a = m a x ( 0 , h ) a=max(0,h) a=max(0,h)
  • y ^ = a w 2 \hat{y}=aw_2 y^=aw2

其整体实现思路如下:

1. 定义神经网络参数
2. 实现前馈神经网络 forward pass
3. 计算损失 loss
4. 实现反向传播 backword pass

2.编程实现及公式推导

# @Time : 2020/5/7 23:25 
# @Author : kingback
# @File : model_practice.py 
# @Software: PyCharm

## 使用numpy实现两层神经网络

import torch
import numpy as np


#一个全连接的Relu神经网络,一个隐藏层,没有bias,用来从x预测y:
#这一实现的三大过程:
#1.前馈神经网络 forword pass
#2.计算损失 loss
#3.反向传播 backword pass


#神经网络参数定义:
N,D_in,D_out,H=64,1000,10,100
# N:代表64个人
# D_in:代表每个人输入到神经网络1000个数据点
# D_out:代表每个人从神经网络输出10个数据点
# H:代表该神经网络含有100个隐藏层

x=np.random.randn(N,D_in)
#定义输入到神经网络之前的数据矩阵,大小为64*1000
y=np.random.randn(N,D_out)
#定义从神经网络输出的的数据矩阵,大小为64*10
w_1=np.random.randn(D_in,H)
#大小为1000*100
w_2=np.random.randn(H,D_out)
#大小为100*10

#定义学习率 learning rate
learning_rate=1e-06
for it in range(500):
    #forword pass
    h=x.dot(w_1)
    #numpy中的点乘np.dot是数学意义上的向量内积
    #print(h.shape)
    #打印矩阵维度信息
    h_relu=np.maximum(h,0)
    #定义relu 函数,是目前深度神经网络中经常使用的激活函数。
    y_hat=h_relu.dot(w_2)
    #大小为64*10

    #计算损失compute loss
    loss=np.square(y_hat-y).sum()
    #估计值与真实值之间差值的平方和再取和
    print(it,loss)

    #计算梯度,主要是对(y_hat-y)^2求各项偏导
    y_hat_grad=2*(y_hat-y)
    w_2_grad=h_relu.T.dot(y_hat_grad)
    h_relu_grad=y_hat_grad.dot(w_2.T)
    h_grad=h_relu_grad.copy()
    h_grad[h<0]=0
    w_1_grad=x.T.dot(h_grad)

    #更新w_1和w_2的权值
    w_1=w_1-learning_rate*w_1_grad
    w_2=w_2-learning_rate*w_2_grad

这里需要说明的一点就是在计算各参数的梯度问题时,是在估计值与真实值之间差值的平方的基础上进行求偏导的,我们令其为A,则有:
A = ( y ^ − y ) 2 A=(\hat{y}-y)^2 A=(y^y)2
易得:
∂ A ∂ y ^ = 2 ⋅ ( y ^ − y ) \frac{\partial{A}}{\partial{\hat{y}}}=2\cdot(\hat{y}-y) y^A=2(y^y)
后面几个偏导的计算就很容易写错了:
∂ A ∂ w 2 = a T ⋅ ∂ A ∂ y ^ \frac{\partial{A}}{\partial{w_2}}=a^T\cdot\frac{\partial{A}}{\partial{\hat{y}}} w2A=aTy^A
∂ A ∂ a = ∂ A ∂ y ^ ⋅ w 2 T \frac{\partial{A}}{\partial{a}}=\frac{\partial{A}}{\partial{\hat{y}}}\cdot w_2^T aA=y^Aw2T
因为 a = m a x ( 0 , h ) a=max(0,h) a=max(0,h),则有:
a = m a x ( 0 , h ) = { h h ≥ 0 0 h < 0 a=max(0,h)=\left\{\begin{aligned}h \qquad h\geq0 \\ 0 \qquad h<0\\ \end{aligned}\right. a=max(0,h)={hh00h<0
所以对h求偏导则有:
∂ A ∂ h = { ∂ A ∂ a ⋅ 1 h ≥ 0 ∂ A ∂ a ⋅ 0 h < 0 \frac{\partial{A}}{\partial{h}}=\left\{\begin{aligned} {\frac{\partial{A}}{\partial{a}} } \cdot1 \qquad h\geq0 \\ {\frac{\partial{A}}{\partial{a}} }\cdot0 \qquad h<0\\ \end{aligned}\right. hA=aA1h0aA0h<0
最后我们再对w_1求偏导:
∂ A ∂ w 1 = x T ⋅ ∂ A ∂ h \frac{\partial{A}}{\partial{w_1}}=x^T\cdot\frac{\partial{A}}{\partial{h}} w1A=xThA
有了上边的推导,相信大家很容易就理解代码了吧。嘿嘿嘿

3.结果测试

在这里插入图片描述
在结果中我们可以看到,在程序刚开始时和程序结束时的loss值有了明显减小:

程序开始时loss值程序结束时loss值
在这里插入图片描述在这里插入图片描述

可以看到程序在训练了500次的情况下,我们的这个两层的神经网络效果还是比较不错的。接下来我也将会继续将该模型改写为torch版本的。

4.参考文章

1.【Code】numpy、pytorch实现全连接神经网络

  • 1
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王延凯的博客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值