在TensorFlow Hub中嘗試傳輸學習

在本文中,我將嘗試使用TensorFlow Hub(TF-HUB)對花卉圖像進行分類。至於程序,TF-HUB的官方教程很容易理解,因此可以作為參考。此外,我將嘗試在一系列過程中獨立收集圖像數據,並將其作為教師數據進行學習。

目錄

  • 關於TensorFlow Hub
    • 摘要
    • 首頁
    • 模型搜索
  • 實驗室設置
    • 啟用GPU
  • 轉移學習對花卉圖像的分類
    • 圖書館安裝
    • 模塊選擇
    • 準備教師數據
    • 模型定義
    • 學習的執行和評估
  • 添加原始教師數據並嘗試圖像分類
    • 圖像數據的集合
    • 重新加載數據
    • 使用其他數據運行學習
    • 用測試數據預測
    • 摘要

關於TensorFlow Hub

摘要

TensorFlow Hub概述頁面


 
 有一個像TensorFlow Hub這樣的知識庫,這是一個預先學習的機器學習模型庫。這是一個用於發布,使用和發現機器學習模型的可重用部分的庫。TensorFlow圖是一個獨立的TensorFlow圖,轉移學習允許您在不同任務之間重用權重和資產。

轉學習的優點如下。

  • 用小數據集訓練模型
  • 改善泛化
  • 加快學習速度

首頁

現在,讓我們試試TensorFlow Hub(TF-HUB)。
從以下URL訪問TF-HUB頁面。

https://tfhub.dev/

TF-HUB的首頁

已經顯示了TF-HUB的首頁。目前(2019/3/28),註冊了227個預先訓練的模型。細分如下。

輸入數據格式:文本(46),圖像(179),運動圖像(2)
算法:文本嵌入(46),圖像分類(71),圖像特徵向量(71),圖像生成(22),圖像其他(對象)檢測(2),地標檢測(1),圖像擴展(6),運動圖像分類(2)

如果從搜索窗口搜索“tf2”,則可以使用該模塊的“TensorFlow 2.0 Preview”版本。由於這與SavedModel 2.0格式相對應,因此請確保在安裝了TensorFlow 2.0和TensorFlow Hub 0.3.0的環境中執行庫版本。

模型搜索

 好吧,讓我們實際上搜索一個模型。

當模塊類型通過搜索窗口中的“tf2”的“image-feature-vector”縮小時,將出現以下兩個。這些模型將在後面描述,但在這裡,在第二行選擇“tf2-preview / inception_v3 / feature_vector”。

在TF-HUB上搜索

顯示預學習模型“tf2-preview / inception_v3 / feature_vector”的概述頁面
。列出了模型的特徵,已發表的文章和原始數據集的描述。您可以從螢幕右側的“Open Colab notebooks” 訪問Colaboratory 的教程頁面

預學習模型概述“tf2-preview / inception_v3 / feature_vector”
預學習模型“tf2-preview / inception_v3 / feature_vector”的協作教程頁面

實驗室設置

啟用GPU

 您可以從“運行時” – >“更改運行時類型”打開“筆記本設置”。為“運行時類型”選擇“Python 3”,為“硬件加速器”選擇“GPU”並保存。

在colaboratory中啟用GPU

有關如何使用Colaboratory的詳細信息,請參閱以下文章。
[在幾秒鐘內使用免費的GPU]關於實驗室的深度學習實踐技巧

轉移學習對花卉圖像的分類

Library安裝

安裝TensorFlow的GPU庫

 !pip install -U --pre tensorflow-gpu --quiet

安裝TF-HUB庫

 !pip install' tensorflow-hub> = 0.3' 

我們在安裝後檢查一下這些信息 

Python 3

from __future__ import absolute_import, division, print_function       

import os

import matplotlib.pylab as plt
import numpy as np

import tensorflow as tf
import tensorflow_hub as hub

print("Version: ", tf.__version__)
print("Eager mode: ", tf.executing_eagerly())
print("Hub version: ", hub.__version__)
print("GPU is", "available" if tf.test.is_gpu_available() else "NOT AVAILABLE")

 結果

Version:  2.0.0-alpha0    
Eager mode: True
Hub version: 0.3.0
GPU is available

您可以看到該版本是最新版本“2.0.0-alpha 0”,Eagle模式已打開,並且GPU已啟用。

模塊選擇

 接下來,讓我們選擇TF-HUB模塊。有幾種類型的預學習模型,有兩種類型的“inception_v3”和“mobilenet_v2”用於提取當前為TF 2.0發布的圖像特徵向量(圖像特徵向量)。由於這些使用TF-Slim的實現,並且“inception_v3”似乎從這個比較表更準確,這次使用。對於模塊,您可以從Collaboration UI的下拉菜單中進行選擇。批量大小將繼續為“64”。 Python 3

module_selection =(“inception_v3”,299,2048)#@ PARAM [“(\”mobilenet_v2 \“,224,1280)”,“(\”inception_v3 \“,299,2048)”] {類型:“原始”, allow-input:true}    
handle_base,pixels,FV_SIZE = module_selection
MODULE_HANDLE =“https://tfhub.dev/google/tf2-preview/{}/feature_vector/2".format(handle_base)
IMAGE_SIZE =(像素,像素)
print(“使用{}輸入大小{}和輸出維度{}”。format(
MODULE_HANDLE,IMAGE_SIZE,FV_SIZE))
BATCH_SIZE = 64#@ param {type:“integer”}

 結果

使用https://tfhub.dev/google/tf2-preview/inception_v3/feature_vector/2輸入大小(299,299)和輸出維度2048 

用於輸入的圖像的大小是299×299像素,輸出維度是2048。

準備教師數據

 接下來,讓我們下載用於學習的圖像的教師數據。“tf.keras.utils.get_file”函數默認下載“〜/ .keras”下的圖像,但您也可以使用“cache_dir”指定任何目錄。Colaboratory默認情況下在“sample_data”中有一個示例數據集,所以這次我會將它添加到它。 Python 3

data_dir = tf.keras.utils.get_file(        
'flower_photos', 'https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz',
untar=True,
cache_dir="sample_data") #指定緩存存儲目錄

下載將很快完成。
變量“data_dir”將下載路徑(“’sample_data / datasets / flower_photos’”)存儲為字符串。

您可以從面板→Colaboratory屏幕左側的“文件”選項卡中檢查目錄結構。

在Colaboratory Explorer中看到的文件列表

讓我們可視化下載的圖像。 慶典

將matplotlib翻譯成日語的庫   
!pip install japanize-matplotlib

 Python 3

import cv2    
from matplotlib
import pyplot as plt
import glob import os
import pandas as pd
import japanize_matplotlib

# 從指定目錄中提取圖像路徑和標籤集
def create_data(path, sample_size):
targets = []
images = []
for label in glob.iglob(path):
if "LICENSE.txt" in label:
continue
count = 1
for image in enumerate(glob.iglob(label + "/*")):
targets.append(label.split("/")[-1])
images.append(image[1])
count += 1
if count > sample_size:
break
df = pd.DataFrame(list(zip(targets, images)), columns=["label", "path"])
df = df.sample(frac=1).reset_index(drop=True)
df_ = df.groupby('label').head(sample_size).reset_index(drop=True).sort_values('label')
targets_ = [x[0] for x in df_.values.tolist()]
images_ = [x[1] for x in df_.values.tolist()]
return targets_, images_

# 顯示圖像
def show_images(target, images, sample_size=10, figsize=(20,18)):
class_num = len(set(target))
fig, axes = plt.subplots(class_num, sample_size, figsize=figsize,
subplot_kw={'xticks': (), 'yticks': ()})
for target, image, ax in zip(target, images, axes.ravel()):
obj = cv2.imread(image)
if obj is None:
continue
obj = cv2.cvtColor(obj, cv2.COLOR_BGR2RGB)
ax.imshow(obj)
ax.set_title(target)

sample_size=4
target, images = create_data("sample_data/datasets/flower_photos/*", sample_size)
show_images(target, images, sample_size, figsize=(18,18))
可視化flower_photos數據集

讓我們用keras預處理模塊“ImageDataGenerator”加載它。您可以從之前指定為“圖像下載目標”的“data_dir”中讀取圖像文件路徑和標籤名稱。如果要擴展(填充)訓練圖像,請將“do_data_augmentation”標誌設置為“True”。

Python 3

datagen_kwargs = dict(rescale=1./255, validation_split=.20)    
valid_datagen = tf.keras.preprocessing.image.ImageDataGenerator(
**datagen_kwargs)
valid_generator = valid_datagen.flow_from_directory(
data_dir, subset="validation", shuffle=False,
target_size=IMAGE_SIZE, batch_size=BATCH_SIZE)

do_data_augmentation = True #@param {type:"boolean"}
if do_data_augmentation:
train_datagen = tf.keras.preprocessing.image.ImageDataGenerator(
rotation_range=40,
horizontal_flip=True,
width_shift_range=0.2, height_shift_range=0.2,
shear_range=0.2, zoom_range=0.2,
**datagen_kwargs)
else:
train_datagen = valid_datagen
train_generator = train_datagen.flow_from_directory(
data_dir, subset="training", shuffle=True,
target_size=IMAGE_SIZE, batch_size=BATCH_SIZE)

 結果

Found 731 images belonging to 5 classes.    
Found 2939 images belonging to 5 classes.

您可以看到已準備好5類圖像用於訓練/驗證。

模型定義

 接下來,讓我們定義模型。在TF-HUB模塊中,可以通過標誌切換轉換學習或微調。如果你想專注於速度,你可能想要使用轉移學習,如果你想專注於準確性,你應該選擇微調。我們這次嘗試默認的轉換學習(“do_fine_tuning”= False)。 

Python 3

   do_fine_tuning = False#@ param {type:“boolean”}

接下來,我們將使用tf.keras.Sequential API來堆疊圖層。首先,在hub.KerasLayer上加載模塊,並將其與dropout層和所有連接的層連接。網絡完成後,構建模型。在TF 2.0的更新中,似乎簡化了對這些部分的描述成為了重點。 

Python 3

print("Building model with", MODULE_HANDLE)    
model = tf.keras.Sequential([
hub.KerasLayer(MODULE_HANDLE, output_shape=[FV_SIZE],
trainable=do_fine_tuning),
tf.keras.layers.Dropout(rate=0.2),
tf.keras.layers.Dense(train_generator.num_classes, activation='softmax',
kernel_regularizer=tf.keras.regularizers.l2(0.0001))
])
model.build((None,)+IMAGE_SIZE+(3,))
model.summary()

 結果

Building model with https://tfhub.dev/google/tf2-preview/inception_v3/feature_vector/2    Model: "sequential"    _________________________________________________________________    Layer (type)                 Output Shape              Param #      =================================================================    keras_layer (KerasLayer)     multiple                  21802784     _________________________________________________________________    dropout (Dropout)            multiple                  0            _________________________________________________________________    dense (Dense)                multiple                  10245        =================================================================    Total params: 21,813,029    Trainable params: 10,245    Non-trainable params: 21,802,784

指定優化方法,損失函數,度量和編譯。 

Python 3

model.compile(      
optimizer = tf.keras.optimizers.SGD(lr = 0.005,動量= 0.9),
loss = tf.keras.losses.CategoricalCrossentropy(label_smoothing = 0.1),
metrics = ['accuracy'])

學習的執行和評估

現在你準備好了。我現在就開始訓練了。 

Python 3

steps_per_epoch = train_generator.samples // train_generator.batch_size    
validation_steps = valid_generator.samples // valid_generator.batch_size
hist = model.fit_generator(
train_generator,
epochs = 5,steps_per_epoch = steps_per_epoch, validation_data = valid_generator,
validation_steps = validation_steps).history

 結果

Epoch 1/5    
45/45 [==============================] - 91s 2s/step - loss: 1.5222 - accuracy: 0.3605 - val_loss: 1.3432 - val_accuracy: 0.6236
Epoch 2/5
45/45 [==============================] - 79s 2s/step - loss: 1.1092 - accuracy: 0.7630 - val_loss: 1.0514 - val_accuracy: 0.8054
Epoch 3/5
45/45 [==============================] - 78s 2s/step - loss: 1.0515 - accuracy: 0.8039 - val_loss: 1.0007 - val_accuracy: 0.8352
Epoch 4/5
45/45 [==============================] - 76s 2s/step - loss: 1.0130 - accuracy: 0.8250 - val_loss: 0.9916 - val_accuracy: 0.8295
Epoch 5/5
45/45 [==============================] - 77s 2s/step - loss: 0.9944 - accuracy: 0.8469 - val_loss: 0.9538 - val_accuracy: 0.8693

5個時代轉,val_accuracy為0.8693。讓我們也繪製學習曲線。 

Python 3

plt.figure()    
plt.ylabel("Loss (training and validation)")
plt.xlabel("Training Steps")
plt.ylim([0,2])
plt.plot(hist["loss"])
plt.plot(hist["val_loss"])
plt.figure()
plt.ylabel("Accuracy (training and validation)")
plt.xlabel("Training Steps")
plt.ylim([0,1])
plt.plot(hist["accuracy"])
plt.plot(hist["val_accuracy"])
在flower_photos數據集中學習曲線

這次學習數據為2939張,驗證數據為731張,但數據量不是很大,但可能是出現了很好的準確性。

添加原始教師數據並嘗試圖像分類

 接下來,讓我們自己準備教師數據。有很多方法可以做到這一點,但是google_images_download庫對於快速嘗試非常有用。這次,讓我們用它來從網上收集圖像。它似乎是在內部使用硒等進行刮擦

圖像數據的集合

使用pip安裝庫。 慶典

   !pip install google_images_download

接下來,我將編寫一個搜索程序。
您可以在參數“keywords”中輸入要收集的圖像的搜索關鍵字。如果用“,”分隔,則每個文件夾將作為單獨的文件夾下載到指定目錄。讓我們將本教程中使用的“sample_data / datasets / flower_photos /”設置為參數“output_directory”。將3個類別(繡球花,牽牛花,龍膽草)添加到之前獲得的數據集“flower_photos”的5個類(雛菊,蒲公英,玫瑰,向日葵,鬱金香)中。在參數“time_range”中指定“{”time_min“:”01/01/2017“,”time_max“:”12/31/2017“}以防止與稍後使用的測試數據混合,2017僅適用於圖像。 

Python 3

from google_images_download import google_images_download   #importing the library       

response = google_images_download.googleimagesdownload() #class instantiation
arguments = {"keywords":"アジサイ,アサガオ,リンドウ","limit":100,"print_urls":True, "output_directory":"sample_data/datasets/flower_photos/", "time_range":'{"time_min":"01/01/2017","time_max":"12/31/2017"}'} #creating list of arguments
paths = response.download(arguments) #passing the arguments to the function
print(paths) #printing absolute paths of the downloaded images

正在下載的日誌如下所示。 結果

Item no.: 1 --> Item name = アジサイ    
Evaluating...
Starting Download...
Image URL: https://upload.wikimedia.org/wikipedia/commons/thumb/1/15/Hydrangea_of_Shimoda_%E4%B8%8B%E7%94%B0%E3%81%AE%E3%81%82%E3%81%98%E3%81%95%E3%81%84_%282630826953%29.jpg/1200px-Hydrangea_of_Shimoda_%E4%B8%8B%E7%94%B0%E3%81%AE%E3%81%82%E3%81%98%E3%81%95%E3%81%84_%282630826953%29.jpg
Completed Image ====> 1. 1200px-hydrangea_of_shimoda_%e4%b8%8b%e7%94%b0%e3%81%ae%e3%81%82%e3%81%98%e3%81%95%e3%81%84_%282630826953%29.jpg
Image URL: https://storage.tenki.jp/storage/static-images/suppl/article/image/2/23/233/23311/1/large.jpg
Completed Image ====> 2. large.jpg
Image URL: https://www.jalan.net/news/img/2018/04/d3d77_0000806446_1-670x443.jpg
Completed Image ====> 3. d3d77_0000806446_1-670x443.jpg
Image URL: https://www.toho-u.ac.jp/sci/bio/column/j5mt8h000000bexy-img/200807_01.jpg
Completed Image ====> 4. 200807_01.jpg
Image URL: https://www.i-iro.com/wp-content/uploads/images/hydrangea-iro-2-680x420.jpg
Completed Image ====> 5. hydrangea-iro-2-680x420.jpg
Image URL: http://www.muse-park.com/wordpress/wp-content/themes/muse-park/img/seasonal-flower/flower05_01.jpg
Completed Image ====> 6. flower05_01.jpg
Image URL: http://www.hana300.com/ajisai98.jpg
・・・

下載完成後,您會發現文件列表中添加了3個類(繡球花,牽牛花和龍膽)。我們這次每班收集100張圖片,但如果您想收集更多圖片,請更改搜索關鍵字或嘗試使用selenium作為選項。

添加此次收集的圖像文件夾的文件列表

讓我們再次可視化圖像。 Python 3

sample_size = 10    
target,images = create_data(“sample_data / datasets / flower_photos / *”,sample_size)
show_images(target,images,sample_size)
可視化flower_photos數據集(圖像添加版本)

也可以從“協作”部分的文件列表中逐個打開圖像並進行檢查。因此,對於可能存在噪聲的圖像,請通過刪除文件來準備數據集。

來自Colaboratory Explorer的文件操作

重新加載數據

現在數據集已經更新,讓我們再次學習它。 

Python 3

datagen_kwargs = dict(rescale=1./255, validation_split=.20)    
valid_datagen = tf.keras.preprocessing.image.ImageDataGenerator(
**datagen_kwargs)
valid_generator = valid_datagen.flow_from_directory(
data_dir, subset="validation", shuffle=False,
target_size=IMAGE_SIZE, batch_size=BATCH_SIZE)

do_data_augmentation = True #@param {type:"boolean"}
if do_data_augmentation:
train_datagen = tf.keras.preprocessing.image.ImageDataGenerator(
rotation_range=40,
horizontal_flip=True,
width_shift_range=0.2, height_shift_range=0.2,
shear_range=0.2, zoom_range=0.2,
**datagen_kwargs)
else:
train_datagen = valid_datagen
train_generator = train_datagen.flow_from_directory(
data_dir, subset="training", shuffle=True,
target_size=IMAGE_SIZE, batch_size=BATCH_SIZE)

 結果

Found 788 images belonging to 8 classes.    
Found 3172 images belonging to 8 classes.

如果使用ImageDataGenerator再次讀取圖像,則可以看到類的數量已增加到8。

使用其他數據運行學習

 讓我們嘗試使用上面的代碼再次學習。 

Python 3

do_fine_tuning = False #@param {type:"boolean"}    

print("Building model with", MODULE_HANDLE)
model = tf.keras.Sequential([
hub.KerasLayer(MODULE_HANDLE, output_shape=[FV_SIZE],
trainable=do_fine_tuning),
tf.keras.layers.Dropout(rate=0.2),
tf.keras.layers.Dense(train_generator.num_classes, activation='softmax', kernel_regularizer=tf.keras.regularizers.l2(0.0001))
])
model.build((None,)+IMAGE_SIZE+(3,))
model.summary()

model.compile(
optimizer=tf.keras.optimizers.SGD(lr=0.005, momentum=0.9),
loss=tf.keras.losses.CategoricalCrossentropy(label_smoothing=0.1),
metrics=['accuracy'])

steps_per_epoch = train_generator.samples // train_generator.batch_size
validation_steps = valid_generator.samples // valid_generator.batch_size
hist = model.fit_generator(
train_generator,
epochs=5, steps_per_epoch=steps_per_epoch,
validation_data=valid_generator,
validation_steps=validation_steps).history

注意)在此過程中,圖像的加載可能會失敗。在這種情況下,請刪除圖像。 慶典

!rm "sample_data/datasets/flower_photos/牽牛花/95. marubarukou300.2.jpg"

像以前一樣運行5個時代。 結果

Epoch 1/5    
49/49 [==============================] - 99s 2s/step - loss: 1.7797 - accuracy: 0.3707 - val_loss: 1.4744 - val_accuracy: 0.6185
Epoch 2/5
49/49 [==============================] - 90s 2s/step - loss: 1.3507 - accuracy: 0.7099 - val_loss: 1.2566 - val_accuracy: 0.7578
Epoch 3/5
49/49 [==============================] - 88s 2s/step - loss: 1.2364 - accuracy: 0.7621 - val_loss: 1.1531 - val_accuracy: 0.8151
Epoch 4/5
49/49 [==============================] - 86s 2s/step - loss: 1.1875 - accuracy: 0.7849 - val_loss: 1.1246 - val_accuracy: 0.8281
Epoch 5/5
49/49 [==============================] - 85s 2s/step - loss: 1.1651 - accuracy: 0.8123 - val_loss: 1.1044 - val_accuracy: 0.8581

這次,val_accuracy是0.8581。我添加的類略低,可能是因為它被原樣使用而沒有刪除噪聲圖像。讓我們也繪製學習曲線。 

Python 3

plt.figure()    
plt.ylabel("Loss (training and validation)")
plt.xlabel("Training Steps")
plt.ylim([0,2])
plt.plot(hist["loss"])
plt.plot(hist["val_loss"])
plt.figure()
plt.ylabel("Accuracy (training and validation)")
plt.xlabel("Training Steps")
plt.ylim([0,1])
plt.plot(hist["accuracy"])
plt.plot(hist["val_accuracy"])
flower_photos數據集中的學習曲線(圖像添加版本)

用測試數據預測

現在你有了一個模型,讓我們嘗試使用測試數據進行分類。在參數“time_range”中指定“{”time_min“:”01/01/2018“,”time_max“:”12/31/2018“}’,以使用與先前訓練數據不同的圖像進行測試。它僅針對2018個圖像。輸出目標目錄“output_directory”指定用於測試的目錄。

bash

TEST_DATA_DIR = "test_data/datasets/flower_photos/"    
!mkdir -p {TEST_DATA_DIR}

 Python 3

from google_images_download import google_images_download   #importing the library       

response = google_images_download.googleimagesdownload() #class instantiation
arguments = {"keywords":"アジサイ,アサガオ,リンドウ,dandelion,roses,tulips,daisy,sunflowers","limit":100,"print_urls":True, "output_directory":TEST_DATA_DIR,"time_range":'{"time_min":"01/01/2018","time_max":"12/31/2018"}'} #creating list of arguments
paths = response.download(arguments) #passing the arguments to the function
print(paths) #printing absolute paths of the downloaded images
測試目錄“test_data”

準備使用ImageDataGenerator再次加載測試圖像。 

Python 3

test_datagen = tf.keras.preprocessing.image.ImageDataGenerator(        
** datagen_kwargs)
test_generator = test_datagen.flow_from_directory(
TEST_DATA_DIR,shuffle = False,
target_size = IMAGE_SIZE,batch_size = BATCH_SIZE)

 結果

Found 778 images belonging to 8 classes.

8個類,778個測試數據可用。
所以讓我們預測模型。 

Python 3

y_prob = model.predict_generator(test_generator, verbose=1)

沒有多少,所以很快就會完成。
讓我們可視化預測結果。 

Python 3

from sklearn import preprocessing    
import pandas as pd

#將預測概率轉換為標籤
#例: [[9.9109542e-01, 6.4130645e-04, 6.3536654e-04, 3.0492968e-03,8.3755807e-04, 1.0973219e-03, 1.1702350e-03, 1.4735168e-03]]→['daisy']
def prob_to_labels(y_prob, generator):
y_classes = y_prob.argmax(axis=-1)
labels = [x for x in generator.class_indices.keys()]
le = preprocessing.LabelEncoder()
le.fit(labels)
result = le.inverse_transform(y_classes)
return list(result)

#獲取為每個標籤指定的編號
def filter_data(targets, generator, sample_size=10):
images = generator.filepaths
df = pd.DataFrame(list(zip(targets, images)), columns=["label", "path"])
df = df.sample(frac=1).reset_index(drop=True)
df_ = df.groupby('label').head(sample_size).reset_index(drop=True).sort_values('label')
targets_ = [x[0] for x in df_.values.tolist()]
images_ = [x[1] for x in df_.values.tolist()]
return targets_, images_
sample_size=10
targets = prob_to_labels(y_prob, test_generator)
targets, images = filter_data(targets, test_generator, sample_size)
show_images(targets, images, sample_size)
預測測試數據的結果

測試數據可以正確分類。我這次加入的三個班級(牽牛花,繡球花,龍膽)看起來也很不錯。

摘要

 即使使用原始教師數據,也發現來自tf.keras的順序API可以無縫地執行圖像讀取,學習和預測。TF-HUB具有除圖像之外的各種模型,例如BERT,一種去年成為主題的通用語言表達模型。請務必嘗試。

範例代碼

Aaron Lee

超過6年的Google Cloud經驗,服務過上百家G Suite與GCP客戶,擔任多次研討會主講人與教育訓練講師,提供架構諮詢與技術支援,幫助各大企業上雲。

Leave a Reply