Task2-设立计算图并自动计算

Task2-设立计算图并自动计算

1. numpy和pytorch实现梯度下降法

######numpy实现:

import numpy as np

# N is batch size; 
N, D_in, H, D_out = 64, 1000, 100, 10

# 输入输出数据的随机初始化
x = np.random.randn(N, D_in)
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 t in range(500):
    # 前向传播
    h = x.dot(w1)
    h_relu = np.maximum(h, 0)
    y_pred = h_relu.dot(w2)
    
    # 计算并打印损失
    loss = np.square(y_pred-y).sum()
    print(t, loss)
    
    #根据损失,计算梯度
    grad_y_pred = 2.0 * (y_pred-y)
    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[h<0] = 0
    grad_w1 = x.T.dot(grad_h)
    
    #更新权重
    w1 -= learning_rate * grad_w1
    w2 -= learning_rate * grad_w2

######PyTorch实现:

import torch

dtype = torch.float
device = torch.device("cpu")
# device = touch.device("cuda:0")  #当运行在GPU时,要加上这行代码

# N是batch size;D_in是输入的维度
# H是隐藏层的维度;D_out是输出的维度
N, D_in, H, D_out = 64, 1000, 100, 10

# 构造随机生成的输入和输出数据
# 设置requires_grad=False,表明在后向传播时,我们不需要计算关于这些张量的梯度
x = torch.randn(N, D_in, device=device, dtype=dtype)
y = torch.randn(H, D_out, device=device, dtype=dtype)

# 网络权重随机初始化
# 设置requires_grad=True,表明在后向传播时,我们需要计算关于这些张量的梯度
w1 = torch.randn(D_in, H, device=device, dtype=dtype, requires_grad=True)
w2 = torch.randn(H, D_out, device=device, dtype=dtype, requires_grad=True)

# 学习率
learing_rate = 1e-6
for t in range(500):
    # 前向传播:这些与我们使用tensors计算正向传播的操作完全相同,但是我们不需要
    # 保留对中间值的引用,因为我们没有手动实现反向传播。
    y_pred = x.mm(w1).clamp(min=0).mm(w2)
    
    # 使用tensor操作计算并打印损失
    # 现在loss是一个shape(1,)类型的张量
    # loss.item()可以获取loss中保存的标量值
    loss = (y_pred - y).pow(2).sum()
    print(t, loss.item())
    
    # 使用autograd来计算后向传播;这个调用将计算相对于所有requires_grad=True的
    # 张量的损失的梯度。
    # After this call w1.grad and w2.grad will be Tensors holding the gradient
    # of the loss with respect to w1 and w2 respectively.
    loss.backward()
    
    # 使用梯度下降手动更新权重。之所以封装于torch.no_grad(),是因为权重的
    # requires_grad=True,而我们在自动微分中没有必要跟踪这些;
    # 另一种可选择的操作是operate on weight.data and weight.grad.data.
    # You can also use torch.optim.SGD to achieve this.
    with torch.no_grad():
        w1 -= learning_rate * w1.grad
        w2 -= learning_rate * w2.grad
        
        # 更新权重之后,手动将梯度设置为0
        w1.grad.zero_()
        w2.grad.zero_()

2. 设定初始值

神经网络的权重初始化方法对模型的收敛速度和性能有着至关重要的影响。主要有四种权重初始化方法:

  • 把w初始化为0

    在线性回归,logistics回归中,基本上把参数初始化为0,模型也能很好的工作。但是在神经网络中,这种方法是不可行的。如果把w初始化为0,那么每一层的神经元学到的东西都是一样 的。

  • 对w随机初始化

    对w进行随机初始化时,要初始化到一个相对较小的值,因为如果X很大的话,W又相对较大,会导致Z非常大,这样如果激活函数是sigmoid,就会导致sigmoid的输出值1或者0,然后会导致一系列问题。但是随机初始化也有缺点,np.random.randn()其实是一个均值为0,方差为1的高斯分布中采样。当神经网络的层数增多时,会发现越往后面的层的激活函数(使用tanH)的输出值几乎都接近于0 。

  • Xavier initialization

    Xavier initialization是 Glorot 等人为了解决随机初始化的问题提出来的另一种初始化方法,他们的思想倒也简单,就是尽可能的让输入和输出服从相同的分布,这样就能够避免后面层的激活函数的输出值趋向于0。虽然Xavier initialization能够很好的 tanH 激活函数,但是对于目前神经网络中最常用的ReLU激活函数,还是无能为力。

  • He initialization

    为了解决上面的问题,我们的何恺明大神提出了一种针对ReLU的初始化方法,一般称作 He initialization。

    现在神经网络中,隐藏层常使用ReLU,权重初始化常用He initialization这种方法。

3. numpy和PyTorch实现线性回归

线性回归包括一元线性回归和多元线性回归,一元的是只有一个x和一个y(eg:y = m * x+b),多元是指有多个x和一个y(eg: y = m1 * x1 + m2 * x2 +b)。一元线性回归其实就是去找到一条直线,这条直线能以最小的误差(Loss)来拟合数据。

numpy实现:

PyTorch实现:

4. PyTorch实现一个简单的神经网络


参考文献:

  1. 深度学习中神经网络的几种权重初始化方法
  2. 线性回归理解(附纯python实现)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值