搭建一个简易的神经网络及理解其中的矩阵求导及反向传播推导

搭建一个基于PyTorch架构的简易神经网络模型 

代码参考《深度学习之pytorch实战计算机视觉》

#搭建一个简易神经网络
import torch
batch_n = 100
hidden_layer = 100
input_data = 1000
output_data = 10

x = torch.randn(batch_n,input_data)
y = torch.randn(batch_n,output_data)

w1 = torch.randn(input_data,hidden_layer)
w2 = torch.randn(hidden_layer,output_data)

epoch_n = 500
learning_rate = 1e-6

for epoch in range(epoch_n):
    h1 = x.mm(w1)
    h1 = h1.clamp(min = 0)
    y_pred = h1.mm(w2)  #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 = h1.t().mm(grad_y_pred)

    grand_h = grad_y_pred.clone()
    grand_h = grand_h.mm(w2.t())
    grand_h.clamp_(min=0)
    grand_w1 = x.t().mm(grand_h)

    w1 -= learning_rate * grand_w1
    w2 -= learning_rate * grad_w2

以上为完整代码,接下来依次解读:

import torch
batch_n = 100
hidden_layer = 100
input_data = 1000
output_data = 10

首先定义了4个整型变量,其中:batch_n是指在一个批次中输入数据的数量,值是100,这意味着我们在一个批次中输入100个数据,同时input_data = 1000,所以每个数据的数据特征是1000个,hidden_layer = 100用于定义经过隐藏层后保留的数据特征个数,因为我们的模型只考虑一层隐藏层,所以代码中仅定义了一个隐藏层的参数,output_data = 10 是输出的数据,可以将输出数据看做是一个分类结果值的数量,个数10表示我们最后要得到10个分类结果值。

所以一个批次的数据从完整的输入到输出的过程是:先输入100个具有1000个特征的数据,经过隐藏层后变为100具有100个特征的数据,再经过输出层后输出100个具有10个分类结果值的数据,在得到输出结果后计算损失并进行后向传播,这样一次模型的训练就完成了,然后循环这个流程指定训练次数。

x = torch.randn(batch_n,input_data)
y = torch.randn(batch_n,output_data)

w1 = torch.randn(input_data,hidden_layer)
w2 = torch.randn(hidden_layer,output_data)

 

对输入层到隐藏层,隐藏层再到输出层的权重初始化定义如上,这些参数维度与前面说到的过程是一致的。我们可以观察到输入层维度是(100,1000),输出层维度是(100,10),输入层到隐藏层的权重参数维度是(1000,100),隐藏层再到输出层的权重参数维度是(100,100)。我们将整个过程看作是矩阵连续的乘法运算就能知道权重参数的维度是如何定义的了。

明确训练的总次数和学习速率

epoch_n = 500
learning_rate = 1e-6

接下来用梯度下降的方法来优化神经网络的参数

for epoch in range(epoch_n):
    h1 = x.mm(w1)    #100*1000
    h1 = h1.clamp(min = 0)    #剪裁蕾丝于ReLU激活函数
    y_pred = h1.mm(w2)  #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 = h1.t().mm(grad_y_pred)

    grand_h = grad_y_pred.clone()
    grand_h = grand_h.mm(w2.t())
    grand_h.clamp_(min=0)
    grand_w1 = x.t().mm(grand_h)

    w1 -= learning_rate * grand_w1
    w2 -= learning_rate * grad_w2

前向传播的预测结果用y_pred来表示,用loss表示误差值,使用均方误差函数计算。代码后面的部分就是实现后向传播对权重参数进行优化,代码中为了计算方便使用的是每个节点的链式求导结果。在得到梯度值后按照定义好的学习速率对w1,w2对权重参数进行更新。

接下来对于梯度的反向传播计算进行描述:(其实每个变量的梯度下降与计算的倒数有关)

以下公式及过程摘自:https://blog.csdn.net/DawnRanger/article/details/78600506

首先给出看一下计算过程

求导过程:

实值函数对矩阵求导

线性变换的导数:

矩阵线性变换求导:

 

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