美文网首页
神经网络

神经网络

作者: 晨光523152 | 来源:发表于2021-01-20 13:07 被阅读0次

    记录一下自己学 pytorch,学习的资料为 pytorch 的中文文档,传送门:https://pytorch.apachecn.org/docs/1.4/blitz/neural_networks_tutorial.html

    # 可以使用 torch.nn 包来构建神经网络
    # 已经介绍了 autograd 包, nn 包则依赖于 autograd 包来定义模型并对它们求导。
    # 一个 nn.Module 包含各个层和一个 forward(input) 方法,该方法返回 output。
    
    # 一个神经网络的典型训练过程如下:
    # 1. 定义包含一些可学习参数(或者叫做权重)的神经网络
    # 2. 在输入数据集上迭代
    # 3. 通过网络处理输入
    # 4. 计算 loss(输出和正确答案的距离)
    # 5. 将梯度反向传播给网络的参数
    # 6. 更新网络的权重,一般使用一个简单的规则: weight = weight - learning_rate * gradient
    
    # 定义网络
    # 让我们定义一个这样的网络:
    
    import torch
    import torch.nn as nn
    import torch.nn.functional as F
    
    class Net(nn.Module):
    
      def __init__(self):
        super(Net, self).__init__()
    
        # 输入图像 channel: 1;输出 channel: 6; 5 x 5 卷积核
        self.conv1 = nn.Conv2d(1, 6, 5)
        self.conv2 = nn.Conv2d(6, 16, 5)
        # an affine operation: y = Wx + b
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)
    
      def forward(self, x):
        # 2 x 2 Max pooling
        x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
        # 如果是方阵,则可以只使用一个数字进行定义
        x = F.max_pool2d(F.relu(self.conv2(x)), 2)
        x = x.view(-1, self.num_flat_features(x))
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
    
        return x
    
      def num_flat_features(self, x):
        size = x.size()[1:] # 除去批处理维度的其他所有维度
        num_features = 1
        for s in size:
          num_features *= s
        return num_features
    
    net = Net()
    print(net)
    # 输出为:
    Net(
      (conv1): Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1))
      (conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
      (fc1): Linear(in_features=400, out_features=120, bias=True)
      (fc2): Linear(in_features=120, out_features=84, bias=True)
      (fc3): Linear(in_features=84, out_features=10, bias=True)
    )
    
    # 只需要定义 forward 函数, backward 函数会使用 autograd 时自动定义, backward 函数用来计算导数。
    # 可以在 forward 函数中使用任何针对张量的操作和计算
    # 一个模型的可学习参数可以通过 net.parameters() 返回
    
    params = list(net.parameters())
    print(len(params))
    print(params[0].size()) # conv1's .weight
    #输出为:
    10
    torch.Size([6, 1, 5, 5])
    
    for i in range(len(params)):
      print(params[i].size())
    #输出为:
    torch.Size([6, 1, 5, 5])
    torch.Size([6])
    torch.Size([16, 6, 5, 5])
    torch.Size([16])
    torch.Size([120, 400])
    torch.Size([120])
    torch.Size([84, 120])
    torch.Size([84])
    torch.Size([10, 84])
    torch.Size([10])
    
    # 尝试一个随机的 32 x 32 的输入。注意这个网络(LeNet)的期待输入是 32 x 32 的张量。
    # 如果使用 MNIST 数据集来训练这个网络,要把图片大小重新调整到 32 x 32。
    
    input = torch.randn(1, 1, 32, 32)
    out = net(input)
    print(out)
    # 输出为:
    tensor([[-0.0884, -0.0955, -0.1157, -0.0185, -0.0328,  0.0188,  0.0193, -0.1154,
              0.0448, -0.0642]], grad_fn=<AddmmBackward>)
    
    # 清零所有参数的梯度缓存,然后进行随机梯度反向传播:
    net.zero_grad()
    out.backward(torch.randn(1, 10))
    
    # 损失函数
    # 一个损失函数接受一对(output,target)作为输入,计算一个值来估计网络的输出和目标值相差多少。
    # nn 包中有很多不同的损失函数。 nn.MSELoss 是比较简单的一种,它计算输出和目标的均方误差
    
    output = net(input)
    target = torch.randn(10)
    target = target.view(1, -1)
    criterion = nn.MSELoss()
    
    loss = criterion(output, target)
    print(loss)
    #输出为:
    tensor(1.3201, grad_fn=<MseLossBackward>)
    
    # 现在,如果使用 loss 的 .grad_fn 属性跟踪反向传播过程,会看到计算图如下:
    
    input -> conv2d -> relu -> maxpool2d -> conv2d -> relu -> maxpool2d
          -> view -> linear -> relu -> linear -> relu -> linear
          -> MSELoss
          -> loss
    
    # 所以,当调用 loss.backward(),整张图开始关于 loss 微分,图中所有设置了 requires_grad=True 的张量 .grad 属性累积着张量梯度。
    
    print(loss.grad_fn)
    print(loss.grad_fn.next_functions[0][0])
    print(loss.grad_fn.next_functions[0][0].next_functions[0][0])
    #输出为:
    <MseLossBackward object at 0x7f4d00808908>
    <AddmmBackward object at 0x7f4d008089b0>
    <AccumulateGrad object at 0x7f4d00808908>
    
    # 反向传播
    
    # 只需要调用 loss.backward() 来反向传播误差。需要清零现有的梯度,否则梯度将会与已有的梯度累加。
    # 现在,将调用 loss.backward(),并且查看 conv1 层的偏置在反向传播前后的梯度。
    
    net.zero_grad()
    print('conv1.bias.grad before backward')
    print(net.conv1.bias.grad)
    
    loss.backward()
    
    print('conv1.bias.grad after backward')
    print(net.conv1.bias.grad)
    #输出为:
    conv1.bias.grad before backward
    tensor([0., 0., 0., 0., 0., 0.])
    conv1.bias.grad after backward
    tensor([ 0.0120, -0.0098, -0.0056,  0.0060,  0.0059, -0.0120])
    
    # 更新权重
    
    # 最简单的更新规则是随机梯度下降法(SGD)
    # weight = weight - learning_rate * gradient
    
    learning_rate = 0
    for f in net.parameters():
      f.data.sub_(f.grad.data * learning_rate)
    
    # 然而,在使用神经网络时,可能希望使用各种不同的更新规则,如 SGD,Nesterov-SGA、Adam、RMSProp 等。
    # 为此,可以使用 torch.optim
    
    import torch.optim as optim
    
    # 创建优化器(optimizer)
    optimizer = optim.SGD(net.parameters(), lr=0.01)
    
    # 在训练的迭代中:
    optimizer.zero_grad() # 清零梯度缓存
    print(net.conv1.weight.grad)
    output = net(input)
    loss = criterion(output, target)
    loss.backward()
    optimizer.step()
    print(net.conv1.weight.grad)
    #输出为:
    tensor([[[[0., 0., 0., 0., 0.],
              [0., 0., 0., 0., 0.],
              [0., 0., 0., 0., 0.],
              [0., 0., 0., 0., 0.],
              [0., 0., 0., 0., 0.]]],
    
    
            [[[0., 0., 0., 0., 0.],
              [0., 0., 0., 0., 0.],
              [0., 0., 0., 0., 0.],
              [0., 0., 0., 0., 0.],
              [0., 0., 0., 0., 0.]]],
    
    
            [[[0., 0., 0., 0., 0.],
              [0., 0., 0., 0., 0.],
              [0., 0., 0., 0., 0.],
              [0., 0., 0., 0., 0.],
              [0., 0., 0., 0., 0.]]],
    
    
            [[[0., 0., 0., 0., 0.],
              [0., 0., 0., 0., 0.],
              [0., 0., 0., 0., 0.],
              [0., 0., 0., 0., 0.],
              [0., 0., 0., 0., 0.]]],
    
    
            [[[0., 0., 0., 0., 0.],
              [0., 0., 0., 0., 0.],
              [0., 0., 0., 0., 0.],
              [0., 0., 0., 0., 0.],
              [0., 0., 0., 0., 0.]]],
    
    
            [[[0., 0., 0., 0., 0.],
              [0., 0., 0., 0., 0.],
              [0., 0., 0., 0., 0.],
              [0., 0., 0., 0., 0.],
              [0., 0., 0., 0., 0.]]]])
    tensor([[[[ 1.4132e-03,  3.0524e-03,  1.4387e-02, -6.9879e-05,  5.0496e-03],
              [ 6.2602e-03,  7.7174e-04,  7.7477e-03,  4.8251e-03, -6.2586e-03],
              [-1.1347e-02,  1.7323e-02,  1.4601e-03,  4.7047e-03,  4.5172e-04],
              [ 1.5339e-03,  6.5314e-03,  3.5240e-03, -1.6078e-04,  2.6001e-02],
              [-4.3787e-03,  2.5129e-02, -4.8452e-03,  1.7136e-02, -2.2656e-03]]],
    
    
            [[[ 1.1603e-02,  2.5870e-04, -4.7882e-04, -1.2974e-02, -7.0833e-03],
              [ 9.1224e-03, -2.7099e-02, -7.2172e-03,  6.0094e-03, -1.9354e-03],
              [ 8.9487e-03,  1.0132e-03, -1.2599e-02,  6.6889e-04,  1.2481e-02],
              [ 1.9308e-02,  1.1304e-02, -2.6835e-02, -5.0302e-03, -1.2123e-02],
              [-8.6779e-03,  2.4515e-03, -1.5991e-03,  3.2772e-03,  1.5057e-03]]],
    
    
            [[[ 2.9538e-03,  3.2182e-03,  2.1735e-02, -4.1001e-03,  7.3709e-03],
              [-7.8341e-03,  8.6530e-03,  1.2804e-02,  4.7380e-03,  2.7090e-02],
              [ 2.3400e-02, -9.9183e-03, -2.7806e-03, -5.3960e-03,  6.5356e-03],
              [-9.2149e-03,  6.3300e-03, -9.1231e-03, -3.1583e-03, -2.5313e-02],
              [-6.8671e-03,  8.7669e-03,  2.8738e-02, -4.0501e-04,  1.3954e-02]]],
    
    
            [[[-2.8224e-02,  3.6240e-03, -3.5161e-03, -1.1865e-02,  5.3318e-03],
              [-3.4220e-03, -9.4413e-03, -8.9566e-03, -9.7369e-03,  9.6336e-03],
              [ 1.0341e-02, -1.8074e-02,  5.9631e-03,  6.8791e-03, -1.7632e-02],
              [ 6.7529e-03,  1.5338e-02,  6.8727e-03,  8.8999e-03, -5.4561e-03],
              [ 9.2013e-03,  4.1394e-03, -1.4813e-02,  1.5590e-02, -9.7826e-03]]],
    
    
            [[[-9.2427e-03,  1.0145e-02, -1.0158e-03,  6.6471e-03, -8.1966e-03],
              [-1.4890e-02, -3.3134e-02, -1.8499e-02,  2.5454e-03,  1.2673e-02],
              [-7.3737e-03, -2.1420e-02, -1.0963e-02, -1.5361e-02, -1.0578e-03],
              [-1.4120e-03,  6.1323e-04, -1.1165e-02,  4.9900e-03, -1.1872e-02],
              [-2.7640e-03,  2.2880e-02, -1.1687e-03, -5.3693e-03,  3.2699e-03]]],
    
    
            [[[ 6.0525e-03, -3.7511e-03, -5.7904e-03, -1.8990e-02,  7.1018e-03],
              [-1.3982e-02,  4.2345e-03, -1.7800e-02, -6.0713e-03, -4.9168e-03],
              [-7.9266e-03, -2.8650e-03,  1.9363e-02, -9.5297e-03, -2.8823e-03],
              [ 1.6598e-03, -8.0634e-04,  3.9225e-03,  1.4599e-02,  1.4768e-03],
              [ 1.2664e-04,  1.2907e-02, -6.1437e-03, -4.5010e-03,  1.0548e-02]]]])
    

    相关文章

      网友评论

          本文标题:神经网络

          本文链接:https://www.haomeiwen.com/subject/ngiczktx.html