tensorflow学习022——自定义训练综合猫狗数据实例训练
数据链接:https://pan.baidu.com/s/1-nLlW6Nng1pAvrxwEfHttA
提取码:vt8p
记得更改代码中的路径
点击查看代码
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/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。