Tensorflow2.0学习(八) — tf.dataset自定义图像数据集
這一節我們參照官方教程提供的代碼,研究如何制作自己的數據集并送入深度學習模型中訓練。我們可以看到,前幾節的內容很多是基于現成的數據集,直接導入使用即可。但在實際應用中,這顯然是不可行的。對于Tensorflow2.0,主要有兩種自定義制作我們自己數據集的方式:一種是直接由tensorflow自身提供的函數來進行制作,而另一種則是調用tensorflow的高級API? Keras的函數來制作,這兩種方式都是可行的。但是建議大家還是使用官方提供的tf.dataset方式,但在這里二者都會進行介紹。那么這一節會先講如何用tensorflow自身提供的方式來自定義數據集,下一節則會討論另一種方式。
這一節我們將要對一些花的數據集來進行處理,這個數據集在網上可以通過遠程鏈接進行下載。但是由于該數據集沒有分好訓練集和測試集的部分,因此在本節代碼中我們不對模型進行測試,當然這也并不是我們這一節的重點,大家只要注重數據集制作的部分即可。
這里附上官方代碼的鏈接:https://tensorflow.google.cn/tutorials/load_data/images
一.自定義數據集的讀取
1.導入相關庫。
from __future__ import absolute_import,division,print_function,unicode_literals import tensorflow as tf import pathlib #讀圖片路徑 import random import IPython.display as display #顯示圖片 import os import matplotlib.pyplot as plt2.這行的代碼主要是跟圖像數據后臺的緩存處理有關。
AUTOTUNE = tf.data.experimental.AUTOTUNE3.下載數據集。fname的意思為下載后文件的命名,而untar=True的意思為對下載完后的文件壓縮包直接進行解壓。
data_root_orig = tf.keras.utils.get_file(origin='https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz',fname='flower_photos',untar=True)4.得到下載文件的目錄。
data_root = pathlib.Path(data_root_orig) data_root5.用iterdir()查看該文件夾下的文件情況。
for item in data_root.iterdir():print(item)6.用glob獲取所有文件并存入列表中。這里*的意思為獲取所有文件,因此*/*的意思則為獲取文件夾下的所有文件及它們的子文件。
all_images_paths = list(data_root.glob('*/*')) #獲取所有文件路徑 all_images_paths[-5:] #顯示后5個數據7.將所有文件路徑存入列表并打亂順序。
all_images_paths = [str(path) for path in all_images_paths] #將文件路徑傳入列表 random.shuffle(all_images_paths) #打亂文件路徑順序 image_count = len(all_images_paths) #查看文件數量 image_count8.隨機選擇3張圖片進行顯示。random_choice的意思為隨機選擇。
for n in range(3):image_path = random.choice(all_images_paths) #隨機選擇display.display(display.Image(image_path)) #圖片顯示9.獲取不同花朵圖片標簽的名字。這里*/獲得的是當前目錄的文件路徑,item.name函數可自動從路徑中篩選出需要的圖片名。
label_names = sorted(item.name for item in data_root.glob('*/') if item.is_dir()) label_names10.因為在訓練時參數必須為數字,因此我們需要將標簽轉為數字表示。這里的enumerate屬于python的語法,即是為其建立一個索引序列并配上下標。
label_to_index = dict((name,index)for index,name in enumerate(label_names)) #轉數字 label_to_index11.查看所有圖片路徑文件的類別。因為圖片路徑的上一級目錄名字就是代表的它的類別,因此我們可以用parent.name直接得到。
for path in all_images_paths:print(pathlib.Path(path).parent.name) #上級路徑12.存儲圖片的數字標簽到列表中。
all_images_labels = [label_to_index[pathlib.Path(path).parent.name] for path in all_images_paths] print(all_images_labels[:10]) #顯示前10個圖片標簽二.自定義數據集的預處理
1.定義圖片預處理函數和圖片讀入函數,第一個decode_jpeg為將讀入圖片的參數映射為圖片,然后將圖片大小統一并歸一化。
def preprocess_img(image):image = tf.image.decode_jpeg(image,channels=3) #映射為圖片image = tf.image.resize(image,[192,192]) #修改大小image /= 255.0 #歸一化return imagedef load_and_preprocess_image(path):image = tf.io.read_file(path) #這里注意的是這里讀到的是許多圖片參數return preprocess_img(image)2.顯示其中一張圖片。
image_path = all_images_paths[0] label = all_images_labels[0] plt.imshow(load_and_preprocess_image(image_path)) plt.grid(False) plt.title(label_names[label].title())3.構建一個tf.dataset,將圖片數據傳入其中。最簡單的方法就是使用from_tensor_slices方法。將圖片路徑字符串數組切片,得到一個字符串數據集。然后將我們剛才定義的圖片讀取和預處理函數傳入map函數中,即通過在路徑數據集上映射preprocess_image來動態加載和格式化圖片。
path_ds = tf.data.Dataset.from_tensor_slices(all_images_paths) #路徑字符串集合 image_ds = path_ds.map(load_and_preprocess_image, num_parallel_calls=AUTOTUNE) #通過路徑加載圖片數據集到了這一步我們就把我們的所有圖片數據集加載到tf.dataset中了。
4.將標簽數據也傳入其中。cast的意思即是將什么數據轉為什么類型,這里我們將其轉為整型int64。
label_ds = tf.data.Dataset.from_tensor_slices(tf.cast(all_images_labels,tf.int64)) #讀入標簽5.將圖片數據和標簽打包組合在一起。
image_label_ds = tf.data.Dataset.zip((image_ds,label_ds)) #圖片和標簽整合6.我們還可以通過一些函數對圖片集進行打亂、重復、分批操作。
Batch_size = 32 ds = image_label_ds.shuffle(buffer_size=image_count) #打亂數據 ds = ds.repeat() #數據重復 ds = ds.batch(Batch_size) #分割batch ds = ds.prefetch(buffer_size=AUTOTUNE) #使數據集在后臺取得 batch到了這一步我們的圖片標簽都已經制作好了,下一步進行模型搭建訓練。
三.模型搭建
1.這里我們將使用一個的名為MobileNetV2模型作為backbone進行訓練。192為我們剛才修改后圖片的尺寸,include_top意為是否保留頂層的全連接層,這里我們選擇False,因為我們只需要它的特征輸出部分。之后我們將這個模型設置為還未訓練的形式。
mobile_net = tf.keras.applications.MobileNetV2(input_shape=(192,192,3),include_top=False) mobile_net.trainable=False2.整體模型搭建。
model = tf.keras.Sequential([mobile_net,tf.keras.layers.GlobalAveragePooling2D(), #平均池化tf.keras.layers.Dense(len(label_names),activation='softmax') #分類 ])3.模型參數設置。
model.compile(optimizer=tf.keras.optimizers.Adam(),loss='sparse_categorical_crossentropy',metrics=["accuracy"])4.打印模型概要。
model.summary()5.查看模型需要訓練完所有圖片的次數是多少,我們將圖片數量/batch_size即可得到。這里要注意的是epochs和step_per_epoch的區別,前者是整體全部圖片訓練的次數,后者則是要訓練完一次epoch所需要的step。
steps_per_epoch=tf.math.ceil(len(all_images_paths)/Batch_size).numpy() steps_per_epoch我們發現要訓練115個step所有的batch才能訓練完。為了節約時間,我們這里只選擇step=3。
model.fit(ds, epochs=1, steps_per_epoch=3,verbose=2)?
以上就是本節的內容,下次內容會講述另一種制作數據集的方式。謝謝大家的觀看和支持!
?
?
?
總結
以上是生活随笔為你收集整理的Tensorflow2.0学习(八) — tf.dataset自定义图像数据集的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: jQuery 实现Ajax
- 下一篇: ArrayList的remove方法(重