简单神经网络的搭建和梯度下降法训练

一、用numpy实现两层神经网络

一个全连接的RELU神经网络,一个隐藏层,为了简单起见不用bais。作用是从x预测y。

Loss 函数为:

                                  Loss = \sum_{i=1}^{m}\left ( \left f(x_{i} \right ) -\right y_{i})^{2}

假设输入为x,所以第一层的输出为h=w_{1}x,然后经过RELU激活函数,得到的结果为h_relu。当时不太清楚为什么要用激活函数,查了一下感觉这篇博客讲的挺好。链接:https://www.cnblogs.com/ya-qiang/p/9258714.html

h_relu又作为第二层的输入,输出为y_pred = h_relu*w2。

然后计算损失函数 Loss = \sum_{i=1}^{m}\left ( \left y\_pred -\right y)^{2}  

到目前为止前向神经网络和loss就计算好了,这时候就要反向传播来修正w1,w2。

先把所有公式理一下:h = x*w1            h_relu = relu(h)      y_pred = h_relu*w2     loss = (y_pred-y)²

这样通过链式法则可以求得w1和w2的梯度,也就是\partial loss/\partial {w_{1}}\partial loss/\partial {w_{2}}

relu函数的导数也就是大于0的部分为1,小于0的部分是0

然后修正w1,w2。

以上的步骤循环进行500次,完整代码如下:

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) # h和0逐位比较取大者  relu激活函数
    y_pred = h_relu.dot(w2) # N*D_out
    
    # computer loss
    loss = np.square(y_pred - y).sum() #计算各元素的平方
    print(it, loss)     #输出损失值
    
    # Backward pass
    # compute the gradient
    grad_y_pred = 2.0 * (y_pred - y)
    grad_w2 = h_relu.T.dot(grad_y_pred)    #矩阵的乘法法则,需要转置.T
    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 weights of w1 and w2
    w1 -= learning_rate * grad_w1
    w2 -= learning_rate * grad_w2

运行结果如下:

可以看到loss的值在慢慢变小。

二、用Pytorch实现

这里先将里面的一些语法改成用pytorch实现就行,用pytorch就不用手撸一遍梯度下降了,直接用loss.backward(),注意要梯度清零。

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)  #需要对w1求梯度
w2 = torch.randn(H,D_out,requires_grad=True)
learning_rate = 1e-6

for it in range(500):
    # forward pass
    h = x.mm(w1)  # 矩阵的点积运算 得到的是 N*H
    h_relu = h.clamp(min=0) # h和0逐位比较取大者  relu激活函数
    y_pred = h_relu.mm(w2) # N*D_out
    
    # computer loss
    loss = (y_pred - y).pow(2).sum() #计算各元素的平方,item() tensor转数字
    print(it, loss.item())
    
    # Backward pass
    # compute the gradient
    loss.backward()
    
    # update weights 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自带的torch.nn在构造神经网络的时候会方便很多,先这样,以后再用。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值