<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                # 5.5 卷積神經網絡(LeNet) 在3.9節(多層感知機的從零開始實現)里我們構造了一個含單隱藏層的多層感知機模型來對Fashion-MNIST數據集中的圖像進行分類。每張圖像高和寬均是28像素。我們將圖像中的像素逐行展開,得到長度為784的向量,并輸入進全連接層中。然而,這種分類方法有一定的局限性。 1. 圖像在同一列鄰近的像素在這個向量中可能相距較遠。它們構成的模式可能難以被模型識別。 2. 對于大尺寸的輸入圖像,使用全連接層容易造成模型過大。假設輸入是高和寬均為1000像素的彩色照片(含3個通道)。即使全連接層輸出個數仍是256,該層權重參數的形狀是`$ 3,000,000\times 256 $`:它占用了大約3 GB的內存或顯存。這帶來過復雜的模型和過高的存儲開銷。 卷積層嘗試解決這兩個問題。一方面,卷積層保留輸入形狀,使圖像的像素在高和寬兩個方向上的相關性均可能被有效識別;另一方面,卷積層通過滑動窗口將同一卷積核與不同位置的輸入重復計算,從而避免參數尺寸過大。 卷積神經網絡就是含卷積層的網絡。本節里我們將介紹一個早期用來識別手寫數字圖像的卷積神經網絡:LeNet [1]。這個名字來源于LeNet論文的第一作者Yann LeCun。LeNet展示了通過梯度下降訓練卷積神經網絡可以達到手寫數字識別在當時最先進的結果。這個奠基性的工作第一次將卷積神經網絡推上舞臺,為世人所知。LeNet的網絡結構如下圖所示。 <div align=center> <img width="600" src="images/5.5_lenet.png"/> </div> <div align=center>LeNet網絡結構</div> ## 5.5.1 LeNet模型 LeNet分為卷積層塊和全連接層塊兩個部分。下面我們分別介紹這兩個模塊。 卷積層塊里的基本單位是卷積層后接最大池化層:卷積層用來識別圖像里的空間模式,如線條和物體局部,之后的最大池化層則用來降低卷積層對位置的敏感性。卷積層塊由兩個這樣的基本單位重復堆疊構成。在卷積層塊中,每個卷積層都使用`$ 5\times 5 $`的窗口,并在輸出上使用sigmoid激活函數。第一個卷積層輸出通道數為6,第二個卷積層輸出通道數則增加到16。這是因為第二個卷積層比第一個卷積層的輸入的高和寬要小,所以增加輸出通道使兩個卷積層的參數尺寸類似。卷積層塊的兩個最大池化層的窗口形狀均為`$ 2\times 2 $`,且步幅為2。由于池化窗口與步幅形狀相同,池化窗口在輸入上每次滑動所覆蓋的區域互不重疊。 卷積層塊的輸出形狀為(批量大小, 通道, 高, 寬)。當卷積層塊的輸出傳入全連接層塊時,全連接層塊會將小批量中每個樣本變平(flatten)。也就是說,全連接層的輸入形狀將變成二維,其中第一維是小批量中的樣本,第二維是每個樣本變平后的向量表示,且向量長度為通道、高和寬的乘積。全連接層塊含3個全連接層。它們的輸出個數分別是120、84和10,其中10為輸出的類別個數。 下面我們通過`Sequential`類來實現LeNet模型。 ``` python import time import torch from torch import nn, optim import sys sys.path.append("..") import d2lzh_pytorch as d2l device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') class LeNet(nn.Module): def __init__(self): super(LeNet, self).__init__() self.conv = nn.Sequential( nn.Conv2d(1, 6, 5), # in_channels, out_channels, kernel_size nn.Sigmoid(), nn.MaxPool2d(2, 2), # kernel_size, stride nn.Conv2d(6, 16, 5), nn.Sigmoid(), nn.MaxPool2d(2, 2) ) self.fc = nn.Sequential( nn.Linear(16*4*4, 120), nn.Sigmoid(), nn.Linear(120, 84), nn.Sigmoid(), nn.Linear(84, 10) ) def forward(self, img): feature = self.conv(img) output = self.fc(feature.view(img.shape[0], -1)) return output ``` 接下來查看每個層的形狀。 ```python net = LeNet() print(net) ``` 輸出: ``` LeNet( (conv): Sequential( (0): Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1)) (1): Sigmoid() (2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) (3): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1)) (4): Sigmoid() (5): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) ) (fc): Sequential( (0): Linear(in_features=256, out_features=120, bias=True) (1): Sigmoid() (2): Linear(in_features=120, out_features=84, bias=True) (3): Sigmoid() (4): Linear(in_features=84, out_features=10, bias=True) ) ) ``` 可以看到,在卷積層塊中輸入的高和寬在逐層減小。卷積層由于使用高和寬均為5的卷積核,從而將高和寬分別減小4,而池化層則將高和寬減半,但通道數則從1增加到16。全連接層則逐層減少輸出個數,直到變成圖像的類別數10。 ## 5.5.2 獲取數據和訓練模型 下面我們來實驗LeNet模型。實驗中,我們仍然使用Fashion-MNIST作為訓練數據集。 ``` python batch_size = 256 train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size=batch_size) ``` 因為卷積神經網絡計算比多層感知機要復雜,建議使用GPU來加速計算。因此,我們對3.6節(softmax回歸的從零開始實現)中描述的`evaluate_accuracy`函數略作修改,使其支持GPU計算。 ``` python # 本函數已保存在d2lzh_pytorch包中方便以后使用。該函數將被逐步改進。 def evaluate_accuracy(data_iter, net, device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')): acc_sum, n = 0.0, 0 with torch.no_grad(): for X, y in data_iter: if isinstance(net, torch.nn.Module): net.eval() # 評估模式, 這會關閉dropout acc_sum += (net(X.to(device)).argmax(dim=1) == y.to(device)).float().sum().cpu().item() net.train() # 改回訓練模式 else: # 自定義的模型, 3.13節之后不會用到, 不考慮GPU if('is_training' in net.__code__.co_varnames): # 如果有is_training這個參數 # 將is_training設置成False acc_sum += (net(X, is_training=False).argmax(dim=1) == y).float().sum().item() else: acc_sum += (net(X).argmax(dim=1) == y).float().sum().item() n += y.shape[0] return acc_sum / n ``` 我們同樣對3.6節中定義的`train_ch3`函數略作修改,確保計算使用的數據和模型同在內存或顯存上。 ``` python # 本函數已保存在d2lzh_pytorch包中方便以后使用 def train_ch5(net, train_iter, test_iter, batch_size, optimizer, device, num_epochs): net = net.to(device) print("training on ", device) loss = torch.nn.CrossEntropyLoss() batch_count = 0 for epoch in range(num_epochs): train_l_sum, train_acc_sum, n, start = 0.0, 0.0, 0, time.time() for X, y in train_iter: X = X.to(device) y = y.to(device) y_hat = net(X) l = loss(y_hat, y) optimizer.zero_grad() l.backward() optimizer.step() train_l_sum += l.cpu().item() train_acc_sum += (y_hat.argmax(dim=1) == y).sum().cpu().item() n += y.shape[0] batch_count += 1 test_acc = evaluate_accuracy(test_iter, net) print('epoch %d, loss %.4f, train acc %.3f, test acc %.3f, time %.1f sec' % (epoch + 1, train_l_sum / batch_count, train_acc_sum / n, test_acc, time.time() - start)) ``` 學習率采用0.001,訓練算法使用Adam算法,損失函數使用交叉熵損失函數。 ``` python lr, num_epochs = 0.001, 5 optimizer = torch.optim.Adam(net.parameters(), lr=lr) train_ch5(net, train_iter, test_iter, batch_size, optimizer, device, num_epochs) ``` 輸出: ``` training on cuda epoch 1, loss 0.0072, train acc 0.322, test acc 0.584, time 3.7 sec epoch 2, loss 0.0037, train acc 0.649, test acc 0.699, time 1.8 sec epoch 3, loss 0.0030, train acc 0.718, test acc 0.724, time 1.7 sec epoch 4, loss 0.0027, train acc 0.741, test acc 0.746, time 1.6 sec epoch 5, loss 0.0024, train acc 0.759, test acc 0.759, time 1.7 sec ``` > 注: 本節代碼在GPU和CPU上都已測試過。 ## 小結 * 卷積神經網絡就是含卷積層的網絡。 * LeNet交替使用卷積層和最大池化層后接全連接層來進行圖像分類。 ## 參考文獻 [1] LeCun, Y., Bottou, L., Bengio, Y., & Haffner, P. (1998). Gradient-based learning applied to document recognition. Proceedings of the IEEE, 86(11), 2278-2324. ----------- > 注:除代碼外本節與原書此節基本相同,[原書傳送門](https://zh.d2l.ai/chapter_convolutional-neural-networks/lenet.html)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看