4.6 TF常用功能模块
4.6 TF常用功能模塊
學(xué)習(xí)目標(biāo)
- 目標(biāo)
- 掌握Checkpoint使用
- 掌握TensorBoard使用
- 掌握data模塊使用
- 掌握ImageDataGenerator的使用
- 應(yīng)用
- 無
4.6.1 fit的callbacks詳解
回調(diào)是在訓(xùn)練過程的給定階段應(yīng)用的一組函數(shù)。可以使用回調(diào)來獲取培訓(xùn)期間內(nèi)部狀態(tài)和模型統(tǒng)計(jì)信息的視圖。您可以將回調(diào)列表(作為關(guān)鍵字參數(shù)callbacks)傳遞給或類的fit()方法。然后將在訓(xùn)練的每個(gè)階段調(diào)用回調(diào)的相關(guān)方法。
- 定制化保存模型
- 保存events文件
4.6.1.1 ModelCheckpoint
from tensorflow.python.keras.callbacks import ModelCheckpoint
- keras.callbacks.ModelCheckpoint(filepath, monitor='val_loss', save_best_only=False, save_weights_only=False, mode='auto', period=1)
- Save the model after every epoch:每隔多少次迭代保存模型
- filepath: 保存模型字符串
- 如果設(shè)置 weights.{epoch:02d}-{val_loss:.2f}.hdf5格式,將會(huì)每隔epoch number數(shù)量并且將驗(yàn)證集的損失保存在該位置
- 如果設(shè)置weights.{epoch:02d}-{val_acc:.2f}.hdf5,將會(huì)按照val_acc的值進(jìn)行保存模型
- monitor: quantity to monitor.設(shè)置為'val_acc'或者'val_loss'
- save_best_only: if save_best_only=True, 只保留比上次模型更好的結(jié)果
- save_weights_only: if True, 只保存去那種(model.save_weights(filepath)), else the full model is saved (model.save(filepath)).
- mode: one of {auto, min, max}. 如果save_best_only=True, 對(duì)于val_acc, 要設(shè)置max, 對(duì)于val_loss要設(shè)置min
- period: 迭代保存checkpoints的間隔
注意:
1、使用ModelCheckpoint一定要在fit當(dāng)中指定驗(yàn)證集才能使用,否則報(bào)錯(cuò)誤。
2、其中val_acc還是val_accuracy需要在這里指定
model.compile(optimizer=tf.keras.optimizers.Adam(),loss=tf.keras.losses.sparse_categorical_crossentropy,metrics=['accuracy'])model.compile(optimizer=tf.keras.optimizers.Adam(),loss=tf.keras.losses.sparse_categorical_crossentropy,metrics=['acc'])4.6.1.2 Tensorboard
- 添加Tensorboard觀察損失等情況
- keras.callbacks.TensorBoard(log_dir='./logs', histogram_freq=0, batch_size=32, write_graph=True, write_grads=False, write_images=False, embeddings_freq=0, embeddings_layer_names=None, embeddings_metadata=None, embeddings_data=None, update_freq='epoch')
- log_dir:保存事件文件目錄
- write_graph=True:是否顯示圖結(jié)構(gòu)
- write_images=False:是否顯示圖片
- write_grads=True:是否顯示梯度histogram_freq?必須大于0
- 打開終端查看:
這是CNN mnist100案例中的效果:
- 目的:貓狗圖片二分類任務(wù)為示例
- 使用 tf.data 結(jié)合 tf.io 和 tf.image 建立Dataset 數(shù)據(jù)集
- 數(shù)據(jù)集可取這里下載:https://www.floydhub.com/fastai/datasets/cats-vs-dogs
- 步驟:
- 1、數(shù)據(jù)集的獲取和構(gòu)建
- 2、模型構(gòu)建和封裝
- 3、訓(xùn)練以及測(cè)試過程實(shí)現(xiàn)
1、數(shù)據(jù)集的獲取和構(gòu)建
class CatOrDog(object):"""貓狗分類"""num_epochs = 1batch_size = 32learning_rate = 0.001# 訓(xùn)練目錄train_cats_dir = '/root/cv_project/tf_example/cats_vs_dogs/train/cats/'train_dogs_dir = '/root/cv_project/tf_example/cats_vs_dogs/train/dogs/'# 驗(yàn)證目錄test_cats_dir = '/root/cv_project/tf_example/cats_vs_dogs/valid/cats/'test_dogs_dir = '/root/cv_project/tf_example/cats_vs_dogs/valid/dogs/'def __init__(self):# 1、讀取訓(xùn)練集的貓狗文件self.train_cat_filenames = tf.constant([CatOrDog.train_cats_dir + filenamefor filename in os.listdir(CatOrDog.train_cats_dir)])self.train_dog_filenames = tf.constant([CatOrDog.train_dogs_dir + filenamefor filename in os.listdir(CatOrDog.train_dogs_dir)])# 2、貓狗文件列表合并,并且初始化貓狗的目標(biāo)值,0為貓,1為狗self.train_filenames = tf.concat([self.train_cat_filenames, self.train_dog_filenames], axis=-1)self.train_labels = tf.concat([tf.zeros(self.train_cat_filenames.shape, dtype=tf.int32),tf.ones(self.train_dog_filenames.shape, dtype=tf.int32)],axis=-1)定義數(shù)據(jù)的獲取方法,通過tf.data指定
def get_batch(self):"""獲取dataset批次數(shù)據(jù):return:"""train_dataset = tf.data.Dataset.from_tensor_slices((self.train_filenames, self.train_labels))# 進(jìn)行數(shù)據(jù)的map, 隨機(jī),批次和預(yù)存儲(chǔ)train_dataset = train_dataset.map(map_func=_decode_and_resize,num_parallel_calls=tf.data.experimental.AUTOTUNE)train_dataset = train_dataset.shuffle(buffer_size=20000)train_dataset = train_dataset.batch(CatOrDog.batch_size)train_dataset = train_dataset.prefetch(tf.data.experimental.AUTOTUNE)return train_dataset# 圖片處理函數(shù),讀取,解碼并且進(jìn)行輸入形狀修改 def _decode_and_resize(filename, label):image_string = tf.io.read_file(filename)image_decoded = tf.image.decode_jpeg(image_string)image_resized = tf.image.resize(image_decoded, [256, 256]) / 255.0return image_resized, label2、模型構(gòu)建和封裝
通過構(gòu)造兩層卷積+兩個(gè)全連接層的網(wǎng)絡(luò)
self.model = tf.keras.Sequential([tf.keras.layers.Conv2D(32, 3, activation='relu', input_shape=(256, 256, 3)),tf.keras.layers.MaxPooling2D(),tf.keras.layers.Conv2D(32, 5, activation='relu'),tf.keras.layers.MaxPooling2D(),tf.keras.layers.Flatten(),tf.keras.layers.Dense(64, activation='relu'),tf.keras.layers.Dense(2, activation='softmax')])3、訓(xùn)練以及測(cè)試過程實(shí)現(xiàn)
模型訓(xùn)練過程,這里就免去指定ckpt以及tensorboard的callbacks了,可以自己去指定實(shí)驗(yàn)
def train(self, train_dataset):"""訓(xùn)練過程:return:"""self.model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=CatOrDog.learning_rate),loss=tf.keras.losses.sparse_categorical_crossentropy,metrics=[tf.keras.metrics.sparse_categorical_accuracy])self.model.fit(train_dataset, epochs=CatOrDog.num_epochs)self.model.save_weights("./ckpt/cat_or_dogs.h5")測(cè)試過程
- 1、需要提供一個(gè)讀取測(cè)試數(shù)據(jù)及的dataset數(shù)據(jù)集
- 2、進(jìn)行model的預(yù)測(cè),可以先進(jìn)行模型保存之后,再次讀取進(jìn)行預(yù)測(cè)
4.6.6 ImageDataGenerator介紹
當(dāng)我們需要做數(shù)據(jù)增強(qiáng)的時(shí)候,我們需要通過實(shí)時(shí)數(shù)據(jù)增強(qiáng)生成張量圖像數(shù)據(jù)批次。數(shù)據(jù)將不斷循環(huán)(按批次)。下面就介紹一個(gè)強(qiáng)大的工具,能夠?qū)τ谔峁┻^來的本地圖片讀取的數(shù)據(jù)還是其他工具讀取的圖片數(shù)據(jù)進(jìn)行在線數(shù)據(jù)怎強(qiáng)。
1、訓(xùn)練的時(shí)候讀取本地圖片以及類別
tf.keras.preprocessing.image.ImageDataGenerator(featurewise_center=False, samplewise_center=False,featurewise_std_normalization=False, samplewise_std_normalization=False,zca_whitening=False, zca_epsilon=1e-06, rotation_range=0, width_shift_range=0.0,height_shift_range=0.0, brightness_range=None, shear_range=0.0, zoom_range=0.0,channel_shift_range=0.0, fill_mode='nearest', cval=0.0, horizontal_flip=False,vertical_flip=False, rescale=None, preprocessing_function=None,data_format=None, validation_split=0.0, dtype=None )-
完整參數(shù)介紹參考TensorFlow官網(wǎng)文檔:https://www.tensorflow.org/api_docs/python/tf/keras/preprocessing/image/ImageDataGenerator#view-aliases
-
train_generator = ImageDataGenerator()
- 生產(chǎn)圖片的批次張量值并且提供數(shù)據(jù)增強(qiáng)功能
- rescale=1.0 / 255,:標(biāo)準(zhǔn)化
- zca_whitening=False: # zca白化的作用是針對(duì)圖片進(jìn)行PCA降維操作,減少圖片的冗余信息
- rotation_range=20:默認(rèn)0, 旋轉(zhuǎn)角度,在這個(gè)角度范圍隨機(jī)生成一個(gè)值
- width_shift_range=0.2,:默認(rèn)0,水平平移
- height_shift_range=0.2:默認(rèn)0, 垂直平移
- shear_range=0.2:# 平移變換
- horizontal_flip=True:水平翻轉(zhuǎn)
- zoom_range:隨機(jī)縮放的范圍
2、使用方法介紹
- 使用flow(x, y, batch_size)
-
使用train_generator.flow_from_directory(
-
directory=path,# 讀取目錄
-
target_size=(h,w),# 目標(biāo)形狀
-
batch_size=size,# 批數(shù)量大小
-
class_mode='binary', # 目標(biāo)值格式,One of "categorical", "binary", "sparse",
- "categorical" :2D one-hot encoded labels
- "binary" will be 1D binary labels
-
shuffle=True
-
這個(gè)API固定了讀取的目錄格式,參考:
- data/train/dogs/dog001.jpgdog002.jpg...cats/cat001.jpgcat002.jpg...validation/dogs/dog001.jpgdog002.jpg...cats/cat001.jpgcat002.jpg...
-
4.6.7 案例:ImageDataGenerator與遷移學(xué)習(xí)結(jié)合(基于VGG)
4.6.7.1 案例效果
??正在上傳…重新上傳取消
Epoch 1/21/13 [=>............................] - ETA: 3:20 - loss: 1.6811 - acc: 0.15622/13 [===>..........................] - ETA: 3:01 - loss: 1.5769 - acc: 0.25003/13 [=====>........................] - ETA: 2:44 - loss: 1.4728 - acc: 0.39584/13 [========>.....................] - ETA: 2:27 - loss: 1.3843 - acc: 0.45315/13 [==========>...................] - ETA: 2:14 - loss: 1.3045 - acc: 0.49386/13 [============>.................] - ETA: 1:58 - loss: 1.2557 - acc: 0.51567/13 [===============>..............] - ETA: 1:33 - loss: 1.1790 - acc: 0.57598/13 [=================>............] - ETA: 1:18 - loss: 1.1153 - acc: 0.62119/13 [===================>..........] - ETA: 1:02 - loss: 1.0567 - acc: 0.6562 10/13 [======================>.......] - ETA: 46s - loss: 1.0043 - acc: 0.6875 11/13 [========================>.....] - ETA: 31s - loss: 0.9580 - acc: 0.7159 12/13 [==========================>...] - ETA: 15s - loss: 0.9146 - acc: 0.7344 13/13 [==============================] - 249s 19s/step - loss: 0.8743 - acc: 0.7519 - val_loss: 0.3906 - val_acc: 0.9000 Epoch 2/21/13 [=>............................] - ETA: 2:56 - loss: 0.3862 - acc: 1.00002/13 [===>..........................] - ETA: 2:44 - loss: 0.3019 - acc: 1.00003/13 [=====>........................] - ETA: 2:35 - loss: 0.2613 - acc: 1.00004/13 [========>.....................] - ETA: 2:01 - loss: 0.2419 - acc: 0.98445/13 [==========>...................] - ETA: 1:49 - loss: 0.2644 - acc: 0.96886/13 [============>.................] - ETA: 1:36 - loss: 0.2494 - acc: 0.96887/13 [===============>..............] - ETA: 1:24 - loss: 0.2362 - acc: 0.97328/13 [=================>............] - ETA: 1:10 - loss: 0.2234 - acc: 0.97669/13 [===================>..........] - ETA: 58s - loss: 0.2154 - acc: 0.9757 10/13 [======================>.......] - ETA: 44s - loss: 0.2062 - acc: 0.9781 11/13 [========================>.....] - ETA: 29s - loss: 0.2007 - acc: 0.9801 12/13 [==========================>...] - ETA: 14s - loss: 0.1990 - acc: 0.979213/13 [==============================] - 243s 19s/step - loss: 0.1923 - acc: 0.9809 - val_loss: 0.1929 - val_acc: 0.93004.6.7.2 數(shù)據(jù)集以及遷移需求
數(shù)據(jù)集是某場(chǎng)景下5個(gè)類別圖片的識(shí)別
?
我們利用現(xiàn)有的VGG模型去進(jìn)行微調(diào)
4.6.7.3 思路和步驟
- 讀取本地的圖片數(shù)據(jù)以及類別
- keras.preprocessing.image import ImageDataGenerator提供了讀取轉(zhuǎn)換功能
- 模型的結(jié)構(gòu)修改(添加我們自定的分類層)
- freeze掉原始VGG模型
- 編譯以及訓(xùn)練和保存模型方式
- 輸入數(shù)據(jù)進(jìn)行預(yù)測(cè)
4.6.7.4 訓(xùn)練的時(shí)候讀取本地圖片以及類別
- 基于上面工具的讀取代碼
代碼:
首先導(dǎo)入包
import tensorflow as tf from tensorflow.keras.preprocessing.image import ImageDataGenerator from tensorflow.keras.applications.vgg16 import VGG16 import numpy as np import os os.environ["TF_CPP_MIN_LOG_LEVEL"] = "2"我們定義一個(gè)遷移學(xué)習(xí)的類,然后進(jìn)行相關(guān)屬性設(shè)置和讀取代碼
class TransferModel(object):def __init__(self):# 定義訓(xùn)練和測(cè)試圖片的變化方法,標(biāo)準(zhǔn)化以及數(shù)據(jù)增強(qiáng)self.train_generator = ImageDataGenerator(rescale=1.0 / 255.0,shear_range=0.2,zoom_range=0.2,horizontal_flip=True)self.test_generator = ImageDataGenerator(rescale=1.0 / 255.0)# 指定訓(xùn)練數(shù)據(jù)和測(cè)試數(shù)據(jù)的目錄self.train_dir = "./data/train"self.test_dir = "./data/test"# 定義圖片訓(xùn)練相關(guān)網(wǎng)絡(luò)參數(shù)self.image_size = (224, 224)self.batch_size = 32def read_img_to_generator(self):"""讀取本地圖片以及類別:return:訓(xùn)練數(shù)據(jù)和測(cè)試數(shù)據(jù)迭代器"""train_gen = self.train_generator.flow_from_directory(directory=self.train_dir,target_size=self.model_size,batch_size=self.batch_size,class_mode='binary',shuffle=True)test_gen = self.test_generator.flow_from_directory(directory=self.test_dir,target_size=self.model_size,batch_size=self.batch_size,class_mode='binary',shuffle=True)return train_gen, test_gen打印結(jié)果為
<keras_preprocessing.image.DirectoryIterator object at 0x12f52cf28>4.6.7.5 VGG模型的修改添加全連接層-GlobalAveragePooling2D
- notop模型:
- 是否包含最后的3個(gè)全連接層(whether to include the 3 fully-connected layers at the top of the network)。用來做fine-tuning專用,專門開源了這類模型。
‘weights='imagenet'’,意思是VGG在imagenet比賽中預(yù)訓(xùn)練的權(quán)重,使用resnet訓(xùn)練
# 在__init__中添加 self.base_model = VGG16(weights='imagenet', include_top=False)base_model會(huì)有相關(guān)屬性,模型的輸入結(jié)構(gòu):inputs,模型的輸出結(jié)構(gòu),我們修改需要得到已有VGG的輸入和自定義模型的輸出構(gòu)建成一個(gè)新的模型。
模型源碼:
if include_top:# Classification blockx = layers.Flatten(name='flatten')(x)x = layers.Dense(4096, activation='relu', name='fc1')(x)x = layers.Dense(4096, activation='relu', name='fc2')(x)x = layers.Dense(classes, activation='softmax', name='predictions')(x)else:if pooling == 'avg':x = layers.GlobalAveragePooling2D()(x)elif pooling == 'max':x = layers.GlobalMaxPooling2D()(x)- 一個(gè)GlobalAveragePooling2D + 兩個(gè)全連接層
- 在圖像分類任務(wù)中,模型經(jīng)過最后CNN層后的尺寸為[bath_size, img_width, img_height, channels],通常的做法是:接一個(gè)flatten layer,將尺寸變?yōu)閇batch_size, w?h?channels]再至少接一個(gè)FC layer,這樣做的最大問題是:模型參數(shù)多,且容易過擬合。
- 利用pooling layer來替代最后的FC layer
- ?
解釋如下:
from keras.layers import Dense, Input, Conv2D from keras.layers import MaxPooling2D, GlobalAveragePooling2Dx = Input(shape=[8, 8, 2048]) # 假定最后一層CNN的層輸出為(None, 8, 8, 2048) x = GlobalAveragePooling2D(name='avg_pool')(x) # shape=(?, 2048) # 取每一個(gè)特征圖的平均值作為輸出,用以替代全連接層 x = Dense(1000, activation='softmax', name='predictions')(x) # shape=(?, 1000) # 1000為類別- 5類圖片識(shí)別模型修改
我們需要拿到基礎(chǔ)VGG模型,并且VGG提供所有層參數(shù)訓(xùn)練好的模型和沒有全連接層參數(shù)的模型notop模型
from tensorflow.keras import Model def refine_base_model(self):"""微調(diào)VGG結(jié)構(gòu),5blocks后面+全局平均池化(減少遷移學(xué)習(xí)的參數(shù)數(shù)量)+兩個(gè)全連接層:return:"""# 1、獲取原notop模型得出# [?, ?, ?, 512]x = self.base_model.outputs[0]# 2、在輸出后面增加我們結(jié)構(gòu)# [?, ?, ?, 512]---->[?, 1 * 1 * 512]x = tf.keras.layers.GlobalAveragePooling2D()(x)# 3、定義新的遷移模型x = tf.keras.layers.Dense(1024, activation=tf.nn.relu)(x)y_predict = tf.keras.layers.Dense(5, activation=tf.nn.softmax)(x)# model定義新模型# VGG 模型的輸入, 輸出:y_predicttransfer_model = tf.keras.models.Model(inputs=self.base_model.inputs, outputs=y_predict)return transfer_model4.6.7.6 freeze VGG模型結(jié)構(gòu)
目的:讓VGG結(jié)構(gòu)當(dāng)中的權(quán)重參數(shù)不參與訓(xùn)練,只訓(xùn)練我們添加的最后兩層全連接網(wǎng)絡(luò)的權(quán)重參數(shù)
- 通過使用每一層的layer.trainable=False
4.6.7.7 編譯和訓(xùn)練
- 編譯
同樣還是進(jìn)行編譯, 在遷移學(xué)習(xí)中算法:學(xué)習(xí)率初始化較小的值,0.001,0.0001,因?yàn)橐呀?jīng)在已訓(xùn)練好的模型基礎(chǔ)之上更新,所以不需要太大學(xué)習(xí)率去學(xué)習(xí)
def compile(self, model):"""編譯模型:return:"""model.compile(optimizer=tf.keras.optimizers.Adam(),loss=tf.keras.losses.sparse_categorical_crossentropy,metrics=['accuracy'])return Nonedef fit_generator(self, model, train_gen, test_gen):"""訓(xùn)練模型,model.fit_generator()不是選擇model.fit():return:"""# 每一次迭代準(zhǔn)確率記錄的h5文件modelckpt = tf.keras.callbacks.ModelCheckpoint('./ckpt/transfer_{epoch:02d}-{val_accuracy:.2f}.h5',monitor='val_accuracy',save_best_only=True,save_weights_only=False,mode='auto',period=1)model.fit_generator(train_gen, epochs=3, validation_data=test_gen, callbacks=[modelckpt])return None- main函數(shù)
4.6.7.8 進(jìn)行預(yù)測(cè)
預(yù)測(cè)的步驟就是讀取圖片以及處理到模型中預(yù)測(cè),加載我們訓(xùn)練的模型
def predict(self, model):"""預(yù)測(cè)輸入圖片的類別:return:"""# 1、加載模型訓(xùn)練好的權(quán)重model.load_weights("./ckpt/transfer_01-0.84.h5")# 2、讀取圖片處理圖片數(shù)據(jù),形狀,數(shù)據(jù)歸一化image = tf.io.read_file("./data/test/dinosaurs/402.jpg")image_decoded = tf.image.decode_jpeg(image)image_resized = tf.image.resize(image_decoded, [224, 224]) / 255.0# 3維-->4維的形狀改變img = tf.reshape(image_resized, (1, image_resized.shape[0], image_resized.shape[1], image_resized.shape[2]))print("修改之后的形狀:", img.shape)# 3、輸入數(shù)據(jù)做預(yù)測(cè)y_predict = model.predict(img)index = np.argmax(y_predict, axis=1)print(self.label_dict[str(index[0])])return None建立圖片類別的字典
self.label_dict = {'0': 'bus','1': 'dinosaurs','2': 'elephants','3': 'flowers','4': 'horse'}4.6.6 總結(jié)
- Checkpoint使用
- TensorBoard使用
- tf.data模塊使用
- ImageDataGenerator的使用
總結(jié)
以上是生活随笔為你收集整理的4.6 TF常用功能模块的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: kdbg调试linux汇编,Ubuntu
- 下一篇: 终于学会上传图片了\( ̄︶ ̄*\))