01-用numpy和torch分别实现两层神经网络

1.numpy实现

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

  • h=W1X+b1
  • a=max(0,h)
  • yhat=W2a+b2

这一实现完全使用numpy来计算前向神经网络,loss,和反向传播。

  • forward pass
  • loss
  • backword pass

numpy ndarry是一个普通的n维array。它不知道任何关于深度学习或者梯度(gradient)的知识,也不知道计算图,只是一种用来计算数学运算的数据结构。

import numpy as np

N,D_in,H,D_out=64,1000,100,10#多少个训练数据,输入的维度,中间隐含层的神经元个数,输出的维度

#随机创建一些训练数据
x=np.random.randn(N,D_in)#64*1000
y=np.random.randn(N,D_out)#64*10

w1=np.random.randn(D_in,H)#1000*100
w2=np.random.randn(H,D_out)#100*10

learning_rate=1e-6#学习率

for t in range(500):#500次
    #向前传递
    h=x.dot(w1)#64*100
    h_relu=np.maximum(h,0)#64*100
    y_pred=h_relu.dot(w2)#64*10
    
    #计算损失
    loss=np.square(y_pred-y).sum()#64*1
    print(t,loss,sep='    ')
    
    #向后传递
    #算出梯度
    grad_y_pred=2.0*(y_pred-y)#64*10
    grad_w2=h_relu.T.dot(grad_y_pred)#100*10
    grad_h_relu=grad_y_pred.dot(w2.T)#64*100
    grad_h=grad_h_relu.copy()#64*100
    grad_h[h<0]=0#64*100
    grad_w1=x.T.dot(grad_h)#1000*100
    
    #更新w1 w2
    w1-=learning_rate*grad_w1
    w2-=learning_rate*grad_w2
    

2.torch实现

  • mm():乘法,相当于dot()
  • t():转置
  • clamp(min= ,max= ):加紧,上下限分别是参数min max

2.1 修改numpy代码

import torch

N,D_in,H,D_out=64,1000,100,10#多少个训练数据,输入的维度,中间隐含层的神经元个数,输出的维度

#随机创建一些训练数据
x=torch.randn(N,D_in)#64*1000
y=torch.randn(N,D_out)#64*10

w1=torch.randn(D_in,H)#1000*100
w2=torch.randn(H,D_out)#100*10

learning_rate=1e-6#学习率

for t in range(500):#500次
    #向前传递
    h=x.mm(w1)#64*100    mm:矩阵乘法,相当于numpy中的dot
    h_relu=h.clamp(min=0)#64*100   clamp:加紧  相当于max   clamp(min= , max= ):固定上下限
    y_pred=h_relu.mm(w2)#64*10
    
    #计算损失
    loss=(y_pred-y).pow(2).sum().item()#64*1   item:一个数据直接转成数字
    print(t,loss,sep='    ')
    
    #向后传递
    #算出梯度
    grad_y_pred=2.0*(y_pred-y)#64*10
    grad_w2=h_relu.t().mm(grad_y_pred)#100*10
    grad_h_relu=grad_y_pred.mm(w2.t())#64*100
    grad_h=grad_h_relu.clone()#64*100   clone():复制,相当于copy
    grad_h[h<0]=0#64*100
    grad_w1=x.t().mm(grad_h)#1000*100
    
    #更新w1 w2
    w1-=learning_rate*grad_w1
    w2-=learning_rate*grad_w2

2.2 PyTorch:Tensor和autograd

2.2.1 简单应用 

#简单介绍requires_grad
x=torch.tensor(1.,requires_grad=True)#注意:必须是浮点型
w=torch.tensor(2.,requires_grad=True)
b=torch.tensor(3.,requires_grad=True)
y=w*x+b # y=2*1+3

y.backward()

#dy / dw =x
w.grad,x.grad,b.grad  #(tensor(1.), tensor(2.), tensor(1.))

2.2.2 torch实现

#torch实现
import torch

N,D_in,H,D_out=64,1000,100,10#多少个训练数据,输入的维度,中间隐含层的神经元个数,输出的维度

#随机创建一些训练数据
x=torch.randn(N,D_in)#64*1000
y=torch.randn(N,D_out)#64*10

w1=torch.randn(D_in,H,requires_grad=True)#1000*100
w2=torch.randn(H,D_out,requires_grad=True)#100*10

learning_rate=1e-6#学习率

for t in range(500):#500次
    #向前传递
    y_pred=x.mm(w1).clamp(min=0).mm(w2)
    
    #计算损失
    loss=(y_pred-y).pow(2).sum()#loss其实是一个计算图
    

    print(t,loss.item(),sep='    ')
    
    #向后传递
    loss.backward()
    
    #更新w1 w2
    with torch.no_grad():
        w1-=learning_rate*w1.grad
        w2-=learning_rate*w2.grad
        w1.grad.zero_()
        w2.grad.zero_()

2.2.3 PyTorch:nn

这次我们使用PyTorch中nn这个库来构建网络。用PyTorch autograd来构建计算图和计算gradients.
然后PyTorch会帮我们自动计算gradient。

#PyTorch:nn
import torch.nn as nn
N,D_in,H,D_out=64,1000,100,10#多少个训练数据,输入的维度,中间隐含层的神经元个数,输出的维度

#随机创建一些训练数据
x=torch.randn(N,D_in)#64*1000
y=torch.randn(N,D_out)#64*10

model=torch.nn.Sequential(
    torch.nn.Linear(D_in,H),# w1 * x + b1    默认bias+True
    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.cuda()#如果想要在cuda上运行
loss_fn=nn.MSELoss(reduction='sum')


learning_rate=1e-6#学习率

for t in range(500):#500次
    #向前传递
    y_pred=model(x)#这样写,就直接model.forward()
    loss=loss_fn(y_pred,y)
    print(t,loss.item(),sep='\t')
    
    loss.backward()
    
    with torch.no_grad():
        for param in model.parameters():#所有的参数都在model.parameters()里面
            param-=learning_rate*param.grad

    model.zero_grad()

2.2.4 PyTorch:optim

这一次我们不再手动更新模型的weights,而是使用optim这个包来帮助我们更新参数。optim这个package提供了各种不同的模型优化方法,包括SGD+mornentum, RMSProp,Adam等等。

import torch.nn as nn
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)
w2=torch.randn(H,D_out,requires_grad=True)

model=torch.nn.Sequential(
    torch.nn.Linear(D_in,H),
    torch.nn.ReLU(),
    torch.nn.Linear(H,D_out)
)
torch.nn.init.normal_(model[0].weight)
torch.nn.init.normal_(model[2].weight)

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

learning_rate=1e-4
optimizer=torch.optim.Adam(model.parameters(),lr=learning_rate)#自动更新参数  learning_rate一般等于1e-4

for t in range(500):
    y_pred=model(x)
    loss=loss_fn(y_pred,y)
    print(t,loss.item(),sep='\t')
    loss.backward()
    optimizer.step()#更新参数 

优化

import torch.nn as nn
import torch

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):
        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)

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

learning_rate=1e-4
optimizer=torch.optim.Adam(model.parameters(),lr=learning_rate)


for t in range(500):
    y_pred=model(x)
    loss=loss_fn(y_pred,y)
    print(t,loss.item(),sep='\t')
    loss.backward()
    optimizer.step()#更新参数
    
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值