運城網(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í) 是一種機器學(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 中)。如果尚未安裝,請運行以下命令:
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ù)增強和預(yù)處理。
- applications: 預(yù)訓(xùn)練模型模塊,包含 VGG16、ResNet 等。
4. 加載和預(yù)處理數(shù)據(jù)
我們將使用 貓狗數(shù)據(jù)集(Cats vs Dogs),這是一個二分類圖像數(shù)據(jù)集,包含 25,000 張貓和狗的圖片。我們將使用 Keras 的 ImageDataGenerator
進行數(shù)據(jù)增強和預(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ù)增強)
train_datagen = ImageDataGenerator(rescale=1./255, # 歸一化rotation_range=40, # 隨機旋轉(zhuǎn)width_shift_range=0.2, # 隨機水平平移height_shift_range=0.2, # 隨機垂直平移shear_range=0.2, # 隨機剪切zoom_range=0.2, # 隨機縮放horizontal_flip=True, # 隨機水平翻轉(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' # 二分類
)# 加載驗證數(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
進行數(shù)據(jù)增強,可以提高模型的泛化能力。 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í)模型
我們將添加自己的全連接層來進行分類。
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
層進行分類。 - 輸出層使用
sigmoid
激活函數(shù)進行二分類。
7. 編譯模型
model.compile(optimizer=keras.optimizers.Adam(),loss='binary_crossentropy',metrics=['accuracy'])
說明:
- 使用 Adam 優(yōu)化器和二元交叉熵損失函數(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 的驗證步數(shù),通常為驗證樣本數(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)練 & 驗證的準(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='驗證準(zhǔn)確率')
plt.xlabel('Epoch')
plt.ylabel('準(zhǔn)確率')
plt.legend(loc='lower right')
plt.title('訓(xùn)練與驗證準(zhǔn)確率')# 損失值
plt.subplot(1,2,2)
plt.plot(history.history['loss'], label='訓(xùn)練損失')
plt.plot(history.history['val_loss'], label='驗證損失')
plt.xlabel('Epoch')
plt.ylabel('損失')
plt.legend(loc='upper right')
plt.title('訓(xùn)練與驗證損失')plt.show()
12. 解凍部分卷積基進行微調(diào)
為了進一步提高模型性能,可以解凍部分卷積基,進行微調(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í)率進行微調(diào)。
- 繼續(xù)訓(xùn)練模型以微調(diào)預(yù)訓(xùn)練模型的權(quán)重。
13. 課程回顧
本文其實不算什么知識點,只是利用遷移學(xué)習(xí)來加速訓(xùn)練的一個實際操作的例子。
作者簡介
前騰訊電子簽的前端負責(zé)人,現(xiàn) whentimes tech CTO,專注于前端技術(shù)的大咖一枚!一路走來,從小屏到大屏,從 Web 到移動,什么前端難題都見過。熱衷于用技術(shù)打磨產(chǎn)品,帶領(lǐng)團隊把復(fù)雜的事情做到極簡,體驗做到極致。喜歡探索新技術(shù),也愛分享一些實戰(zhàn)經(jīng)驗,幫助大家少走彎路!
溫馨提示:可搜老碼小張公號聯(lián)系導(dǎo)師