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)

# 图像增强,可以将图片左右反转,上下翻转,甚至可以截取一部分,这样就增加了图片的数量,增加了训练集的数量,并且考虑到了更多的情况
# 甚至可以改变图片的亮度
posted @ 2022-03-03 17:57  白菜茄子  阅读(54)  评论(0编辑  收藏  举报