import torch
#import numpy
#from torch.autograd import Variable
EPOCH = 500
LEARNING_RATE = 1e-6
N , D_in , H , D_out = 64 , 1000, 100 , 10
# N代表的是样本个数,D_in是样本的维度,H是隐藏层的维度,D_out是输出层的维度
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)
"""h = w1 * x
h_relu = relu(h)
y = w2 * x"""
for step in range(EPOCH):
#前向传播
h = torch.mm(X, w1) # 隐层 h = w1 * x
h_relu = h.clamp(min=0) # relu 将小于0的部分修正为0 大于0的部分则不变
y_pred = torch.mm(h_relu, w2) # 输出层 y = w2 * h_relu
# 损失函数计算误差
loss = (y_pred - Y).pow(2).sum()
if step % 100 == 0:
print('epoch: {} loss: {:.5f}'.format(step, loss.item()))#loss为(1,)的tensor
# 反向传播 计算导数
loss.backward() # 会自动计算所有参数的导数(包括W1、W2、X)
#更新参数
with torch.no_grad():
#随机梯度下降
w1 -= LEARNING_RATE * w1.grad
w2 -= LEARNING_RATE * w2.grad
#更新完梯度之后要手动置0。不置0会一直叠加
w1.grad.zero_()
w2.grad.zero_()
import torch
EPOCH = 500
LEARNING_RATE = 1e-6
#超参数初始化
N , D_in , H , D_out = 64 , 1000, 100 , 10 # N代表的是样本个数,D_in是样本的维度,H是隐藏层的维度,D_out是输出层的维度
#训练数据和参数初始化
X = torch.randn(N,D_in)
Y = torch.randn(N,D_out)
# 先用随机值初始化两层神经网络的权重
w1 = torch.randn(D_in,H)
w2 = torch.randn(H,D_out)
#print("X:",X,"Y:",Y,w1,w2)
for step in range(500):
#前向传播
h = X.mm(w1) #(N,H)
h_relu = h.clamp(min=0)#(N,H)
y_pred = h_relu.mm(w2) #(N,D_out)
#定义损失函数
loss = (y_pred - Y).pow(2).sum().item()
if step % 100 == 0:
print('epoch: {} loss: {:.5f}'.format(step, loss))#loss为(1,)的tensor
#反向传播
grad_y_pred = 2.0 * (y_pred - Y)#(N,D_out)
grad_w2 = h_relu.t().mm(grad_y_pred)#(H,D_out)
grad_h_relu = grad_y_pred.mm(w2.t())#(N,H)
grad_h[h > 0] = grad_h_relu[h > 0].clone()#大于0时导数不变
grad_h[h < 0] = 0#小于0时导数变0
grad_w1 = X.t().mm(grad_h)#要grad_w1的矩阵维度和w1维度相同,才能相减
#参数更新
w1 -= LEARNING_RATE * grad_w1
w2 -= LEARNING_RATE * grad_w2
这种写法,反向传播的求导是最大的难点。需要理解正向传播和反向传播来推导公式,再把公式用代码实现。最好需要看一下吴恩达的机器学习视频的前三章(代价函数和梯度求导)和神经网络部分,理解反向传播的计算方法。但是它的视频的激励函数不同,我们需要针对本代码中的relu函数来实现反向传播。
下面是对神经网络里面的一些tensor进行输出,从维度来理解
import torch
lr = 1e-6
EPOCH = 500
LEARNING_RATE = 1e-6
#超参数初始化
N , D_in , H , D_out = 3 , 4, 2 ,1 # N代表的是样本个数,D_in是样本的维度,H是隐藏层的维度,D_out是输出层的维度
#训练数据和参数初始化
X = torch.randn(N,D_in)
Y = torch.randn(N,D_out)
# 先用随机值初始化两层神经网络的权重
w1 = torch.randn(D_in,H)
w2 = torch.randn(H,D_out)
print("X:",X)#3样本 4特征
print("Y:",Y)#3结果
print("w1:",w1)
print("w2",w2)
h = X.mm(w1)
print("h:",h)
h_relu = h.clamp(min=0)#(N,h_dim)
print("h_relu",h_relu)
X: tensor([[ 1.3393, -0.3668, -0.3531, 1.4490],
[-0.2834, 0.3056, 1.0691, 1.7448],
[ 0.1956, 0.9079, 0.4525, -1.1220]])
Y: tensor([[-1.8117],
[-0.4406],
[ 1.1850]])
w1: tensor([[ 1.4459, -0.1429],
[-0.8366, -0.5614],
[-1.4148, -0.4373],
[ 0.4911, -1.1529]])
w2 tensor([[-0.6083],
[-0.2623]])
h: tensor([[ 3.4545, -1.5016],
[-1.3210, -2.6101],
[-1.6679, 0.5581]])
h_relu tensor([[3.4545, 0.0000],
[0.0000, 0.0000],
[0.0000, 0.5581]])
其实这已经是年初1月做的了, 距离现在已经很久啦。 如今想来, 这依然是入门深度学习最好的实践之一 。 入门深度学习的第一份代码,应该是这个。
然后吴恩达的机器学习视频也在上半年看完了,我是在黄海广博士的博客上稍作修改我的吴恩达机器学习笔记的。
但是后来发现,本地的markdown博客并不能在csdn上直接展示,里面的图很难传。就不更新啦,有需要可以联系我要。
目前我即将入读博士,如果对机器学习或自然语言处理感兴趣,欢迎关注我的知乎一起学习交流:
https://www.zhihu.com/people/da-shu-22-92-78