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()#更新参数