網(wǎng)絡(luò))
姓名zgx 學(xué)號******姓名和學(xué)號zgx******本實驗屬于哪門課程中國海洋大學(xué)25秋《軟件工程原理與實踐》實驗名稱實驗3卷積神經(jīng)網(wǎng)絡(luò)一、實驗內(nèi)容本次實驗中的三個實驗均來自以下鏈接實驗三https://oucaigroup.feishu.cn/wiki/ZZHiwlpZJiLuNCkpL5ScHeCTnqg實驗四https://oucaigroup.feishu.cn/wiki/TWFdw1ecwiBILikSJrecvMX4nOf實驗五https://oucaigroup.feishu.cn/wiki/UJ1xwmjVziixTckP1zFcgNgcnqc1. 實驗三MNIST數(shù)據(jù)集分類1.1 基礎(chǔ)準備這部分代碼主要是在為后面的神經(jīng)網(wǎng)絡(luò)訓(xùn)練做準備導(dǎo)入所需要的庫、定義模型參數(shù)統(tǒng)計函數(shù)、設(shè)置運行設(shè)備三部分。1.2 加載數(shù)據(jù)MNIST1.2.1 MNIST 數(shù)據(jù)集并預(yù)處理設(shè)置圖片的大小為28*28, 并設(shè)置輸出類別數(shù)100-9 并加載訓(xùn)練集和測試集。對圖片進行預(yù)處理 transforms.ToTensor()將圖片轉(zhuǎn)換成張量并將像素值縮放到0~1 通過transforms.Normalize()對像素進行標準化并用transforms.Compose()將上述操作組合起來依次執(zhí)行。1.2.2 顯示數(shù)據(jù)集中的部分圖像取出 MNIST 訓(xùn)練集中的前 20 張圖片按 4 行 5 列顯示出來。1.3 創(chuàng)建網(wǎng)絡(luò)1.3.1 構(gòu)建神經(jīng)網(wǎng)絡(luò)這部分代碼定義了兩種模型全連接神經(jīng)網(wǎng)絡(luò)首先將每張 28×28 的圖片展開為包含 784 個像素值的一維向量然后依次通過兩個隱藏層和一個輸出層引入ReLU函數(shù)進行非線性變換最后通過LogSoftmax輸出各類別的對數(shù)概率。卷積神經(jīng)網(wǎng)絡(luò)直接接收二維圖像通過兩次卷積提取圖像中的筆畫、邊緣等局部特征并在每次卷積后使用 ReLU 激活和最大池化。將大小從 28×28 逐步縮小為 4×4再將特征展開送入兩個全連接層完成分類。這部分主要是為后續(xù)訓(xùn)練和比較分類做準備。1.3.2 定義訓(xùn)練和測試函數(shù)對每批數(shù)據(jù)依次執(zhí)行梯度清零、前向傳播、損失計算、反向傳播和參數(shù)更新。損失計算采用負對數(shù)似然損失主要是用于衡量預(yù)測結(jié)果與真實標簽之間的差距。每隔 100 個批次輸出一次訓(xùn)練進度和當前批次的損失這樣也能方便觀察結(jié)果。最后是進行測試選擇每張圖片輸出值最大的類別作為預(yù)測標簽將預(yù)測標簽與真實標簽進行比較累計預(yù)測正確的數(shù)量同時累加各批次的損失。計算平均損失和分類準確率。1.4 進行訓(xùn)練1.4.1 在小型全連接網(wǎng)絡(luò)上訓(xùn)練先設(shè)置隱藏層有8個神經(jīng)元隨后調(diào)用FC2Layer創(chuàng)建全連接模型。開始進行訓(xùn)練。其中的optim.SGD()是帶動量的隨機梯度下降優(yōu)化器。有動量可以使參數(shù)更新時結(jié)合之前積累的更新方向可以更好的減少來回震蕩。1.4.2 在卷積神經(jīng)網(wǎng)絡(luò)上訓(xùn)練定義兩個卷積層各輸出 6 個特征通道利用CNN(創(chuàng)建卷積神經(jīng)網(wǎng)絡(luò)也同樣為CNN設(shè)計帶動量的隨機梯度下降優(yōu)化器。最后輸出結(jié)果通過以上對比可以發(fā)現(xiàn)含有相同參數(shù)的CNN效果要明顯優(yōu)于簡單的全連接網(wǎng)絡(luò)。主要是因為CNN中的“卷積”和“池化”可以更好的挖掘圖像中的信息幫助神經(jīng)網(wǎng)絡(luò)更精準的識別。1.5 打亂像素順序后再次在兩個網(wǎng)絡(luò)上訓(xùn)練與測試如果把圖像中的像素打亂順序“卷積”和“池化”會難以發(fā)揮作用。再次實驗觀察兩個神經(jīng)網(wǎng)絡(luò)上的結(jié)果如何。1.5.1 隨機打亂像素后圖像的形態(tài)把像素打亂就是把圖片中的28\×28784 個像素隨機打亂然后組成的圖像。1.5.2 重新定義訓(xùn)練與測試函數(shù)與之前的測試函數(shù)沒多大區(qū)別只是對數(shù)據(jù)進行了打亂順序操作。1.5.3 在小型全連接網(wǎng)絡(luò)上訓(xùn)練1.5.3 在卷積神經(jīng)網(wǎng)絡(luò)上訓(xùn)練通過兩次實驗來看全連接網(wǎng)絡(luò)的性能基本沒有發(fā)生變化但是卷積神經(jīng)網(wǎng)絡(luò)的性能明顯的下降。這主要因為卷積神經(jīng)網(wǎng)絡(luò)的核心“卷積”和“池化”需要利用像素之間的局部關(guān)系打亂之后這些像素關(guān)系就無法得到利用了也大大影響了卷積神經(jīng)網(wǎng)絡(luò)的性能。2. 實驗四CIFAR10 數(shù)據(jù)集分類2.1 基礎(chǔ)準備這部分代碼完成了模型訓(xùn)練前的數(shù)據(jù)準備工作。先導(dǎo)入所需的庫并根據(jù) GPU 是否可用選擇計算設(shè)備。隨后將圖片轉(zhuǎn)換成張量把像素值調(diào)整到 ?1 到 1 的范圍再分別加載 CIFAR-10 的訓(xùn)練集和測試集使用 DataLoader 按批次讀取數(shù)據(jù)。訓(xùn)練時打亂樣本順序測試時保持原有順序。最后定義類別名稱方便查看預(yù)測結(jié)果。展示CIFAR10 數(shù)據(jù)集里面的一些照片這里的迭代器沒有 .next() 方法需要使用 Python 內(nèi)置的 next() 函數(shù)獲取一批數(shù)據(jù)。將原語句改成images, labels next(iter(trainloader))即可2.2 定義網(wǎng)絡(luò)、損失函數(shù)和優(yōu)化器這部分代碼搭建了一個包含兩個卷積層、兩次最大池化和三個全連接層的分類網(wǎng)絡(luò)。卷積層負責(zé)提取圖片特征池化層負責(zé)縮小特征圖、減少計算量全連接層則綜合這些特征輸出十個類別的得分。圖片經(jīng)過卷積和池化后每張得到 16 張大小為 5×5 的特征圖需要先展開成 400 個特征值再送入全連接層。最后代碼將模型放到指定設(shè)備上并設(shè)置交叉熵損失函數(shù)和 Adam 優(yōu)化器為后續(xù)計算損失和更新參數(shù)做好準備。2.3 訓(xùn)練網(wǎng)絡(luò)這部分代碼實現(xiàn)了模型的訓(xùn)練過程共訓(xùn)練 10 輪每輪按批次讀取訓(xùn)練圖片和真實標簽。每個批次先清空之前的梯度再將圖片輸入模型計算預(yù)測結(jié)果與真實標簽之間的損失隨后通過反向傳播計算梯度由優(yōu)化器更新模型參數(shù)。反向傳播負責(zé)計算梯度而優(yōu)化器負責(zé)真正調(diào)整參數(shù)兩者共同完成模型的學(xué)習(xí)。訓(xùn)練過程中還會定期輸出當前批次的損失方便觀察訓(xùn)練進度和損失變化。2.4 訓(xùn)練結(jié)果從測試集中取出8張圖片這部分也會報錯解決方法同2.1中的圖片展示方法把圖片輸入模型看看CNN把這些圖片識別成了什么可以看出有部分圖片識別錯了。網(wǎng)絡(luò)在整個數(shù)據(jù)集上的表現(xiàn)3. 實驗五VGG16對CIFAR10分類3.1 定義dataloader這部分代碼在原有的數(shù)據(jù)加載流程中加入了數(shù)據(jù)增強并分別設(shè)置訓(xùn)練集和測試集的預(yù)處理方式。訓(xùn)練圖片經(jīng)過隨機裁剪和水平翻轉(zhuǎn)后同一張圖片在不同輪次中可能呈現(xiàn)不同的位置和朝向有助于模型適應(yīng)圖片的變化。測試圖片只進行張量轉(zhuǎn)換和標準化保證評估過程穩(wěn)定。同時代碼調(diào)整了各通道的標準化參數(shù)并將訓(xùn)練和測試的批次大小都設(shè)為 128。也就是 transform 負責(zé)處理單張圖片而 DataLoader 負責(zé)把圖片和標簽組織成批次兩者共同為模型提供訓(xùn)練和測試數(shù)據(jù)。3.2 VGG網(wǎng)絡(luò)定義模型實現(xiàn)代碼這部分代碼通過配置列表搭建了一個 VGG 風(fēng)格的卷積神經(jīng)網(wǎng)絡(luò)列表中的數(shù)字表示卷積層的輸出通道數(shù)M 表示最大池化。相比之前的簡單網(wǎng)絡(luò)它增加了卷積層和通道數(shù)并在每個卷積層后加入批量歸一化和 ReLU以提取更豐富的特征并幫助穩(wěn)定訓(xùn)練。圖片經(jīng)過五次池化后由 32×32 縮小到 1×1最終得到 512 個特征再通過全連接層輸出十個類別的得分。代碼中需要修改一下語句self.features self._make_layers(self.cfg)否則會導(dǎo)致變量名不一致。代碼中需要修改一下語句self.classifier nn.Linear(512, 10)將2048改為512適配后續(xù)的代碼參數(shù)否則無法運行成功。初始化一些參數(shù)使用交叉熵損失函數(shù)衡量預(yù)測結(jié)果與真實標簽之間的差距再設(shè)置學(xué)習(xí)率為 0.001 的 Adam 優(yōu)化器用于后續(xù)更新模型參數(shù)。對比之下?lián)p失函數(shù)和優(yōu)化方式是保持不變的。3.3 網(wǎng)絡(luò)訓(xùn)練訓(xùn)練的代碼和之前完全一樣3.4 測試驗證準確率測試代碼也與之前完全一樣根據(jù)結(jié)果可以發(fā)現(xiàn)一個簡化版的VGG網(wǎng)絡(luò)就可以將準確率從63%大幅度提升到82.79%二、問題總結(jié)與體會1. DataLoader 中shuffle 取不同值有什么區(qū)別shuffle決定讀取樣本時是否打亂順序。shuffleTrue每輪訓(xùn)練重新打亂樣本順序使不同 batch 的樣本組合發(fā)生變化減少固定排列順序?qū)τ?xùn)練的影響。shuffleFalse按數(shù)據(jù)集原有順序讀取每輪的樣本順序基本一致。訓(xùn)練集通常設(shè)為True測試集通常設(shè)為False。訓(xùn)練時打亂數(shù)據(jù)有助于模型學(xué)習(xí)測試時不更新參數(shù)一般不需要打亂也方便對應(yīng)預(yù)測結(jié)果和原始樣本。2. transform 中取不同值有什么區(qū)別Normalize(mean, std)是按通道調(diào)整像素數(shù)值改變輸入數(shù)據(jù)的中心位置和數(shù)值尺度。其計算公式為x′x?meanstd x\frac{x-\text{mean}}{\text{std}}x′stdx?mean?例如Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))中兩組數(shù)分別對應(yīng) RGB 三個通道的均值參數(shù)和標準差參數(shù)。輸入已經(jīng)在[0,1]時變換后落在[-1,1]。這不代表處理后的實際均值一定為 0、標準差一定為 1。只有使用數(shù)據(jù)本身的相應(yīng)統(tǒng)計量才有這樣的標準化效果。3. epoch 和 batch 的區(qū)別是什么batch一次送入模型的一批樣本。batch size這一批包含多少個樣本。epoch整個訓(xùn)練集被完整訓(xùn)練一遍。例如訓(xùn)練集有 50,000 張圖片batch_size100那么1 個 epoch500 個 batch 1\text{ 個 epoch}500\text{ 個 batch}1個epoch500個batch通常每處理一個 batch就進行一次前向傳播、損失計算、反向傳播和參數(shù)更新。因此訓(xùn)練 10 個 epoch通常會更新參數(shù) 5,000 次。4. 1×1 卷積和 FC 有什么區(qū)別主要起什么作用1×1 卷積雖然只覆蓋一個空間位置但會使用該位置的所有輸入通道對這些通道進行加權(quán)組合。例如輸入為64×32×32使用 16 個 1×1 卷積核步長為 1、不填充時輸出為64×32×32→16×32×32 64\times32\times32\rightarrow16\times32\times3264×32×32→16×32×32空間尺寸不變通道數(shù)由 64 變成 16。對比項1×1 卷積展平后的全連接層 FC處理范圍每個空間位置上的所有通道展平后的全部輸入特征空間結(jié)構(gòu)保留二維位置結(jié)構(gòu)通常輸出一個特征向量參數(shù)共享不同空間位置使用同一組權(quán)重不同輸入位置通常使用不同權(quán)重常見作用通道融合、升降維、殘差分支對齊綜合全部特征輸出分類得分1×1 卷積主要有三個用途調(diào)整通道數(shù)使特征符合后續(xù)網(wǎng)絡(luò)的輸入要求。融合不同通道的信息學(xué)習(xí)新的特征組合。先降低通道數(shù)再進行較大的卷積減少后續(xù)計算量。它本身仍是線性變換接上 ReLU 等激活函數(shù)后才能引入非線性。5. Residual Learning 為什么能夠提升準確率普通網(wǎng)絡(luò)直接學(xué)習(xí)目標映射 H(x)殘差學(xué)習(xí)則讓網(wǎng)絡(luò)學(xué)習(xí)F(x)H(x)?x F(x)H(x)-xF(x)H(x)?x最后通過跳躍連接得到y(tǒng)F(x)x yF(x)xyF(x)x也就是保留輸入特征再學(xué)習(xí)需要補充或修正的部分。它主要解決深層網(wǎng)絡(luò)難以訓(xùn)練的問題保留原有信息。輸入可以通過跳躍連接直接傳到后面不必完全依賴多層變換。方便梯度傳播。反向傳播多了一條直接路徑有助于減輕深層網(wǎng)絡(luò)的梯度傳播困難。緩解網(wǎng)絡(luò)退化。如果新增的層暫時學(xué)不到有效改進可以讓殘差接近 0使整個模塊接近恒等映射避免新增層必須重新學(xué)會“保留輸入”。因此殘差結(jié)構(gòu)使更深的網(wǎng)絡(luò)更容易優(yōu)化從而有機會學(xué)到更有效的特征并提高準確率。6. 代碼練習(xí)二中的網(wǎng)絡(luò)與 LeNet 有什么區(qū)別代碼練習(xí)二采用的是 LeNet 風(fēng)格的卷積神經(jīng)網(wǎng)絡(luò)由兩層卷積、兩次最大池化和三層全連接組成用于 CIFAR-10 圖像分類。輸入圖片為三通道的 32×32 彩色圖像數(shù)據(jù)在網(wǎng)絡(luò)中的變化如下表中省略 batch 維度網(wǎng)絡(luò)操作輸出形狀輸入圖片3×32×32第一層 5×5 卷積接 ReLU6×28×28第一次 2×2 最大池化6×14×14第二層 5×5 卷積接 ReLU16×10×10$第二次 2×2 最大池化16×5×516×5×516×5×5展平400第一層全連接接 ReLU120第二層全連接接 ReLU84第三層全連接10兩者的共同點是采用局部連接和卷積權(quán)重共享來提取圖像特征再通過后續(xù)網(wǎng)絡(luò)完成分類。它們都能直接從圖像中學(xué)習(xí)特征不需要手工設(shè)計特征。主要區(qū)別如下激活函數(shù)不同。早期網(wǎng)絡(luò)使用 sigmoid 類的平滑飽和激活函數(shù)本實驗在兩層卷積和前兩層全連接之后使用 ReLU。ReLU 計算簡單正值區(qū)域不會因激活函數(shù)飽和而使梯度趨近于零有利于訓(xùn)練。下采樣方式不同。本實驗明確使用MaxPool2d(2, 2)每次取局部區(qū)域的最大值使特征圖的高、寬減半。1989 年網(wǎng)絡(luò)的下采樣由其局部連接和步長設(shè)計實現(xiàn)不能直接理解為本代碼中的獨立最大池化層。具體層結(jié)構(gòu)和參數(shù)配置不同。本實驗的卷積通道數(shù)為3→6→16全連接層為400→120→84→10。它沿用了 LeNet 系列的設(shè)計思路但不是對 1989 年網(wǎng)絡(luò)結(jié)構(gòu)的原樣復(fù)現(xiàn)。訓(xùn)練配置不同。本實驗使用交叉熵損失和 Adam 優(yōu)化器學(xué)習(xí)率為0.001。最后一層直接輸出 10 個類別的原始得分由CrossEntropyLoss完成相應(yīng)計算因此不需要在網(wǎng)絡(luò)末尾額外添加 Softmax。7. 卷積后 feature map 尺寸變小如何應(yīng)用 Residual Learning關(guān)鍵要求是參與相加的兩個張量必須具有相同的形狀包括通道數(shù)、高和寬。尺寸一致時可以直接相加yF(x)x yF(x)xyF(x)x尺寸不一致時需要先調(diào)整捷徑分支yF(x)P(x) yF(x)P(x)yF(x)P(x)其中P(x) 是用于匹配形狀的變換。情況處理方法高、寬不變通道數(shù)改變用 1×1 卷積調(diào)整通道數(shù)高、寬縮小例如減半用帶步長的 1×1 卷積同時調(diào)整空間尺寸和通道數(shù)因未填充卷積而縮小如32→28可修改主分支的 padding 保持尺寸或?qū)輳椒种нM行匹配的裁剪等處理例如主分支把輸入從64×32×32變成128×16×16捷徑分支可以使用nn.Conv2d(64, 128, kernel_size1, stride2)。這樣兩條分支的輸出都是128×16×16可以逐元素相加。8. 有什么方法可以進一步提升準確率可以從以下方面改進方法具體做法與目的數(shù)據(jù)增強訓(xùn)練時加入適度的隨機裁剪、水平翻轉(zhuǎn)減少對固定圖像形式的依賴調(diào)整學(xué)習(xí)率前期使用合適的學(xué)習(xí)率后期逐步降低讓參數(shù)調(diào)整更細調(diào)整訓(xùn)練輪數(shù)訓(xùn)練不足時增加 epoch出現(xiàn)過擬合時不再單純延長訓(xùn)練改進網(wǎng)絡(luò)結(jié)構(gòu)適當增加卷積通道或深度引入殘差連接提高特征提取能力加入 BatchNorm改善網(wǎng)絡(luò)的訓(xùn)練穩(wěn)定性控制過擬合使用權(quán)重衰減、適當?shù)?Dropout 或早停檢查數(shù)據(jù)處理確保標簽正確、標準化一致測試時調(diào)用model.eval()首先應(yīng)同時觀察訓(xùn)練集和驗證集的損失、準確率再決定調(diào)整方向訓(xùn)練集和驗證集都表現(xiàn)不好重點檢查是否訓(xùn)練不足、學(xué)習(xí)率不合適或模型能力不足。訓(xùn)練集很好驗證集明顯較差重點考慮過擬合增加數(shù)據(jù)增強和正則化。訓(xùn)練過程中損失反復(fù)大幅波動優(yōu)先檢查學(xué)習(xí)率和輸入數(shù)據(jù)。心得體會通過本次實驗我學(xué)會了在 Colab 中使用 PyTorch 完成 MNIST 和 CIFAR-10 圖像分類熟悉了數(shù)據(jù)預(yù)處理、模型搭建、訓(xùn)練和測試的基本過程也弄清了卷積層、池化層和全連接層各自的作用對圖片如何經(jīng)過網(wǎng)絡(luò)得到分類結(jié)果有了更具體的認識。通過簡單卷積網(wǎng)絡(luò)和 VGG 網(wǎng)絡(luò)的對比我進一步理解了不同網(wǎng)絡(luò)結(jié)構(gòu)在特征提取方式上的差異。同時也認識到圖像分類效果不僅與網(wǎng)絡(luò)結(jié)構(gòu)有關(guān)數(shù)據(jù)增強、學(xué)習(xí)率和訓(xùn)練輪數(shù)等設(shè)置也會影響結(jié)果不能只靠增加網(wǎng)絡(luò)層數(shù)來提高準確率。這次實驗讓我逐漸能夠把代碼中的操作與所學(xué)原理聯(lián)系起來對卷積神經(jīng)網(wǎng)絡(luò)有了更清楚的理解也學(xué)會了在遇到維度不匹配等問題時沿著數(shù)據(jù)在網(wǎng)絡(luò)中的變化過程查找原因。