JadenFK
哪有什么岁月静好,只是有人替我们负重前行! http://JadenFK.github.io

这篇博客早就想写了,因为这节课是我在疫情的假期里看的,还不错,准备一直看完。所有最近又复习了一遍。因为之前一直在学《动手学深度学习》PyTorch版,不过,我这个人真是懒,一直么学好,也断断续续。不过,我还是会把那本书接着学一遍,先看这个视频了,因为最近有可能用到。

本系列博客是根据哔哩哔哩上pytorch入门与实战这个视频课程写的(主要是代码),因为是小白,死磕课本有点费劲,学习《动手学深度学习》PyTorch版时就发现了。

哔哩哔哩上这系列课的网址:https://www.bilibili.com/video/BV12741177Cu?from=search&seid=17209581732555565064

实现的两层神经网络的模型:    :为了简单实现,偏置项b不在网络中实现。

$ h = w_{1}*X + b_{1} $

$ a = max(0,h) $

$ y_{hat} = w_{2}*a + b_{2} $

以下代码是我为了记忆,自己直接敲的一遍,有错误请指出,谢谢了

下面使用numpy实现该神经网络:1 2 3 4 步,所有的网络基本都是这几步,其他的就是数据处理什么的

import numpy as np
N, D_in, H, D_out = 64, 1000, 100, 10



# 定义输入输出数据
x = np.random.randn(D_in, H)
y = np.random.randn(N, D_out)

# 权重随机初始化
w1 = np.random.randn(D_in, H)
w2 = np.random.randn(H, D_out)

learning_rate = 1e-6
for it in range(500): # 对网络训练500次
  # 1 Forward pass,前向网络,也就是模型
  h = x.dot(w1) # .dot()在numpy中是计算向量点积的函数
  h_relu = np.maximum(h, 0)  # .maximum()是采用的ReLU激活函数
  y_pred = h_relu.dot(w2)
  
  # 2 计算损失函数
  loss = np.square(y_pred - y).sum() # 平方损失函数,.square()就是求平方,sum()求和
  print(it, loss)
  
  # 3 backward pass, 反向网络,也就是计算梯度。若是看代码费劲,可以先对上面提的神经网络模型公式进行求导,然后对应到Forward Pass中的定义即可。我的推导见附录一
  grad_y_pred = 2.0 * (y_pred - y)
  grad_w2 = h_relu.T.dot(grad_y_pred)
  grad_h_relu = grad_y_perd.dot(w2.T)
  grad_h = grad_h_relu.copy()
  grad_h[h<0] = 0
  grad_w1 = x.T.dot(grad_h)
  
  # 4 update weights of w1 and w2, 更新权重,也就是学习一个好的权重
  w1 -= learning_rate * grad_w1
  w2 -= learning_rate * grad_w2

PyTorch实现上述两层神经网络模型:附录二有numpy和PyTorch的封装的函数的小差别对比

import torch
N, D_in, H, D_out
= 64, 1000, 100, 10 # 定义输入输出数据 x = torch.randn(D_in, H) y = torch.randn(N, D_out) # 权重随机初始化 w1 = torch.randn(D_in, H) w2 = torch.randn(H, D_out) learning_rate = 1e-6 for it in range(500): # 对网络训练500次   # 1 Forward pass,前向网络,也就是模型   h = x.mm(w1) # .mm()在torch中是计算向量点积的函数   h_relu = h.clamp(min=0)  # .clamp()是采用的ReLU激活函数,是类似于range,一个min,一个max,夹在中间,大于max,就记为max,小于min,就记为min   y_pred = h_relu.mm(w2)      # 2 计算损失函数   loss = np.square(y_pred - y).sum() # 平方损失函数,.square()就是求平方,sum()求和   print(it, loss)      # 3 backward pass, 反向网络,也就是计算梯度。若是看代码费劲,可以先对上面提的神经网络模型公式进行求导,然后对应到Forward Pass中的定义即可。我的推导见附录一   grad_y_pred = (y_pred - y).pow(2)   grad_w2 = h_relu.t().mm(grad_y_pred)   grad_h_relu = grad_y_perd.mm(w2.t())   grad_h = grad_h_relu.clone()   grad_h[h<0] = 0   grad_w1 = x.t().mm(grad_h)      # 4 update weights of w1 and w2, 更新权重,也就是学习一个好的权重   w1 -= learning_rate * grad_w1   w2 -= learning_rate * grad_w2

PyTorch简化版实现上述网络(torch.nn.Sequential()):(因为pytorch封装了好多方法和类,可以自动求梯度,不用自己实现)

import torch.nn as nn
N, D_in, H, D_out = 64, 1000, 100, 10
x = torch.randn(D_in, H) 
y = torch.randn(N, D_out)

model = nn.Sequential(
  nn.Linear(D_in, H, bias=False),
  nn.ReLU(),
  nn.Linear(H, D_out)
)

nn.init.normal_(model[0].weight) # 初始化一下权重,否则会模型效果会差。
nn.init.normal_(model[2].weight)

loss_fn = nn.MSELoss(reduction='sum')

 learning_rate = 1e-6
 for it in range(500):

    y_pred = model(x)   # 相当于model.forward(x),model会自动做前向传播

    loss = loss_fn(y_pred, y)

    print(it, loss)

    loss.backward()

    with torch.no_grad():   #加入这句,可以不记录计算图的历史,节省内存

      for param in model.parameters(): # 遍历模型参数,优化

        param -= learning_rate * param.grad

    model.zero_grad()  # 计算下次梯度前,清零梯度

PyTorch简化版实现上述网络(torch.nn.Module())


import torch.nn as nn
N, D_in, H, D_out = 64, 1000, 100, 10

x = torch.randn(D_in, H) 
y = torch.randn(N, D_out)

class TwoLayerNet(nn.Module):
  def __init__(self, D_in, H, D_out):
    super(TwoLayerNet, self).__init__() # 必须这么写
    self.linear1 = nn.Linear(D_in, H, bias=False)
    self.linear2 = nn.Linear(H, D_out, bias=False)

  def forward(self,x):
    y_pred = self.linear2(self.linear1(x).clamp(min=0))
  return y_pred

model = TwoLayreNet(D_in, H, D_out)
loss_fn = nn.MSELoss(reduction='sum')
learning_rate = 1e-4
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate) # 若使用SGD优化器,需要初始化weight,否则效果不好,玄学。。。

for it in range(500):
  y_pred = model(x)

  loss = loss_fn(y_pred,y)
  print(it, loss)
  
  # 三步操作:梯度清零,反向计算新梯度,一步优化(update parameter)
  optimizer.zero_grad()
  loss.backward()
  optimizer.step()

上述torch.nn.Sequential和torch.nn.Modele,在我学习《动手学深度学习》时也介绍过,可以去我以前的博客看看,欢迎指点和探讨,我是小白,虽然我黑。

附录一:(字体有点low了)

附录二:(字体样子自动过滤)

 

posted on 2020-06-12 21:50  郭心全  阅读(548)  评论(0编辑  收藏  举报

……