三军未动,粮草先行(使用的软件和工具)

我们在jupyter notebook上来运行我们的代码
使用的是pytorch
为什么使用jupter notebook呢?
Don‘t repeat yourself
1.它可以保留运行的结果,不用重复运行
2.可以在code和markdown之间切换,方便记录学习,markdown的注释更加好看,更能更多
为什么使用pytorch呢?
在这里插入图片描述
用的真爽,让我神采奕奕,容光焕发,双目炯炯有神!


热身:用numpy实现两层神经网络

一个全连接ReLU神经网络,一个隐藏层,没有bias。用来从x预测y,使用L2 Loss

  • h = w 1 x + b 1 h=w_1x+b_1 h=w1x+b1
  • a = m a x ( 0 , h ) a=max(0,h) a=max(0,h)
  • y h a t = w 2 a y_{hat}=w_2a yhat=w2a
    这一实现完全使用numpy来计算前向神经网络,loss,和反向传播。
  • forward pass
  • loss
  • backward pass
    numpy ndarray是一个普通的n维array。它不知道任何关于深度学习或者梯度(gradient)的知识,也不知道计算图(computation graph),知识一种用来计算数学运算的数据结构
import numpy as np
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 it in range(500):
    # Forward pass
    h=x.dot(w1) # N*H
    h_relu=np.maximum(h,0) # N*H
    y_pred=h_relu.dot(w2) # N*D_out
    # compute loss
    loss =np.square(y_pred-y).sum() #和均方差的区别只是一个乘积
    print(it,loss) # 其实是存在一个mean函数的,这里先不管
    # Backward pass
    # compute the gradient
    grad_y_pred=2.0*(y_pred-y) #loss 求导
    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)
    # update weight of w1 and w2
    w1 -=learning_rate*grad_w1
    w2 -=learning_rate*grad_w2

有关反向传播的矩阵乘法推导

在这里插入图片描述


PyTorch:Tensors来创建网络,计算损失以及反向传播

一个PyTorch Tensor很想一个numpy的ndarray。但是它和numpy ndarray最大的区别是,PyTorch Tensor可以在CPU或者GPU上运算,如果想要在GPU上运算,就需要把Tensor换成cuda类型

import torch
N,D_in,H,D_out=64,1000,100,10
# 随机创建一些训练数据
x=torch.randn(N,D_in)
y=torch.randn(N,D_out)
w1=torch.randn(D_in,H,requires_grad=True)  #反向传播需要声明 默认false
w2=torch.randn(H,D_out,requires_grad=True)  #反向传播需要声明
learning_rate=1e-6 # 过拟合,欠拟合
for it in range(500):
    # Forward pass
    y_pred=x.mm(w1).clamp(min=0).mm(w2)
    # compute loss
    loss =(y_pred-y).pow(2).sum() #和均方差的区别只是一个乘积  computation graph
    print(it,loss.item()) # 其实是存在一个mean函数的,这里先不管
    # Backward pass
    # compute the gradient
    loss.backward()
    # update weight of w1 and w2
    with torch.no_grad():
        w1 -=learning_rate*w1.grad
        w2 -=learning_rate*w2.grad
        w1.grad.zero_()
        w2.grad.zero_()

我们可以看出来自动反向传播很方便


Pytorch:nn库来构建网络

import torch.nn as nn
N,D_in,H,D_out=64,1000,100,10
# 随机创建一些训练数据
x=torch.randn(N,D_in)
y=torch.randn(N,D_out)
model =torch.nn.Sequential(
    torch.nn.Linear(D_in,H),#bias 正则项
    torch.nn.ReLU(),
    torch.nn.Linear(H,D_out)
)
# torch.nn.init.normal_(model[0].weight)  # 正态分布输入
# torch.nn.init.normal_(model[2].weight)
# model=model.cude()
loss_fn=nn.MSELoss(reduction='sum')
learning_rate=1e-6 # 过拟合,欠拟合
for it in range(500):
    # Forward pass
    y_pred=model(x)   # computation graph
    # compute loss
    loss =loss_fn(y_pred,y)
    print(it,loss.item()) 
    # Backward pass
    model.zero_grad()
    loss.backward()
    # update weight of w1 and w2
    with torch.no_grad():
        for param in model.parameters():
            param -= learning_rate *param.grad

我们可以看出来nn库将模型看成一个类,在计算损失函数时更简单


PyTorch:optim 让参数更新也自动化

optim提供了SGD+momentum,RMSProp,Adam等模型优化方法

import torch.nn as nn
N,D_in,H,D_out=64,1000,100,10
# 随机创建一些训练数据
x=torch.randn(N,D_in)
y=torch.randn(N,D_out)
model =torch.nn.Sequential(
    torch.nn.Linear(D_in,H),#bias 正则项
    torch.nn.ReLU(),
    torch.nn.Linear(H,D_out)
)
# model=model.cude()
loss_fn=nn.MSELoss(reduction='sum')
learning_rate=1e-4 # 过拟合,欠拟合 -3 --- -4  比较好
optimizer=torch.optim.Adam(model.parameters(),lr=learning_rate)
# learning_rate=1e-6 # 过拟合,欠拟合 
# optimizer=torch.optim.SGD(model.parameters(),lr=learning_rate)
for it in range(500):
    # Forward pass
    y_pred=model(x)   # computation graph
    # compute loss
    loss =loss_fn(y_pred,y)
    print(it,loss.item()) # 其实是存在一个mean函数的,这里先不管
    # Backward pass
    optimizer.zero_grad() # 自动清空
    loss.backward()
    # update model parameters
    optimizer.step()    # 自动更新参数

PyTorch:自定义nn Modules

我们可以定义一个模型,这个模型继承自nn.Module类。如果需要定义一个比Sequential模型更加复炸的模型,就需要定义nn.Module模型。

import torch.nn as nn
N,D_in,H,D_out=64,1000,100,10
# 随机创建一些训练数据
x=torch.randn(N,D_in)
y=torch.randn(N,D_out)
class TwoLayerNet(torch.nn.Module):    # 定义两个函数=定义了模型
    def __init__(self,D_in,H,D_out):
        # define the model architecture
        super(TwoLayerNet,self).__init__()   # 继承+初始化
        self.linear1=torch.nn.Linear(D_in,H,bias=False)
        self.linear2=torch.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=TwoLayerNet(D_in,H,D_out);
# model=model.cude()
loss_fn=nn.MSELoss(reduction='sum')
learning_rate=1e-4 # 过拟合,欠拟合 -3 --- -4  比较好
optimizer=torch.optim.Adam(model.parameters(),lr=learning_rate)
# learning_rate=1e-6 # 过拟合,欠拟合 
# optimizer=torch.optim.SGD(model.parameters(),lr=learning_rate)
for it in range(500):
    # Forward pass
    y_pred=model(x)   # computation graph  =.forward(x)
    # compute loss
    loss =loss_fn(y_pred,y)
    print(it,loss.item()) # 其实是存在一个mean函数的,这里先不管
    # Backward pass
    optimizer.zero_grad() # 自动清空
    loss.backward()
    # update model parameters
    optimizer.step()    # 自动更新参数

自定义在后面处理复杂模型的时候有妙用


finally

目前见过最好的pytorch学习视频

有不懂的留下评论或者看视频,或者百度,谢谢大家!

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐