手把手教学,实现两层神经网络(在b站有辅助视频,视频非原创)
·
如何实现两层神经网络
三军未动,粮草先行(使用的软件和工具)
我们在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学习视频
有不懂的留下评论或者看视频,或者百度,谢谢大家!
更多推荐
所有评论(0)