反向传播:代码演示篇

概述

本节继上一节反向传播:公式推导篇的代码演示,本节将从零开始演示反向传播训练参数的整个过程,除此之外还将使用TF2.0来进行快速求导作为拓展演示。

正文

首先想一下训练模型的步骤:
1、创建一个模型
2、准备好模型的输入,以及标签
3、损失函数根据模型的输出以及标签求出损失值
4、求损失函数对各个参数的偏导
5、根据求出的偏导数值更新参数

1、从零开始

由于是从零开始,所以这里我们使用一个非常简单的模型g(a,x,y)以方便求偏导,如下:
a表示模型的输入,x、y表示变量,也就是我们训练的值。

def g(a,x,y):
    h1=a*(x**2+x)
    h2=h1*y+2*y
    return h2,h1

有了g(a,x,y)这个前向传播函数,我们就可以求出反向传播的偏导数,这里损失函数我们使用均方误差0.5*(g_predict - g_target)**2,加0.5是为了求导后更简单。
有高数基础的,我们可以轻易得出以下偏导数

#损失函数L对模型输出g的偏导
def _dL_dg(g_predict,g_target):
    return g_predict-g_target
#g对参数y的偏导    
def _dg_dy(h1,y):
    return h1+2
#g对h1的偏导
def _dg_dh1(y):
    return y
#h1对参数x的偏导
def _dh1_dx(a,x):
    return a*(2*x + 1)

开始训练:

import numpy as np
import random

#初始化参数x、y
x=np.array(0.).astype("float32")
y=np.array(0.).astype("float32")
#这里手动设置你想要训练的最终的x、y的值。
#一方面可以得出标签,一方面能直观验证自己的模型的有没有训练成功
x_target=np.array(1)
y_target=np.array(5)
#定义学习率
lr=0.01
#开始训练
for i in range(1000):
	#随机取输入
    a = np.array(np.random.random()).astype("float32")
    #根据自己设定的值,得出标签
    g_target, _ = g(a,x_target,y_target)
    #得出模型预测的值
    g_predict, h1 = g(a,x,y)
	#求出损失值
    L=0.5*(g_predict-g_target)**2
    
	#开始反向传播
    dL_dg = _dL_dg(g_predict,g_target)
    dg_dh1= _dg_dh1(y)
    dh1_dx= _dh1_dx(a,x)
    
    #根据链式法则,求出dg_dy,dg_dx
    dg_dy = dL_dg * _dg_dy(h1, y)
    dg_dx = dL_dg * dg_dh1 * dh1_dx
    
    #根据学习率,以及梯度(偏导)dg_dy,dg_dx更新参数值
    x=x - lr*dg_dx
    y=y - lr*dg_dy

    if i%100==0:
        print('Loss:',L)
        
print('x:',x)
print('y:',y)

运行输出:

Loss: 121.5706952295294
Loss: 0.532752900621499
Loss: 0.01831088644040585
Loss: 0.004482554627769781
Loss: 0.0021340579303471266
Loss: 0.0011336842526728065
Loss: 6.456618332174425e-05
Loss: 1.3528191843236397e-07
Loss: 1.1819489879170875e-07
Loss: 2.6564044454382296e-07
x: 1.0000843120267124
y: 4.99975193425045

分析:我们可以看到训练1000次后,x=1.0000843120267124
y=4.99975193425045;与x_target=1,y_target=5非常接近。

2、借助深度学习框架

待更新。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章