PyTorch框架学习二十——模型微调(Finetune)
PyTorch框架學習二十——模型微調(Finetune)
- 一、Transfer Learning:遷移學習
- 二、Model Finetune:模型的遷移學習
- 三、看個例子:用ResNet18預訓練模型訓練一個圖片二分類任務
因為模型微調的內容沒有實際使用過,但是后面是肯定會要了解的,所以這里算是一個引子,簡單從概念上介紹一下遷移學習與模型微調,后面有時間或需要用到時再去詳細了解。
一、Transfer Learning:遷移學習
是機器學習(ML)的一項分支,主要研究源域的知識如何應用到目標域。將源域所學習到的知識應用到目標任務當中,用于提升在目標任務里模型的性能。
所以遷移學習的主要目的就是借助其他的知識提升模型性能。
詳細了解可以參考這篇綜述:《A Survey on Transfer Learning》
二、Model Finetune:模型的遷移學習
訓練一個Model,就是去更新它的權值,這里的權值可以稱為知識,從AlexNet的卷積核可視化中,我們可以看到大多數卷積核為邊緣等信息,這些信息就是AlexNet在ImageNet上學習到的知識,所以可以把權值理解為神經網絡在特定任務中學習到的知識,而這些知識可以遷移,將其遷移到新任務中,這樣就完成了一個Transfer Learning,這就是模型微調,這就是為什么稱Model Finetune為Transfer Learning,它其實是將權值認為是知識,把這些知識應用到新任務中去。
為什么要 Model Finetune?
一般來說需要模型微調的任務都有如下特點:在新任務中數據量較小,不足以訓練一個較大的Model。可以用Model Finetune的方式輔助我們在新任務中訓練一個較好的模型,讓訓練過程更快。
模型微調的步驟
一般來說,一個神經網絡模型可以分為Features Extractor和Classifer兩部分,前者用于提取特征,后者用于合理分類,通常我們習慣對Features Extractor的結構和參數進行保留,而僅修改Classifer來適應新任務。這是因為新任務的數據量太小,預訓練參數已經具有共性,不再需要改變,如果再用這些小數據訓練,可能反而過擬合。
所以步驟如下:
模型微調訓練方法
因為需要保留Features Extractor的結構和參數,提出了兩種訓練方法:
三、看個例子:用ResNet18預訓練模型訓練一個圖片二分類任務
涉及到的data:https://pan.baidu.com/s/115grxHrq6kMZBg6oC2fatg
提取碼:yld7
輸出結果為:
use device :cpu Training:Epoch[000/025] Iteration[010/016] Loss: 0.6572 Acc:60.62% epoch:0 conv1.weights[0, 0, ...] :tensor([[-0.0104, -0.0061, -0.0018, 0.0748, 0.0566, 0.0171, -0.0127],[ 0.0111, 0.0095, -0.1099, -0.2805, -0.2712, -0.1291, 0.0037],[-0.0069, 0.0591, 0.2955, 0.5872, 0.5197, 0.2563, 0.0636],[ 0.0305, -0.0670, -0.2984, -0.4387, -0.2709, -0.0006, 0.0576],[-0.0275, 0.0160, 0.0726, -0.0541, -0.3328, -0.4206, -0.2578],[ 0.0306, 0.0410, 0.0628, 0.2390, 0.4138, 0.3936, 0.1661],[-0.0137, -0.0037, -0.0241, -0.0659, -0.1507, -0.0822, -0.0058]],grad_fn=<SelectBackward>) Valid: Epoch[000/025] Iteration[010/010] Loss: 0.4565 Acc:84.97% Training:Epoch[001/025] Iteration[010/016] Loss: 0.4074 Acc:85.00% epoch:1 conv1.weights[0, 0, ...] :tensor([[-0.0104, -0.0061, -0.0018, 0.0748, 0.0566, 0.0171, -0.0127],[ 0.0111, 0.0095, -0.1099, -0.2805, -0.2712, -0.1291, 0.0037],[-0.0069, 0.0591, 0.2955, 0.5872, 0.5197, 0.2563, 0.0636],[ 0.0305, -0.0670, -0.2984, -0.4387, -0.2709, -0.0006, 0.0576],[-0.0275, 0.0160, 0.0726, -0.0541, -0.3328, -0.4206, -0.2578],[ 0.0306, 0.0410, 0.0628, 0.2390, 0.4138, 0.3936, 0.1661],[-0.0137, -0.0037, -0.0241, -0.0659, -0.1507, -0.0822, -0.0058]],grad_fn=<SelectBackward>) Valid: Epoch[001/025] Iteration[010/010] Loss: 0.2846 Acc:93.46% Training:Epoch[002/025] Iteration[010/016] Loss: 0.3542 Acc:83.12% epoch:2 conv1.weights[0, 0, ...] :tensor([[-0.0104, -0.0061, -0.0018, 0.0748, 0.0566, 0.0171, -0.0127],[ 0.0111, 0.0095, -0.1099, -0.2805, -0.2712, -0.1291, 0.0037],[-0.0069, 0.0591, 0.2955, 0.5872, 0.5197, 0.2563, 0.0636],[ 0.0305, -0.0670, -0.2984, -0.4387, -0.2709, -0.0006, 0.0576],[-0.0275, 0.0160, 0.0726, -0.0541, -0.3328, -0.4206, -0.2578],[ 0.0306, 0.0410, 0.0628, 0.2390, 0.4138, 0.3936, 0.1661],[-0.0137, -0.0037, -0.0241, -0.0659, -0.1507, -0.0822, -0.0058]],grad_fn=<SelectBackward>) Valid: Epoch[002/025] Iteration[010/010] Loss: 0.2904 Acc:89.54% Training:Epoch[003/025] Iteration[010/016] Loss: 0.2266 Acc:93.12% epoch:3 conv1.weights[0, 0, ...] :tensor([[-0.0104, -0.0061, -0.0018, 0.0748, 0.0566, 0.0171, -0.0127],[ 0.0111, 0.0095, -0.1099, -0.2805, -0.2712, -0.1291, 0.0037],[-0.0069, 0.0591, 0.2955, 0.5872, 0.5197, 0.2563, 0.0636],[ 0.0305, -0.0670, -0.2984, -0.4387, -0.2709, -0.0006, 0.0576],[-0.0275, 0.0160, 0.0726, -0.0541, -0.3328, -0.4206, -0.2578],[ 0.0306, 0.0410, 0.0628, 0.2390, 0.4138, 0.3936, 0.1661],[-0.0137, -0.0037, -0.0241, -0.0659, -0.1507, -0.0822, -0.0058]],grad_fn=<SelectBackward>) Valid: Epoch[003/025] Iteration[010/010] Loss: 0.2252 Acc:94.12% Training:Epoch[004/025] Iteration[010/016] Loss: 0.2805 Acc:87.50% epoch:4 conv1.weights[0, 0, ...] :tensor([[-0.0104, -0.0061, -0.0018, 0.0748, 0.0566, 0.0171, -0.0127],[ 0.0111, 0.0095, -0.1099, -0.2805, -0.2712, -0.1291, 0.0037],[-0.0069, 0.0591, 0.2955, 0.5872, 0.5197, 0.2563, 0.0636],[ 0.0305, -0.0670, -0.2984, -0.4387, -0.2709, -0.0006, 0.0576],[-0.0275, 0.0160, 0.0726, -0.0541, -0.3328, -0.4206, -0.2578],[ 0.0306, 0.0410, 0.0628, 0.2390, 0.4138, 0.3936, 0.1661],[-0.0137, -0.0037, -0.0241, -0.0659, -0.1507, -0.0822, -0.0058]],grad_fn=<SelectBackward>) Valid: Epoch[004/025] Iteration[010/010] Loss: 0.1953 Acc:95.42% Training:Epoch[005/025] Iteration[010/016] Loss: 0.2423 Acc:91.88% epoch:5 conv1.weights[0, 0, ...] :tensor([[-0.0104, -0.0061, -0.0018, 0.0748, 0.0566, 0.0171, -0.0127],[ 0.0111, 0.0095, -0.1099, -0.2805, -0.2712, -0.1291, 0.0037],[-0.0069, 0.0591, 0.2955, 0.5872, 0.5197, 0.2563, 0.0636],[ 0.0305, -0.0670, -0.2984, -0.4387, -0.2709, -0.0006, 0.0576],[-0.0275, 0.0160, 0.0726, -0.0541, -0.3328, -0.4206, -0.2578],[ 0.0306, 0.0410, 0.0628, 0.2390, 0.4138, 0.3936, 0.1661],[-0.0137, -0.0037, -0.0241, -0.0659, -0.1507, -0.0822, -0.0058]],grad_fn=<SelectBackward>) Valid: Epoch[005/025] Iteration[010/010] Loss: 0.2399 Acc:92.16% Training:Epoch[006/025] Iteration[010/016] Loss: 0.2455 Acc:90.00% epoch:6 conv1.weights[0, 0, ...] :tensor([[-0.0104, -0.0061, -0.0018, 0.0748, 0.0566, 0.0171, -0.0127],[ 0.0111, 0.0095, -0.1099, -0.2805, -0.2712, -0.1291, 0.0037],[-0.0069, 0.0591, 0.2955, 0.5872, 0.5197, 0.2563, 0.0636],[ 0.0305, -0.0670, -0.2984, -0.4387, -0.2709, -0.0006, 0.0576],[-0.0275, 0.0160, 0.0726, -0.0541, -0.3328, -0.4206, -0.2578],[ 0.0306, 0.0410, 0.0628, 0.2390, 0.4138, 0.3936, 0.1661],[-0.0137, -0.0037, -0.0241, -0.0659, -0.1507, -0.0822, -0.0058]],grad_fn=<SelectBackward>)可以看出,模型的訓練從一開始就有了較高的準確率,比較快速地進入了較好訓練狀態,相比于不借助其他知識的普通訓練,速度上要快很多。
而且這里是用分組參數的方法將特征提取部分的學習率設置為0,這樣就不改變特征提取部分的參數了,而將全連接層的學習率正常設置,從上面的結果也能看出特征提取部分的權值一直沒有改變(改變的是全連接層的權值,所以準確率才會提升)。
ps:這次筆記涉及的遷移學習的知識還只是基礎,以后若有需要還要更加深入。
總結
以上是生活随笔為你收集整理的PyTorch框架学习二十——模型微调(Finetune)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 应用程序利用ADO对象访问数据库
- 下一篇: MFC中如何给对话框添加背景图片