最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

深度學習Tensorflow?2.4?完成遷移學習和模型微調

 更新時間:2023年01月06日 16:44:14   作者:我是王大你是誰  
這篇文章主要為大家介紹了深度學習Tensorflow?2.4?完成遷移學習和模型微調,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

前言

本文使用 cpu 的 tensorflow 2.4 完成遷移學習和模型微調,并使用訓練好的模型完成貓狗圖片分類任務。

預訓練模型在 NLP 中最常見的可能就是 BERT 了,在 CV 中我們此次用到了 MobileNetV2 ,它也是一個輕量化預訓練模型,它已經經過大量的圖片分類任務的訓練,里面保存了一個可以通用的去捕獲圖片特征的模型網絡結構,其可以通用地提取出圖片的有意義特征。這些特征捕獲功能可以輕松遷移到其他圖片任務上幫助其完成特征提取工作。

本文的工作,就是在 MobileNetV2 基礎上加入我們自定義的若干網絡層,通過使用大量的貓狗數據先對新添加的分類器層進行遷移學習,然后結合基礎模型的最后幾層與我們的自定義分類器一起進行微調訓練,就可以輕松獲得一個效果很好的貓狗圖片分類模型,而不必基于大量數據集從頭開始訓練一個大型模型,這樣會很耗時間。

實現過程

1. 獲取數據

首先我們要使用 tensorflow 的內置函數,從網絡上下載貓狗圖片集,訓練數據中的貓、狗圖片各 1000 張,驗證數據中的貓、狗圖片各 500 張。每張圖片的大小都是(160, 160, 3),每個 batch 中有 32 張圖片。

import matplotlib.pyplot as plt
import numpy as np
import os
import tensorflow as tf
URL = 'https://storage.googleapis.com/mledu-datasets/cats_and_dogs_filtered.zip'
BATCH_SIZE = 32
IMG_SIZE = (160, 160)
path_to_zip = tf.keras.utils.get_file('cats_and_dogs.zip', origin=URL, extract=True)
PATH = os.path.join(os.path.dirname(path_to_zip), 'cats_and_dogs_filtered')
train_dir = os.path.join(PATH, 'train')
validation_dir = os.path.join(PATH, 'validation')
train_dataset = tf.keras.utils.image_dataset_from_directory(train_dir, shuffle=True, batch_size=BATCH_SIZE, image_size=IMG_SIZE)
validation_dataset = tf.keras.utils.image_dataset_from_directory(validation_dir, shuffle=True, batch_size=BATCH_SIZE, image_size=IMG_SIZE)
class_names = train_dataset.class_names

在這里我們挑選了部分圖片和標簽進行展示。

plt.figure(figsize=(10, 10))
for images, labels in train_dataset.take(1):
    for i in range(3):
        ax = plt.subplot(3, 3, i + 1)
        plt.imshow(images[i].numpy().astype("uint8"))
        plt.title(class_names[labels[i]])
        plt.axis("off")     

2. 數據擴充與數據縮放

(1)由于我們沒有測試集數據,使用 tf.data.experimental.cardinality 確定驗證集中有多少個 batch 的數據,然后將其中的 20% 的 batch 編程測試集。

val_batches = tf.data.experimental.cardinality(validation_dataset)
test_dataset = validation_dataset.take(val_batches // 5)
validation_dataset = validation_dataset.skip(val_batches // 5)

(2)為了保證在加載數據的時候不會出現 I/O 不會阻塞,我們在從磁盤加載完數據之后,使用 cache 會將數據保存在內存中,確保在訓練模型過程中數據的獲取不會成為訓練速度的瓶頸。如果說要保存的數據量太大,可以使用 cache 創(chuàng)建磁盤緩存提高數據的讀取效率。另外我們還使用 prefetch 在訓練過程中可以并行執(zhí)行數據的預獲取。

AUTOTUNE = tf.data.AUTOTUNE
train_dataset = train_dataset.prefetch(buffer_size=AUTOTUNE)
validation_dataset = validation_dataset.prefetch(buffer_size=AUTOTUNE)
test_dataset = test_dataset.prefetch(buffer_size=AUTOTUNE)

(3)因為我們沒有大量的圖片數據,我們將現有的圖片數據進行旋轉或者翻轉操作可以增加樣本的多樣性,這樣也有助于減少過擬合現象。RandomFlip 函數將根據 mode 屬性將圖片進行水平或垂直翻轉圖像。"可選的有 "horizontal" 、 "vertical" 或 "horizontal_and_vertical" 。"horizontal" 是左右翻轉, "vertical" 是上下翻轉。RandomRotation 函數通過設置 factor 來講圖片進行旋轉,假如 factor=0.2 會將圖片在 [-20% * 2pi, 20% * 2pi] 范圍內隨機旋轉。

data_augmentation = tf.keras.Sequential([
  tf.keras.layers.RandomFlip('horizontal'),
  tf.keras.layers.RandomRotation(0.1),
])	

我們這里將隨便使用一張圖片,使用數據增強的方法對其進行變化,第一張圖是原圖,其他的都是進行了變化的圖片

for image, _ in train_dataset.take(1):
    plt.figure(figsize=(10, 10))
    first_image = image[0]
    for i in range(3):
        if  i==0:
            ax = plt.subplot(3, 3, i + 1)
            plt.imshow(first_image/ 255)
            plt.axis('off')
        else:
            ax = plt.subplot(3, 3, i + 1)
            augmented_image = data_augmentation(tf.expand_dims(first_image, 0))
            plt.imshow(augmented_image[0] / 255)
            plt.axis('off')

(4)由于 MobileNetV2 模型的輸入值范圍是在 [-1, 1] 范圍內,但此時我們的圖片數據中的像素值處于 [0, 255] 范圍內,所以要重新縮放這些像素值, Rescaling 函數可以實現該操作。如果將 [0, 255] 范圍的輸入縮放到 [0, 1] 的范圍,我們可以通過設置參數 scale=1./255 來實現。如果將 [0, 255] 范圍內的輸入縮放到 [-1, 1] 范圍內,我們可以通過設置參數 scale=1./127.5, offset=-1 來實現。

rescale = tf.keras.layers.Rescaling(1./127.5, offset=-1)	

3. 遷移學習

(1)我們將 MobileNet V2 模型當做一個基礎模型,此模型已基于 ImageNet 數據集進行完美的預訓練,一般來說最后一層就是一個分類器,我們選擇將在 MobileNet V2 的倒數第二個網絡層上搭建自己的分類器,與最后一層相比倒數第二層能夠保留更豐富的圖片特征。在實際操作中我們實例化 MobileNetV2 模型,通過指定 include_top=False 參數,可以加載不包括最頂層的整個預訓練網絡結果。 該模型的作用就是將(160,160,3)大小的圖片轉換為(5,5,1280)的特征輸出。

(2)第一層是將我們的訓練數據都進行數據增強操作,也就是隨機的翻轉和旋轉。

(3)第二層是接收輸入為 (160,160,3)大小的圖片的輸入層。

(4)第三層是我們直接拿來用的 MobileNetV2 ,因為我們要直接使用基礎模型的圖片特征提取能力,所以為了在訓練過程中其權重不發(fā)生變化,我們將基礎模型中的權重參數都凍結。

(5)第四層是一個池化層,可以將每個 batch 從 (32,5,5,1280) 壓縮為 (32,1280) 大小的輸出。

(6)第五層是 Dropout ,防止過擬合。

(7)第六層是對該圖片一個預測值,也就是 logit 。如果是正數預測標簽 1 ,如果是負數預測標簽 0 。

(8)我們從模型的 summary 中可以看到,此時我們的模型中的 2259265 個參數被凍結,只有 1281 個參數是可以訓練的,它們是分屬兩個變量的可訓練參數,即最后一個全連接層即權重 1280 個可訓練參數和偏差 1 個可訓練參數。

IMG_SHAPE = IMG_SIZE + (3,)
inputs = tf.keras.Input(shape=(160, 160, 3))
x = data_augmentation(inputs)
x = tf.keras.applications.mobilenet_v2.preprocess_input(x)
base_model = tf.keras.applications.MobileNetV2(input_shape=IMG_SHAPE, include_top=False, weights='imagenet')
base_model.trainable = False
x = base_model(x, training=False)
x = tf.keras.layers.GlobalAveragePooling2D()(x)
x = tf.keras.layers.Dropout(0.2)(x)
outputs = tf.keras.layers.Dense(1)(x)
model = tf.keras.Model(inputs, outputs)
model.summary()

模型結構如下:

Model: "model_2"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 input_8 (InputLayer)        [(None, 160, 160, 3)]     0         
 sequential_2 (Sequential)   (None, 160, 160, 3)       0         
 tf.math.truediv_3 (TFOpLamb  (None, 160, 160, 3)      0         
 da)                                                             
 tf.math.subtract_3 (TFOpLam  (None, 160, 160, 3)      0         
 bda)                                                            
 mobilenetv2_1.00_160 (Funct  (None, 5, 5, 1280)       2257984   
 ional)                                                          
 global_average_pooling2d_3   (None, 1280)             0         
 (GlobalAveragePooling2D)                                        
 dropout_2 (Dropout)         (None, 1280)              0         
 dense_2 (Dense)             (None, 1)                 1281      
=================================================================
Total params: 2,259,265
Trainable params: 1,281
Non-trainable params: 2,257,984

可以看到模型中的可訓練的 2 個變量:

model.trainable_variables

結果如下:

[<tf.Variable 'dense_2/kernel:0' shape=(1280, 1) dtype=float32, numpy=
 array([[ 0.08899798],
        [-0.06681276],
        [ 0.00906871],
        ...,
        [-0.00114891],
        [-0.01134416],
        [-0.02000826]], dtype=float32)>,
 <tf.Variable 'dense_2/bias:0' shape=(1,) dtype=float32, numpy=array([0.03746362], dtype=float32)>]    

(9)選擇 Adam 優(yōu)化器,將我們的學習率設置為 0.0003 。選擇 BinaryCrossentropy 作為損失函數。選擇常規(guī)的 accuracy 作為評估指標。此時我們先對基礎模型訓練 10 個 epoch 。

lr = 0.0003
initial_epochs = 10
model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=lr),
              loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
              metrics=['accuracy'])
history = model.fit(train_dataset, validation_data=test_dataset, epochs=initial_epochs)

訓練過程如下:

Epoch 1/10
63/63 [==============================] - 24s 352ms/step - loss: 0.5517 - accuracy: 0.6835 - val_loss: 0.2720 - val_accuracy: 0.8958
Epoch 2/10
63/63 [==============================] - 21s 327ms/step - loss: 0.2792 - accuracy: 0.8865 - val_loss: 0.1499 - val_accuracy: 0.9531
...
Epoch 9/10
63/63 [==============================] - 20s 321ms/step - loss: 0.1075 - accuracy: 0.9530 - val_loss: 0.0766 - val_accuracy: 0.9740
Epoch 10/10
63/63 [==============================] - 21s 329ms/step - loss: 0.1040 - accuracy: 0.9560 - val_loss: 0.0742 - val_accuracy: 0.9740

(10)使用測試數據對模型進行評估。

model.evaluate(validation_dataset)

結果如下:

loss: 0.0664 - accuracy: 0.9765

4. 微調

(1)在上面的操作中,我們僅僅在 MobileNetV2 基礎模型的頂部添加了一層池化層、一層 Dropout、一層全連接層作為我們的自定義分類器。預訓練模型 MobileNetV2 中權重在訓練過程中未曾發(fā)生過更新。

(2)我們還有一種被稱為微調的方法,可以在訓練基礎模型權重的同時,同時訓練我們上面自定義添加的用于分類的分類器。這個微調的訓練過程可以將基礎模型的通用的圖片特征提取能力調整為專門提取本任務中貓狗數據集特征的能力。這個微調的操作只能在我們進行了上面的遷移學習操作之后才能進行,否則如果一開始直接將基礎模型和我們自定義的若干層分類器一起進行訓練,則會由于隨機初始化的分類器導致整個模型的更新梯度太大,從而使得基礎模型喪失了其預訓練的有效能力。其次在微調過程中我們應該選擇性地去微調少量頂部的網絡層而不是整個 MobileNet 模型,因為在卷積神經網絡中,低層的網絡層一般捕獲到的是通用的圖片特征,這個能力可以泛化應用到幾乎所有類型的圖片,但是越往頂部的網絡層,越來越聚焦于捕獲訓練時所用到的訓練數據的特征,而微調的目標正是是讓這個模型更加適用于所用的專門的數據集,也就是本次進行的貓狗圖片。

(3)MobileNetV2 模型一共有 154 層結構,我們將模型的前 100 層的參數進行凍結,對頂部的 54 層網絡結構中的參數與我們自定義的分類器的若干層一起進行訓練,我們通過打印模型的 summary 可以看到,此時共有 54 個可以訓練的變量,這些變量中共有可訓練的參數 1862721 個。

base_model.trainable = True
fine_tune_at = 100
for layer in base_model.layers[:fine_tune_at]:
    layer.trainable = False
print("%d trainable variables "%len(model.trainable_variables))
model.summary()

結果如下:

56 trainable variables 
Model: "model_2"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 input_8 (InputLayer)        [(None, 160, 160, 3)]     0         
 sequential_2 (Sequential)   (None, 160, 160, 3)       0         
 tf.math.truediv_3 (TFOpLamb  (None, 160, 160, 3)      0         
 da)                                                             
 tf.math.subtract_3 (TFOpLam  (None, 160, 160, 3)      0         
 bda)                                                            
 mobilenetv2_1.00_160 (Funct  (None, 5, 5, 1280)       2257984   
 ional)                                                          
 global_average_pooling2d_3   (None, 1280)             0         
 (GlobalAveragePooling2D)                                        
 dropout_2 (Dropout)         (None, 1280)              0         
 dense_2 (Dense)             (None, 1)                 1281      
=================================================================
Total params: 2,259,265
Trainable params: 1,862,721
Non-trainable params: 396,544

(4)之前我們對基礎模型訓練了 10 個 epoch ,現在我們進行微調過程中再對模型訓練 10 個 epoch ,且我們將從上面訓練結束的 epoch 開始恢復并進行現在的訓練過程。

(5)這里我們改用 RMSprop 優(yōu)化器,且因為此時我們是要對整體模型進行微調,所以設置的學習率比之前降低 10 倍,否則如果較大會很快產生過擬合。

fine_tune_epochs = 10
total_epochs =  initial_epochs + fine_tune_epochs
model.compile(loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
              optimizer = tf.keras.optimizers.RMSprop(learning_rate=lr/10),
              metrics=['accuracy'])
history_fine = model.fit(train_dataset,  epochs=total_epochs,  initial_epoch=history.epoch[-1],  validation_data=validation_dataset)	

訓練結果輸出:

Epoch 10/20
63/63 [==============================] - 39s 561ms/step - loss: 0.1073 - accuracy: 0.9570 - val_loss: 0.1017 - val_accuracy: 0.9592
Epoch 11/20
63/63 [==============================] - 34s 538ms/step - loss: 0.0688 - accuracy: 0.9725 - val_loss: 0.0448 - val_accuracy: 0.9827
...
Epoch 19/20
63/63 [==============================] - 34s 537ms/step - loss: 0.0244 - accuracy: 0.9900 - val_loss: 0.0709 - val_accuracy: 0.9777
Epoch 20/20
63/63 [==============================] - 33s 528ms/step - loss: 0.0220 - accuracy: 0.9905 - val_loss: 0.0566 - val_accuracy: 0.9851

(6)使用測試數據對模型進行評估。

model.evaluate(test_dataset)

結果輸出:

loss: 0.0544 - accuracy: 0.9792

之前模型最后的驗證準確率為 0.9740 ,測試準確率為 0.9765 ,而經過微調的模型,最后餓驗證準確率為 0.9851 ,測試準確率為 0.9792 ,都有所提升。

5. 預測

我們隨機挑選一個 batch 進行預測,并將圖片與預測標簽進行顯示,結果表明預測全都正確。

image_batch, label_batch = test_dataset.as_numpy_iterator().next()
predictions = model.predict_on_batch(image_batch).flatten()
predictions = tf.nn.sigmoid(predictions)
predictions = tf.where(predictions < 0.5, 0, 1)
plt.figure(figsize=(10, 10))
for i in range(9):
    ax = plt.subplot(3, 3, i + 1)
    plt.imshow(image_batch[i].astype("uint8"))
    plt.title(class_names[predictions[i]])
    plt.axis("off")

以上就是深度學習Tensorflow 2.4 完成遷移學習和模型微調的詳細內容,更多關于Tensorflow 遷移學習模型微調的資料請關注腳本之家其它相關文章!

相關文章

  • 使用matplotlib繪制并排柱狀圖的實戰(zhàn)案例

    使用matplotlib繪制并排柱狀圖的實戰(zhàn)案例

    堆積柱狀圖有堆積柱狀圖的好處,比如說我們可以很方便地看到多分類總和的趨勢,下面這篇文章主要給大家介紹了關于使用matplotlib繪制并排柱狀圖的相關資料,需要的朋友可以參考下
    2022-07-07
  • 如何利用PyQt5美化你的GUI界面

    如何利用PyQt5美化你的GUI界面

    python的腳本開發(fā)簡單,有時候只需幾行代碼就能實現豐富的功能,而且python本身是跨平臺的,所以深受程序員的喜愛,下面這篇文章主要給大家介紹了關于如何利用PyQt5美化你的GUI界面的相關資料,需要的朋友可以參考下
    2022-01-01
  • Python迭代器和生成器介紹

    Python迭代器和生成器介紹

    這篇文章主要介紹了Python迭代器和生成器介紹,本文分別用代碼實例講解了Python的迭代器和生成器,需要的朋友可以參考下
    2015-03-03
  • CentOS7下python3.7.0安裝教程

    CentOS7下python3.7.0安裝教程

    這篇文章主要為大家詳細介紹了CentOS7下python3.7.0安裝教程,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-07-07
  • python中的二維列表實例詳解

    python中的二維列表實例詳解

    這篇文章主要介紹了python中的二維列表實例詳解,文中給大家介紹了python 二維列表按列取元素的方法,需要的朋友可以參考下
    2018-06-06
  • python如何正確使用yield

    python如何正確使用yield

    在 Python 開發(fā)中,yield 關鍵字的使用其實較為頻繁,例如大集合的生成,簡化代碼結構、協(xié)程與并發(fā)都會用到它。但是,你是否真正了解 yield 的運行過程呢?這篇文章,我們就來看一下 yield 的運行流程,以及在開發(fā)中哪些場景適合使用yield
    2021-05-05
  • Django把SQLite數據庫轉換為Mysql數據庫的過程

    Django把SQLite數據庫轉換為Mysql數據庫的過程

    之前我們默認使用的是SQLite數據庫,我們開發(fā)完成之后,里面有許多數據,如果我們想轉換成Mysql數據庫,那我們先得把舊數據從SQLite導出,然后再導入到新的Mysql數據庫里去,這篇文章主要介紹了Django如何把SQLite數據庫轉換為Mysql數據庫,需要的朋友可以參考下
    2023-05-05
  • 使用python 計算百分位數實現數據分箱代碼

    使用python 計算百分位數實現數據分箱代碼

    這篇文章主要介紹了使用python 計算百分位數實現數據分箱代碼,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-03-03
  • Python爬蟲包 BeautifulSoup  遞歸抓取實例詳解

    Python爬蟲包 BeautifulSoup 遞歸抓取實例詳解

    這篇文章主要介紹了Python爬蟲包 BeautifulSoup 遞歸抓取實例詳解的相關資料,需要的朋友可以參考下
    2017-01-01
  • 詳解Python連接MySQL數據庫的多種方式

    詳解Python連接MySQL數據庫的多種方式

    這篇文章主要介紹了Python連接MySQL數據庫方式,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-04-04

最新評論

娄底市| 乐山市| 娱乐| 清水县| 晋城| 平度市| 拜泉县| 日照市| 元朗区| 日照市| 汉源县| 佛教| 合肥市| 雅安市| 木兰县| 清水县| 澄江县| 托克逊县| 辉南县| 宁安市| 长葛市| 华安县| 汉中市| 榕江县| 陆河县| 丹棱县| 泰州市| 平顺县| 安新县| 太仓市| 日照市| 大庆市| 玛沁县| 江陵县| 科技| 邵武市| 桐乡市| 丰都县| 无极县| 泸水县| 碌曲县|