運(yùn)城網(wǎng)站建設(shè)公司有多少錢愛站網(wǎng)seo
在前面的文章中,我們介紹了如何使用 Keras 構(gòu)建和訓(xùn)練全連接神經(jīng)網(wǎng)絡(luò)(MLP)、卷積神經(jīng)網(wǎng)絡(luò)(CNN)和循環(huán)神經(jīng)網(wǎng)絡(luò)(RNN)。本文將帶你深入學(xué)習(xí)如何使用 遷移學(xué)習(xí)(Transfer Learning) 來加速和提升模型性能。我們將使用 Keras 和預(yù)訓(xùn)練的卷積神經(jīng)網(wǎng)絡(luò)(如 VGG16)來完成一個圖像分類任務(wù)。
目錄
- 什么是遷移學(xué)習(xí)
- 環(huán)境準(zhǔn)備
- 導(dǎo)入必要的庫
- 加載和預(yù)處理數(shù)據(jù)
- 加載預(yù)訓(xùn)練模型
- 構(gòu)建遷移學(xué)習(xí)模型
- 編譯模型
- 訓(xùn)練模型
- 評估模型
- 保存和加載模型
- 總結(jié)
1. 什么是遷移學(xué)習(xí)
遷移學(xué)習(xí) 是一種機(jī)器學(xué)習(xí)技術(shù),它利用在一個任務(wù)上訓(xùn)練的模型來解決另一個相關(guān)任務(wù)。通過遷移學(xué)習(xí),我們可以:
- 加速訓(xùn)練: 利用預(yù)訓(xùn)練模型的特征提取能力,減少訓(xùn)練時間。
- 提高性能: 在數(shù)據(jù)量有限的情況下,遷移學(xué)習(xí)可以顯著提高模型的泛化能力。
- 減少數(shù)據(jù)需求: 預(yù)訓(xùn)練模型已經(jīng)在大規(guī)模數(shù)據(jù)集上訓(xùn)練過,可以減少對新數(shù)據(jù)的需求。
在圖像分類任務(wù)中,遷移學(xué)習(xí)通常涉及使用在 ImageNet 等大型數(shù)據(jù)集上預(yù)訓(xùn)練的卷積神經(jīng)網(wǎng)絡(luò)(如 VGG16、ResNet、Inception 等),并將其應(yīng)用到新的圖像分類任務(wù)中。
2. 環(huán)境準(zhǔn)備
確保你已經(jīng)安裝了 Python(推薦 3.6 及以上版本)和 TensorFlow(Keras 已集成在 TensorFlow 中)。如果尚未安裝,請運(yùn)行以下命令:
pip install tensorflow
3. 導(dǎo)入必要的庫
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers, models, applications
from tensorflow.keras.preprocessing.image import ImageDataGenerator
import matplotlib.pyplot as plt
import numpy as np
- tensorflow: 深度學(xué)習(xí)框架,Keras 已集成其中。
- ImageDataGenerator: 用于數(shù)據(jù)增強(qiáng)和預(yù)處理。
- applications: 預(yù)訓(xùn)練模型模塊,包含 VGG16、ResNet 等。
4. 加載和預(yù)處理數(shù)據(jù)
我們將使用 貓狗數(shù)據(jù)集(Cats vs Dogs),這是一個二分類圖像數(shù)據(jù)集,包含 25,000 張貓和狗的圖片。我們將使用 Keras 的 ImageDataGenerator
進(jìn)行數(shù)據(jù)增強(qiáng)和預(yù)處理。
# 數(shù)據(jù)集路徑
train_dir = 'data/train'
validation_dir = 'data/validation'# 圖像參數(shù)
img_height, img_width = 150, 150
batch_size = 32# 訓(xùn)練數(shù)據(jù)生成器(數(shù)據(jù)增強(qiáng))
train_datagen = ImageDataGenerator(rescale=1./255, # 歸一化rotation_range=40, # 隨機(jī)旋轉(zhuǎn)width_shift_range=0.2, # 隨機(jī)水平平移height_shift_range=0.2, # 隨機(jī)垂直平移shear_range=0.2, # 隨機(jī)剪切zoom_range=0.2, # 隨機(jī)縮放horizontal_flip=True, # 隨機(jī)水平翻轉(zhuǎn)fill_mode='nearest' # 填充方式
)# 測試數(shù)據(jù)生成器(僅歸一化)
test_datagen = ImageDataGenerator(rescale=1./255)# 加載訓(xùn)練數(shù)據(jù)
train_generator = train_datagen.flow_from_directory(train_dir,target_size=(img_height, img_width),batch_size=batch_size,class_mode='binary' # 二分類
)# 加載驗(yàn)證數(shù)據(jù)
validation_generator = test_datagen.flow_from_directory(validation_dir,target_size=(img_height, img_width),batch_size=batch_size,class_mode='binary'
)
說明:
- 使用
ImageDataGenerator
進(jìn)行數(shù)據(jù)增強(qiáng),可以提高模型的泛化能力。 flow_from_directory
方法從目錄中加載數(shù)據(jù),目錄結(jié)構(gòu)應(yīng)為train_dir/class1/
和train_dir/class2/
。
5. 加載預(yù)訓(xùn)練模型
我們將使用預(yù)訓(xùn)練的 VGG16 模型,并凍結(jié)其卷積基(convolutional base),只訓(xùn)練頂部的全連接層。
# 加載預(yù)訓(xùn)練的 VGG16 模型,不包括頂部的全連接層
conv_base = applications.VGG16(weights='imagenet',include_top=False,input_shape=(img_height, img_width, 3))# 凍結(jié)卷積基
conv_base.trainable = False# 查看模型結(jié)構(gòu)
conv_base.summary()
說明:
weights='imagenet'
: 使用在 ImageNet 數(shù)據(jù)集上預(yù)訓(xùn)練的權(quán)重。include_top=False
: 不包括頂部的全連接層,以便我們添加自己的分類器。conv_base.trainable = False
: 凍結(jié)卷積基,防止其權(quán)重在訓(xùn)練過程中被更新。
6. 構(gòu)建遷移學(xué)習(xí)模型
我們將添加自己的全連接層來進(jìn)行分類。
model = models.Sequential([conv_base, # 預(yù)訓(xùn)練的卷積基layers.Flatten(), # 展平層layers.Dense(256, activation='relu'), # 全連接層layers.Dropout(0.5), # Dropout 層,防止過擬合layers.Dense(1, activation='sigmoid') # 輸出層,二分類
])# 查看模型結(jié)構(gòu)
model.summary()
說明:
- 添加
Flatten
層將多維輸出展平。 - 添加
Dense
層和Dropout
層進(jìn)行分類。 - 輸出層使用
sigmoid
激活函數(shù)進(jìn)行二分類。
7. 編譯模型
model.compile(optimizer=keras.optimizers.Adam(),loss='binary_crossentropy',metrics=['accuracy'])
說明:
- 使用 Adam 優(yōu)化器和二元交叉熵?fù)p失函數(shù)。
- 評估指標(biāo)為準(zhǔn)確率。
8. 訓(xùn)練模型
# 設(shè)置訓(xùn)練參數(shù)
epochs = 10# 訓(xùn)練模型
history = model.fit(train_generator,steps_per_epoch=train_generator.samples // batch_size,epochs=epochs,validation_data=validation_generator,validation_steps=validation_generator.samples // batch_size
)
說明:
steps_per_epoch
: 每個 epoch 的步數(shù),通常為訓(xùn)練樣本數(shù)除以批量大小。validation_steps
: 每個 epoch 的驗(yàn)證步數(shù),通常為驗(yàn)證樣本數(shù)除以批量大小。
9. 評估模型
test_loss, test_acc = model.evaluate(validation_generator, steps=validation_generator.samples // batch_size)
print(f"\n測試準(zhǔn)確率: {test_acc:.4f}")
10. 保存和加載模型
# 保存模型
model.save("cats_vs_dogs_transfer_learning.h5")# 加載模型
new_model = keras.models.load_model("cats_vs_dogs_transfer_learning.h5")
11. 可視化訓(xùn)練過程
# 繪制訓(xùn)練 & 驗(yàn)證的準(zhǔn)確率和損失值
plt.figure(figsize=(12,4))# 準(zhǔn)確率
plt.subplot(1,2,1)
plt.plot(history.history['accuracy'], label='訓(xùn)練準(zhǔn)確率')
plt.plot(history.history['val_accuracy'], label='驗(yàn)證準(zhǔn)確率')
plt.xlabel('Epoch')
plt.ylabel('準(zhǔn)確率')
plt.legend(loc='lower right')
plt.title('訓(xùn)練與驗(yàn)證準(zhǔn)確率')# 損失值
plt.subplot(1,2,2)
plt.plot(history.history['loss'], label='訓(xùn)練損失')
plt.plot(history.history['val_loss'], label='驗(yàn)證損失')
plt.xlabel('Epoch')
plt.ylabel('損失')
plt.legend(loc='upper right')
plt.title('訓(xùn)練與驗(yàn)證損失')plt.show()
12. 解凍部分卷積基進(jìn)行微調(diào)
為了進(jìn)一步提高模型性能,可以解凍部分卷積基,進(jìn)行微調(diào)。
# 解凍最后幾個卷積層
conv_base.trainable = True# 查看可訓(xùn)練的參數(shù)
for layer in conv_base.layers:if layer.name == 'block5_conv1':breaklayer.trainable = False# 重新編譯模型
model.compile(optimizer=keras.optimizers.Adam(1e-5), # 使用較低的學(xué)習(xí)率loss='binary_crossentropy',metrics=['accuracy'])# 繼續(xù)訓(xùn)練模型
history_fine = model.fit(train_generator,steps_per_epoch=train_generator.samples // batch_size,epochs=5,validation_data=validation_generator,validation_steps=validation_generator.samples // batch_size
)
說明:
- 解凍部分卷積層,并使用較低的學(xué)習(xí)率進(jìn)行微調(diào)。
- 繼續(xù)訓(xùn)練模型以微調(diào)預(yù)訓(xùn)練模型的權(quán)重。
13. 課程回顧
本文其實(shí)不算什么知識點(diǎn),只是利用遷移學(xué)習(xí)來加速訓(xùn)練的一個實(shí)際操作的例子。
作者簡介
前騰訊電子簽的前端負(fù)責(zé)人,現(xiàn) whentimes tech CTO,專注于前端技術(shù)的大咖一枚!一路走來,從小屏到大屏,從 Web 到移動,什么前端難題都見過。熱衷于用技術(shù)打磨產(chǎn)品,帶領(lǐng)團(tuán)隊(duì)把復(fù)雜的事情做到極簡,體驗(yàn)做到極致。喜歡探索新技術(shù),也愛分享一些實(shí)戰(zhàn)經(jīng)驗(yàn),幫助大家少走彎路!
溫馨提示:可搜老碼小張公號聯(lián)系導(dǎo)師