tensorflow學習022——自定義訓練綜合貓狗資料例項訓練
阿新 • • 發佈:2022-03-03
點選檢視程式碼
import tensorflow as tf from tensorflow import keras import matplotlib.pyplot as plt import numpy as np import glob import os # 資料讀取 # print(os.path.exists(r"E:\WORK\tensorflow\dataset\dc\train")) train_image_path = glob.glob(r'E:\WORK\tensorflow\dataset\dc_2000\train\*\*.jpg') print(train_image_path[:5]) train_image_label = [int(p.split('\\')[-2] == 'cat') for p in train_image_path] # 狗0 貓1 print(train_image_label[:5]) def load_preprosess_image(path, label): image = tf.io.read_file(path) # 讀取圖片檔案 image = tf.image.decode_jpeg(image,channels=3) # 對圖片進行解碼 image = tf.image.resize(image, [256,256]) # 將圖片縮放到統一大小 image = tf.cast(image,tf.float32) # 更改資料型別,模型圖片的資料元素型別為uint8 image = image / 255 # 歸一化 label = tf.reshape(label, [1]) # 將[0,1,0] 轉換為[[0],[1],[0]]格式 return image, label # 建立dataset train_image_ds = tf.data.Dataset.from_tensor_slices((train_image_path,train_image_label)) AUTOTUNE = tf.data.experimental.AUTOTUNE train_image_ds = train_image_ds.map(load_preprosess_image,num_parallel_calls=AUTOTUNE) BATVH_SIZE = 32 train_count = len(train_image_path) train_image_ds = train_image_ds.shuffle(train_count).batch(BATVH_SIZE) train_image_ds = train_image_ds.prefetch(AUTOTUNE) # 當訓練一部分資料的時候,會在後臺提前讀取一部分資料 # 建立模型 # model = keras.Sequential([ # tf.keras.layers.Conv2D(64,(3,3),input_shape=(256,256,3)), # tf.keras.layers.BatchNormalization(), # 批標準化,可以用於防止過擬合,使得網路可以建的更深,有正則化的效果 # tf.keras.layers.Activation('relu'), # tf.keras.layers.MaxPooling2D(), # tf.keras.layers.Conv2D(128,(3,3)), # tf.keras.layers.BatchNormalization(), # tf.keras.layers.Activation('relu'), # tf.keras.layers.MaxPooling2D(), # tf.keras.layers.Conv2D(256, (3, 3)), # tf.keras.layers.BatchNormalization(), # tf.keras.layers.Activation('relu'), # tf.keras.layers.MaxPooling2D(), # tf.keras.layers.Conv2D(512, (3, 3)), # tf.keras.layers.BatchNormalization(), # tf.keras.layers.Activation('relu'), # tf.keras.layers.MaxPooling2D(), # tf.keras.layers.Conv2D(1024, (3, 3)), # tf.keras.layers.BatchNormalization(), # tf.keras.layers.Activation('relu'), # tf.keras.layers.GlobalAveragePooling2D(), # 再得到的(12,12)上兩維進行求平均值得到一個值 # tf.keras.layers.Dense(1024), # tf.keras.layers.BatchNormalization(), # tf.keras.layers.Activation('relu'), # tf.keras.layers.Dense(256), # tf.keras.layers.BatchNormalization(), # tf.keras.layers.Activation('relu'), # tf.keras.layers.Dense(1) # 這裡可以不寫啟用函式,因為對於二分類問題而言,不啟用的畫最後認為輸出結果大於0使一種結果,小於0使一種結果,啟用的畫只是進行歸一化 # # np.array[p[0].numpy() for p in tf.cast(pred>0,tf.int32)] 就可以將最後的結果轉換為0 1格式 # ]) model = keras.Sequential([ tf.keras.layers.Conv2D(64,(3,3),input_shape=(256,256,3)), tf.keras.layers.Activation('relu'), tf.keras.layers.MaxPooling2D(), tf.keras.layers.Conv2D(128,(3,3)), tf.keras.layers.Activation('relu'), tf.keras.layers.MaxPooling2D(), tf.keras.layers.Conv2D(256, (3, 3)), tf.keras.layers.Activation('relu'), tf.keras.layers.MaxPooling2D(), tf.keras.layers.Conv2D(512, (3, 3)), tf.keras.layers.Activation('relu'), tf.keras.layers.MaxPooling2D(), tf.keras.layers.Conv2D(1024, (3, 3)), tf.keras.layers.Activation('relu'), tf.keras.layers.GlobalAveragePooling2D(), # 再得到的(12,12)上兩維進行求平均值得到一個值 tf.keras.layers.Dense(256), tf.keras.layers.Activation('relu'), tf.keras.layers.Dense(1) # 這裡可以不寫啟用函式,因為對於二分類問題而言,不啟用的畫最後認為輸出結果大於0使一種結果,小於0使一種結果,啟用的畫只是進行歸一化 # np.array[p[0].numpy() for p in tf.cast(pred>0,tf.int32)] 就可以將最後的結果轉換為0 1格式 ]) # 損失函式與優化器 optimizer = tf.keras.optimizers.Adam() epoch_loss_avg = tf.keras.metrics.Mean("train_loss") train_accuracy = tf.keras.metrics.Accuracy('train_acc') def train_step(model,images,labels): with tf.GradientTape() as t: pred = model(images) loss_step = tf.keras.losses.BinaryCrossentropy(from_logits=True)(labels,pred) grads = t.gradient(loss_step,model.trainable_variables) optimizer.apply_gradients(zip(grads,model.trainable_variables)) epoch_loss_avg(loss_step) train_accuracy(labels,tf.cast(pred>0,tf.int32)) # 新增驗證資料 test_image_path = glob.glob(r'E:\WORK\tensorflow\dataset\dc_2000\test\*\*.jpg') test_image_label = [int(p.split('\\')[-2] == 'cat') for p in test_image_path] # 狗0 貓1 # print(len(test_image_path)) # print(len(test_image_label)) # print(test_image_path[:3]) # print(test_image_label[:3]) # exit(0) test_image_ds = tf.data.Dataset.from_tensor_slices((test_image_path,test_image_label)) test_image_ds = test_image_ds.map(load_preprosess_image,num_parallel_calls=AUTOTUNE) test_image_ds = test_image_ds.batch(BATVH_SIZE) test_image_ds = test_image_ds.prefetch(AUTOTUNE) epoch_loss_avg_test = tf.keras.metrics.Mean("test_loss") test_accuracy = tf.keras.metrics.Accuracy("test_acc") def test_step(model,images,labels): pred = model.predict(images) # 這裡不能直接使用model(image),因為這樣雖然也能返回預測結果,但是同時會對網路進行訓練 loss_step = tf.keras.losses.BinaryCrossentropy(from_logits=True)(labels,pred) epoch_loss_avg_test(loss_step) test_accuracy(labels,tf.cast(pred>0,tf.int32)) def train(epoches): train_loss_results = [] train_acc_results = [] test_loss_results = [] test_acc_results = [] for epoch in range(epoches): for imgs_,labels_ in train_image_ds: train_step(model,imgs_,labels_) print(".",end='') print() train_loss_results.append(epoch_loss_avg.result()) train_acc_results.append(train_accuracy.result()) for imgs_,labels_ in test_image_ds: test_step(model,imgs_,labels_) test_loss_results.append(epoch_loss_avg_test.result()) test_acc_results.append(test_accuracy.result()) print('Epoch:{}/{} train_loss:{:.3f} train_acc:{:.3f} test_loss:{:.3f} test_acc:{:.3f}'.format( epoch+1,epoches,epoch_loss_avg.result(),train_accuracy.result(),epoch_loss_avg_test.result(),test_accuracy.result())) epoch_loss_avg.reset_states() train_accuracy.reset_states() epoch_loss_avg_test.reset_states() test_accuracy.reset_states() return train_acc_results, train_acc_results train(20) # 影象增強,可以將圖片左右反轉,上下翻轉,甚至可以擷取一部分,這樣就增加了圖片的數量,增加了訓練集的數量,並且考慮到了更多的情況 # 甚至可以改變圖片的亮度
作者:孫建釗
出處:http://www.cnblogs.com/sunjianzhao/
本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連線,否則保留追究法律責任的權利。