动手学深度学习(pytorch|动手学深度学习(四)——用numpy和torch实现单层神经网络对比)


文章目录

    • 用numpy和torch实现单层神经网络对比
      • 1. 使用numpy实现
      • 2. 使用torch实现
      • 3. 使用optim自动更新的代码

用numpy和torch实现单层神经网络对比 单层神经网络的基本原理请参考机器学习——神经网络(四):BP神经网络
主要的过程为:
  • forward pass (正向传递)
  • loss (计算损失)
  • backward pass (反向更新)
1. 使用numpy实现
import numpy as np import matplotlib.pyplot as plt N,D_in,H,D_out = 64,1000,100,10# N是输入数据个数,每个输入数据是1000维,中间层是100维,10维输出# 随机创建训练数据 x_data = https://www.it610.com/article/np.random.randn(N,D_in) y_data = np.random.randn(N,D_out)# 初始化权重 w1 = np.random.randn(D_in,H) w2 = np.random.randn(H,D_out)# 定义学习参数 learning_rate = 1e-6 iteration = 1000 for it in range(iteration): h = x_data.dot(w1) # .dot矩阵乘法 h_relu = np.maximum(h,0) y_pred = h_relu.dot(w2)# compute loss loss = np.square(y_pred - y_data).sum() if it%10==0: print(it,loss)# backward pass # 1.compute the gradient grad_y_pred = 2.0*(y_pred - y_data) grad_w2 = h_relu.T.dot(grad_y_pred) grad_h_relu = grad_y_pred.dot(w2.T) grad_h = grad_h_relu.copy() #复制grad_h_relu grad_h[h<0] = 0 grad_w1 = x_data.T.dot(grad_h)# 2.update weight of w1 and w2 w1 -= learning_rate * grad_w1 w2 -= learning_rate * grad_w2 # 绘图 plt.figure(1) plt.scatter(it,loss) plt.show()

结果视图:

动手学深度学习(pytorch|动手学深度学习(四)——用numpy和torch实现单层神经网络对比)
文章图片

函数解释:
  1. numpy.random.randn(d0,d1,…,dn)
    • randn函数返回一个或一组样本,具有标准正态分布。
    • dn表格每个维度
    • 返回值为指定维度的array
  2. 【动手学深度学习(pytorch|动手学深度学习(四)——用numpy和torch实现单层神经网络对比)】np.maximum(X, Y, out=None)
    • X和Y逐位进行比较,选择最大值. 最少接受两个参数
  3. .dot()
    矩阵相乘
    如果处理的是一维数组,则得到的是两数组的內积
    如果是二维数组(矩阵)之间的运算,则得到的是矩阵积(mastrix product)
  4. .T
    矩阵的转置
2. 使用torch实现
代码:
# 在pytorch中的求导很简单N,D_in,H,D_out = 64,1000,100,10# N是输入数据个数,每个输入数据是1000维,中间层是100维,10维输出# 随机创建训练数据 x_data = https://www.it610.com/article/torch.randn(N,D_in) y_data = torch.randn(N,D_out)# 初始化权重 model = torch.nn.Sequential( torch.nn.Linear(D_in,H), # w_1*x+b1 torch.nn.ReLU(), torch.nn.Linear(H,D_out), ) # 直接初始化的模型下降非常缓慢,修改其初始化参数优化非常明显,改变lr也比较明显 torch.nn.init.normal_(model[0].weight) torch.nn.init.normal_(model[2].weight)# loss functoin loss_fn = torch.nn.MSELoss(reduction ='sum')# learning rate and iteration learning_rate = 1e-6 iteration = 1000# caculate the result for it in range(iteration): # model forward y_pred =model(x_data)# compute loss loss =loss_fn(y_pred,y_data) # computation graph if it%10==0: print(it,loss.item())# backward pass # 1.compute the gradient(使用backward的grad会不断地叠加) loss.backward() # 2.update weight of w1 and w2 with torch.no_grad(): for param in model.parameters(): param -= learning_rate*param.grad model.zero_grad() # 注意要清空grad参数结果,否则会在上一次计算的结果上进行叠加

不同之处:
  1. 所有的numpy.random.randn函数变为torch.randn
  2. torch中使用区间限定函数.clamp(min=num1,max=num2)来替代了numpy中常用numpy.maximum
  3. torch中的矩阵乘法使用.mm()替代numpy中的.dot()
  4. torch中的装置使用.t()替代numpy中的.T
  5. 在pytorch中有已经定义好的神经网络训练函数
  6. torch库中可以调用loss.backward()直接得到与函数相关的参数的梯度,进而进行梯度下降计算;其中的注意点我将在下一个博客单独说明。
  7. 当下降不是很明显的时候可以从:①learning rate的大小 ②初始化参数 两个方面进行考虑,learning rate越大下降得越快,但有欠拟合的缺点,初始化参数就比较玄学了。
改变初始化参数的代码为:
torch.nn.init.normal_(model[0].weight) torch.nn.init.normal_(model[2].weight)

  1. torch中可以使用optim来自动更新参数而非自己手动更新。optim包有很多的优化方法比如SCD+momentum,RMSProp,Adam等都可以直接调用。(在后面将继续介绍)
3. 使用optim自动更新的代码
步骤就是不用自动更新了,定义一个optimizer,将model的参数和learning rate传递进torch.optim.Adam中去;在迭代的过程中使用optimizer.zero_grad()方法和optimizer.step()方法进行更新即可(注意这里删掉了上方更改初始化的代码)
# 在pytorch中的求导很简单N,D_in,H,D_out = 64,1000,100,10# N是输入数据个数,每个输入数据是1000维,中间层是100维,10维输出# 随机创建训练数据 x_data = https://www.it610.com/article/torch.randn(N,D_in) y_data = torch.randn(N,D_out)# 初始化权重 model = torch.nn.Sequential( torch.nn.Linear(D_in,H), # w_1*x+b1 torch.nn.ReLU(), torch.nn.Linear(H,D_out), )# modle = model.cuda() 通常我们是需要在GPU上运行的,当然也要传递各种参数loss_fn = torch.nn.MSELoss(reduction ='sum')# 定义学习参数 learning_rate = 1e-4# 定义优化方法optimizer optimizer = torch.optim.Adam(model.parameters(),lr=learning_rate) iteration = 1000for it in range(iteration): # model forward y_pred =model(x_data)# compute loss loss =loss_fn(y_pred,y_data) # computation graph if it%10==0: print(it,loss.item())optimizer.zero_grad() # backward pass loss.backward()# update model parameters optimizer.step()

pytorch新人上路,各位大佬多多指点

    推荐阅读