[自然語言處理-先修]五、卷積神經(jīng)網(wǎng)絡(luò)

學(xué)習(xí)路線參考:

https://blog.51cto.com/u_15298598/3121189

https://github.com/Ailln/nlp-roadmap

https://juejin.cn/post/7113066539053482021

本節(jié)學(xué)習(xí)使用工具&閱讀文章:

https://easyai.tech/ai-definition/cnn/

https://blog.csdn.net/weixin_44912159/article/details/105345760

  1. 概述

    卷積神經(jīng)網(wǎng)絡(luò)是神經(jīng)網(wǎng)絡(luò)的一個(gè)分支,其特色為包含卷積計(jì)算。CNN可以進(jìn)行監(jiān)督學(xué)習(xí)和非監(jiān)督學(xué)習(xí),有著較強(qiáng)的數(shù)據(jù)特征提取能力,且機(jī)器學(xué)習(xí)效果穩(wěn)定,不依賴特征工程。多用于圖像處理。

    CNN中除了全連接層還存在著兩種特有的網(wǎng)絡(luò)層:卷積層、池化層。

    CNN結(jié)構(gòu)
  1. 卷積層

    用于提取輸入矩陣的特征。

    卷積層的計(jì)算原理是卷積核在輸入矩陣上進(jìn)行滑動,每滑動一次,就將滑動區(qū)域的元素和自身相乘并累加,從而計(jì)算出輸出矩陣中對應(yīng)位置的元素。

    卷積核是可學(xué)習(xí)的參數(shù),相當(dāng)于權(quán)重。


    卷積層計(jì)算過程

假設(shè)輸入矩陣的規(guī)模為m*n,滑動步長為t,卷積核規(guī)模為k*k,則卷積層的輸出矩陣尺寸為(m-k+t)*(n-k+t)。通?;瑒硬介L為1。

  • 前向傳播

    假設(shè)輸入集合為X=\{X_1,X_2,…,X_n\},卷積核矩陣集合為W=\{W_1,W_2,…,W_n\},卷積輸出矩陣為S,其規(guī)模為i*j,偏置量為b。則卷積過程可以表示為:S=(X*W)+b=\sum^n_k(X_k*W_k)+b

    假設(shè)卷積層具有激活函數(shù)\theta(x),則卷積層的輸出結(jié)果為\theta(S)=\theta(\sum^n_k(X_k*W_k)+b)

  1. 池化層

    用于對信息進(jìn)行抽樣,簡化輸入數(shù)據(jù)的同時(shí)保證特征不變性。

    池化層的計(jì)算原理是池化核在輸入矩陣上進(jìn)行滑動,按照池化規(guī)則進(jìn)行計(jì)算。通常池化核的計(jì)算方法一般有最大值池化和平均值池化兩種。

    池化層計(jì)算過程
  2. Pytorch實(shí)現(xiàn)

    1. 數(shù)據(jù)準(zhǔn)備(使用MNIST數(shù)據(jù)集)

      import torch
      from torch import nn
      from torch.utils.data import DataLoader
      from torchvision import datasets
      from torchvision.transforms import ToTensor, Lambda, Compose
      import matplotlib.pyplot as plt
      
      # 載入訓(xùn)練集
      training_data = datasets.MNIST(
          root="data",
          train=True,
          download=True,
          transform=ToTensor()
      )
      
      # 載入測試集
      test_data = datasets.MNIST(
          root="data",
          train=False,
          download=True,
          transform=ToTensor()
      )
      
      print(training_data.train_data.size())   # [60000,28,28]
      plt.imshow(training_data.train_data[0].numpy()) # 展示第一張圖片
      plt.show()
      
      展示第一張圖片
      batch_size = 128
      
      # 創(chuàng)建數(shù)據(jù)管道
      train_dataloader = DataLoader(training_data, batch_size=batch_size, shuffle=True)
      test_dataloader = DataLoader(test_data, batch_size=batch_size)
      
      # 檢查數(shù)據(jù)形狀
      for X, y in test_dataloader:
          print("Shape of X [N, C, H, W]: ", X.shape, X.dtype)
          print("Shape of y: ", y.shape, y.dtype)
          break
          
      # N: 一個(gè)batch中的data實(shí)例數(shù)量
      # C: 通道數(shù)
      # [H, W]: 圖片的高和寬
      
    2. 網(wǎng)絡(luò)搭建

      class CNN(nn.Module):
          def __init__(self):
              super(CNN, self).__init__()
              self.conv1 = nn.Sequential(
                  nn.Conv2d(1, 16, kernel_size=3, padding=1), 
                  # input:1 * 28 * 28, output:16 * 28 * 28 
                  nn.ReLU(),
                  nn.MaxPool2d(2) # input:16 * 28 * 28, output:16 * 14 * 14 
                  ) 
      
              self.conv2 = nn.Sequential(
                  nn.Conv2d(16, 32, kernel_size=3, padding=1), 
                  # input:16 * 14 * 14, output:32 * 14 * 14 
                  nn.ReLU(),
                  nn.MaxPool2d(2) # input:32 * 14 * 14, output:32 * 7 * 7 
                  ) 
      
              self.classifier = nn.Sequential(
                  nn.Linear(32 * 7 * 7, 10) # 將輸出分成10類
                  )
      
          def forward(self, x):
            x = self.conv1(x)
            x = self.conv2(x)
            x = x.view(x.size(0), -1) # [batch, 32, 7, 7] → [batch, 32*7*7]
            out = self.classifier(x)
            return out
      
      model = CNN()
      print(model)
      
      CNN(
        (conv1): Sequential(
          (0): Conv2d(1, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
          (1): ReLU()
          (2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
        )
        (conv2): Sequential(
          (0): Conv2d(16, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
          (1): ReLU()
          (2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
        )
        (classifier): Sequential(
          (0): Linear(in_features=1568, out_features=10, bias=True)
        )
      )
      
    3. 損失函數(shù)與優(yōu)化器定義

      loss_fn = nn.CrossEntropyLoss() # 交叉熵
      
      optimizer = torch.optim.Adam(model.parameters()) # Adam優(yōu)化
      
    4. 模型訓(xùn)練

      # epochs: 迭代次數(shù)
      epochs=10
      
      for i in range(epochs): # 每個(gè)epoch的迭代
          model.train() # 訓(xùn)練模式
          train_loss=0
          for j, (X, y) in enumerate(train_dataloader): # 每個(gè)batch的迭代
              # 前向傳播
              pred = model(X)
              # 計(jì)算損失
              loss = loss_fn(pred, y)
              train_loss += loss.item()
              # 反向傳播
              optimizer.zero_grad()
              loss.backward()
              optimizer.step()
      
              # 每100個(gè)batch輸出損失值
              if j % 100 == 0:
                  loss = loss.item()
                  print(f"epoch {i} batch {j} loss: {loss/batch_size:>7f}")
          
          # 每次迭代結(jié)束后輸出測試結(jié)果  
          with torch.no_grad():
              model.eval() # 評估模式
              test_loss=0
              hit=0
              for (X, y) in test_dataloader:
                  pred = model(X)
                  test_loss += loss_fn(pred, y).item()
                  hit += (pred.argmax(1) == y).sum().item()
              print(f"epoch {i}, train loss: {train_loss/len(train_dataloader.dataset):>7f} test loss: {test_loss/len(test_dataloader.dataset):>7f} accuracy: {hit/len(test_dataloader.dataset) :>7f}")    
      
      • optimizer.zero_grad()

        清空歷史梯度。

        根據(jù)pytorch中的backward()函數(shù)的計(jì)算,當(dāng)網(wǎng)絡(luò)參量進(jìn)行反饋時(shí),梯度是被積累的而不是被替換掉。batch之間并不需要累積梯度,因此每個(gè)batch都要zero_grad。

      • loss.backward()

        進(jìn)行反向傳播,并計(jì)算梯度。

      • optimizer.step()

        優(yōu)化器對權(quán)重值進(jìn)行更新。

      • with torch.no_grad()

        停止autograd模塊的工作,以起到加速和節(jié)省顯存的作用。它的作用是將該with語句包裹起來的部分停止梯度的更新。

    5. 結(jié)果

      epoch 0 batch 0 loss: 0.017991
      epoch 0 batch 100 loss: 0.018041
      epoch 0 batch 200 loss: 0.018068
      epoch 0 batch 300 loss: 0.018066
      epoch 0 batch 400 loss: 0.018037
      epoch 0, train loss: 0.018034 test loss: 0.018228 accuracy: 0.099000
      epoch 1 batch 0 loss: 0.018085
      epoch 1 batch 100 loss: 0.017887
      epoch 1 batch 200 loss: 0.018049
      epoch 1 batch 300 loss: 0.018109
      epoch 1 batch 400 loss: 0.018097
      epoch 1, train loss: 0.018034 test loss: 0.018228 accuracy: 0.099000
      epoch 2 batch 0 loss: 0.017934
      epoch 2 batch 100 loss: 0.017987
      epoch 2 batch 200 loss: 0.018088
      epoch 2 batch 300 loss: 0.017946
      epoch 2 batch 400 loss: 0.018093
      epoch 2, train loss: 0.018034 test loss: 0.018228 accuracy: 0.099000
      epoch 3 batch 0 loss: 0.017929
      epoch 3 batch 100 loss: 0.017884
      epoch 3 batch 200 loss: 0.018053
      epoch 3 batch 300 loss: 0.017972
      epoch 3 batch 400 loss: 0.017919
      epoch 3, train loss: 0.018034 test loss: 0.018228 accuracy: 0.099000
      epoch 4 batch 0 loss: 0.018011
      epoch 4 batch 100 loss: 0.017994
      epoch 4 batch 200 loss: 0.017952
      epoch 4 batch 300 loss: 0.018021
      epoch 4 batch 400 loss: 0.018020
      epoch 4, train loss: 0.018034 test loss: 0.018228 accuracy: 0.099000
      epoch 5 batch 0 loss: 0.018102
      epoch 5 batch 100 loss: 0.018018
      epoch 5 batch 200 loss: 0.018042
      epoch 5 batch 300 loss: 0.018090
      epoch 5 batch 400 loss: 0.017981
      epoch 5, train loss: 0.018034 test loss: 0.018228 accuracy: 0.099000
      epoch 6 batch 0 loss: 0.017944
      epoch 6 batch 100 loss: 0.017992
      epoch 6 batch 200 loss: 0.018033
      epoch 6 batch 300 loss: 0.018052
      epoch 6 batch 400 loss: 0.018094
      epoch 6, train loss: 0.018034 test loss: 0.018228 accuracy: 0.099000
      epoch 7 batch 0 loss: 0.018016
      epoch 7 batch 100 loss: 0.018022
      epoch 7 batch 200 loss: 0.018112
      epoch 7 batch 300 loss: 0.018066
      epoch 7 batch 400 loss: 0.018044
      epoch 7, train loss: 0.018034 test loss: 0.018228 accuracy: 0.099000
      epoch 8 batch 0 loss: 0.018011
      epoch 8 batch 100 loss: 0.018112
      epoch 8 batch 200 loss: 0.018002
      epoch 8 batch 300 loss: 0.018023
      epoch 8 batch 400 loss: 0.018140
      epoch 8, train loss: 0.018034 test loss: 0.018228 accuracy: 0.099000
      epoch 9 batch 0 loss: 0.018014
      epoch 9 batch 100 loss: 0.017930
      epoch 9 batch 200 loss: 0.018003
      epoch 9 batch 300 loss: 0.017927
      epoch 9 batch 400 loss: 0.017920
      epoch 9, train loss: 0.018034 test loss: 0.018228 accuracy: 0.099000
      
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容