记一次简单的深度学习——一个简易神经网络

记一次简单的深度学习——一个简易神经网络

代码

import torch
"""
一次完整的训练:
输入:100个具有1000个特征的数据
经过隐藏层:100个具有100个特征的数据
经过输出层:100个具有10个分类结果值的数据
在得到数据结果后还可以计算损失并进行后向传播(预测结果+实际值->损失->后向传播优化参数)
一次完整的训练OVER

循环这个流程可以完成指定次数的训练,并优化模型参数
"""
batch_n = 100  # 一个批次输入100个数据
hidden_layer = 100  # 经过隐藏层后保留的数据特征个数
input_data = 1000  # 输入时每个数据的特征个数
output_data = 10  # 输出时每个数据的特征个数

# 用randn随机生成输入数据x与真实值y
x = torch.randn(batch_n, input_data)  # 输入:100个具有1000个特征的数据
y = torch.randn(batch_n, output_data)  # 输出:100个具有10个分类结果值的数据
# 用randn随机初始化权重参数(这里暂时不讨论权重初始化的专门方法,初始生成用随机)
w1 = torch.randn(input_data, hidden_layer)  # 经过隐藏层:100个具有100个特征的数据
w2 = torch.randn(hidden_layer, output_data)  # 经过输出层:100个具有10个分类结果值的数据

epoch_n = 20  # 训练的轮次数
learning_rate = 1e-6  # 学习率(用于控制梯度更新的快慢)

for epoch in range(epoch_n):
    # 隐藏层
    h = x.mm(w1)  # (100,1000)*(1000*100)->(100,100) 100个具有100个特征的数据
    h = h.clamp(min=0)  # clamp剪裁,小于0的值赋为0(相当于加上ReLU激活函数)
    # 输出层
    y_pred = h.mm(w2)  # (100,100)*(100,10)=(100,10) 100个具有10个特征的数据
    # 计算损失
    loss = (y_pred - y).pow(2).sum()  # 平方损失
    print("Epoch:{}, Loss:{:.4f}".format(epoch, loss))
    # 后向传播,优化参数
    grad_y_pred = 2 * (y_pred - y)
    grad_w2 = h.t().mm(grad_y_pred)

    grad_h = grad_y_pred.clone()
    grad_h = grad_h.mm(w2.t())
    grad_h.clamp(min=0)
    grad_w1 = x.t().mm(grad_h)

    w1 -= learning_rate*grad_w1
    w2 -= learning_rate*grad_w2

后向传播

由于数学公式在代码中不好表示,下面对“后向传播,优化参数”这个过程进行详细补充说明:

要计算梯度,就要后向传播梯度,要后向传播,就要先知道前向是怎么传播的,我们已经有的公式是:
h = c l a m p ( x w 1 ) y p r e d = h w 2 l o s s = ( y p r e d − y ) 2 ( 这里忽略 s u m ( ) 是因为 s u m ( ) 是为了把损失张量转标量,并没有其他运算意义 ) h={\rm clamp}(xw_1)\\ y_{\rm pred}=hw_2\\ loss={(y_{\rm pred}-y)}^2 \\{\rm (这里忽略sum() 是因为sum()是为了把损失张量转标量,并没有其他运算意义)} h=clamp(xw1)ypred=hw2loss=(ypredy)2(这里忽略sum()是因为sum()是为了把损失张量转标量,并没有其他运算意义)
据此,我们可以得到前向传播图(前向传播就是从输入到输出,把变量以及变换用拓扑图表示出来,这里我们为了计算,把 l o s s loss loss也加上):
在这里插入图片描述
我们要算 w 1 w_1 w1的梯度就要先算 h h h的梯度,要算 h h h的梯度就要先算 y p r e d y_{\rm pred} ypred的梯度(这也体现了梯度传播链,并且“后向”),则有以下梯度计算过程(与上述代码相对应):
g r a d ( y p r e d ) = ∂ l o s s ∂ y p r e d = ∂ ( ( y p r e d − y ) 2 ) ∂ y p r e d = 2 ( y p r e d − y ) grad(y_{\rm pred}) =\frac{\partial loss}{\partial y_{\rm pred}} =\frac{\partial ((y_{\rm pred}-y)^2)}{\partial y_{\rm pred}} =2(y_{\rm pred}-y) grad(ypred)=ypredloss=ypred((ypredy)2)=2(ypredy)

g r a d ( h ) = ∂ l o s s ∂ h = ∂ l o s s ∂ y p r e d ∂ y p r e d ∂ h = g r a d ( y p r e d ) ∂ y p r e d ∂ h = 2 ( y p r e d − y ) ∂ h w 2 ∂ h = 2 ( y p r e d − y ) w 2 grad(h) =\frac{\partial loss}{\partial h} =\frac{\partial loss}{\partial y_{\rm pred}}\frac{\partial y_{\rm pred}}{\partial h} =grad(y_{\rm pred})\frac{\partial y_{\rm pred}}{\partial h} =2(y_{\rm pred}-y)\frac{\partial hw_2}{\partial h} =2(y_{\rm pred}-y)w_2 grad(h)=hloss=ypredlosshypred=grad(ypred)hypred=2(ypredy)hhw2=2(ypredy)w2

同理得: g r a d ( w 2 ) = 2 ( y p r e d − y ) h grad(w_2)=2(y_{\rm pred}-y)h grad(w2)=2(ypredy)h
g r a d ( w 1 ) = ∂ l o s s ∂ w 1 = ∂ l o s s ∂ h ∂ h ∂ w 1 = g r a d ( h ) ∂ h ∂ w 1 = 2 ( y p r e d − y ) w 2 ∂ c l a m p ( x w 1 ) ∂ w 1 grad(w_1) =\frac{\partial loss}{\partial w_1} =\frac{\partial loss}{\partial h}\frac{\partial h}{\partial w_1} =grad(h)\frac{\partial h}{\partial w_1} =2(y_{\rm pred}-y)w_2\frac{\partial {\rm clamp}(xw_1)}{\partial w_1} grad(w1)=w1loss=hlossw1h=grad(h)w1h=2(ypredy)w2w1clamp(xw1)
求到这里就出现问题了 ∂ c l a m p \partial {\rm clamp} clamp要怎么处理?

c l a m p \rm clamp clamp相当于ReLU激活函数,长下面这个样子:
在这里插入图片描述
R e L U ( x ) = { x x > 0 0 x ≤ 0 {\rm ReLU}(x)=\begin{cases}x&x\gt0\\0&x\le0\end{cases} ReLU(x)={x0x>0x0
发现它的导数很有特征,大于0导数就是1,小于0导数就是0,那么:
g r a d ( w 1 ) = g r a d ( h ) ∂ h ∂ w 1 = g r a d ( h ) ∂ c l a m p ( x w 1 ) ∂ w 1 = g r a d ( h ) ∂ c l a m p ( x w 1 ) ∂ x w 1 ∂ x w 1 ∂ w 1 = g r a d ( h ) x ∂ c l a m p ( x w 1 ) ∂ x w 1 = { g r a d ( h ) x x w 1 = h > 0 0 x w 1 = h ≤ 0 grad(w_1) =grad(h)\frac{\partial h}{\partial w_1} =grad(h)\frac{\partial {\rm clamp}(xw_1)}{\partial w_1} =grad(h)\frac{\partial {\rm clamp}(xw_1)}{\partial xw_1}\frac{\partial xw_1}{\partial w_1} =grad(h)x\frac{\partial {\rm clamp}(xw_1)}{\partial xw_1}\\ =\begin{cases}grad(h)x&xw_1=h\gt 0\\0&xw_1=h\le 0\end{cases} grad(w1)=grad(h)w1h=grad(h)w1clamp(xw1)=grad(h)xw1clamp(xw1)w1xw1=grad(h)xxw1clamp(xw1)={grad(h)x0xw1=h>0xw1=h0
(注意 x x x是常量,更不用说就算 x x x是变量求偏导也要看成常量)

那么这个结果其实跟 g r a d ( h ) grad(h) grad(h)先进行clamp()处理再乘以 x x x是一样的,即:
g r a d ( w 1 ) = { g r a d ( h ) x h > 0 0 h ≤ 0 = ( { g r a d ( h ) h > 0 0 h ≤ 0 ) × x = c l a m p ( g r a d ( h ) ) × x grad(w_1) =\begin{cases}grad(h)x&h\gt 0\\0&h\le 0\end{cases} =(\begin{cases}grad(h)&h\gt 0\\0&h\le 0\end{cases})\times x={\rm clamp}(grad(h))\times x grad(w1)={grad(h)x0h>0h0=({grad(h)0h>0h0)×x=clamp(grad(h))×x

也即代码中的这两行grad_h.clamp(min=0)grad_w1 = x.t().mm(grad_h)

至于 x x x它是常量,而且我们用不到它的梯度,所以就不求。那么至此,所有的梯度都求解完毕。

参数优化

讲完了“后向传播”,该讲“参数优化”了:

对于参数优化是有固定公式的: θ j = θ j − η × ∂ L o s s ( θ j ) θ j \theta_j=\theta_j-\eta\times\frac{\partial Loss(\theta_j)}{\theta_j} θj=θjη×θjLoss(θj) θ j − = η × g r a d ( θ j ) \theta_j-=\eta\times grad(\theta_j) θj=η×grad(θj)。对应代码中的这两行w1 -= learning_rate*grad_w1w2 -= learning_rate*grad_w2

好了,至此,“一个简易神经网络”就讲解完毕了。

其他

什么?你问博主为什么要写这么多,这不是很简单吗,为什么连乘法交换律这样的小学知识也要写出来?因为博主是个大笨比😢,第一次接触深度学习,每一行代码都像是大怪兽一样让我感到深深的无助,在与怪兽经历长时间搏斗后终于胜利了,这兴奋不亚于我第一次学会hello world,贴出来给自己加油,鼓励自己即使是个大笨比也要坚持学下去。(不要在评论区喷我,博主很脆弱)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
java大数据人工智能培训学校全套教材系列课程由1000集视频构成,基本就 是1)时下流行的java培训学校主流内部教材,2)和市面上培训学校的通 行的课程体系几乎一样。所以这套课程都能自己学下来,等于上了培训学校一次,完全可以找个java工程师的工作了。 通过学习卷积神经网络概述,为什么引入神经网络来做识别,判断,预测,训练模型,激活函数,sigmoid激活函数,导数和切线,sigmoid激活函数如何求导,链式法则,梯度,梯度下降法与delta法则,BP(back propagation)误差逆传播神经网络,卷积到底有什么作用?如何做到特征提取,池化的名字由来,dropout,Anaconda Prompt的用法,Jupyter notebook的用法,Spyder的用法,建立安装Tensorflow所需的Anaconda虚拟环境,如何在Anaconda虚拟环境安装Tensorflow与Keras概念等让大家对人工智能,卷积神经网络快速入门。课程特色:专业细致,偏案例,理论强。课程软件使用:Anaconda,Spyder,Jupyter notebook重要声明:1) 如果感觉噪音大,可以选择不用耳机,加音箱或用电脑原声 2) 既然我们的名字叫人工智能深度学习卷积神经网络入门,这个课程的特点就在于成本最低的, 让你最快速的,最容易的入门。人工智能深度学习卷积神经网络入门的最大的难点在于入门入不了,从而最终放弃。俗话说师傅领进门,修行在个人。只要入了门了,后面的事都好办。选课前,务必注意本章的学习目标和内容。想学更多,注意后边的课程。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值