第八周 tensorflow实现猫狗识别

一、本周学习内容:

1、自己搭建VGG16网络

在这里插入图片描述
vgg16网络代码

def vgg_net(num_layer,filter):
    blk = Sequential()
    for _ in range(num_layer):
        blk.add(Conv2D(filters=filter,kernel_size=3,padding='same',activation='relu'))
    blk.add(MaxPool2D(pool_size=(2,2),strides=2))
    return blk

conv_arch = [(2,64),(2,128),(3,256),(3,512),(3,512)]
model = Sequential()
for num_layer,filter in conv_arch:
    model.add(vgg_net(num_layer,filter))
model.add(Sequential([
    Flatten(),
    Dense(4096,activation='relu'),
    Dropout(0.5),
    Dense(4096,activation='relu'),
    Dropout(0.5),
    Dense(len(class_num),activation='softmax')  # 输出类别数自行更改
]))

x = tf.random.uniform((1,224,224,3))
y = model(x)
print(model.summary())

2、了解model.train_on_batch()

y_pred = model.train_on_batch(
x,
y=None,
sample_weight=None,
class_weight=None,
reset_metrics=True,
return_dict=False,
)
x:模型输入,单输入就是一个 numpy 数组, 多输入就是 numpy 数组的列表
y:标签,单输出模型就是一个 numpy 数组, 多输出模型就是 numpy 数组列表
sample_weight:mini-batch 中每个样本对应的权重,形状为 (batch_size)
class_weight:类别权重,作用于损失函数,为各个类别的损失添加权重,主要用于类别不平衡的情况, 形状为 (num_classes)
reset_metrics:默认True,返回的metrics只针对这个mini-batch, 如果False,metrics 会跨批次累积
return_dict:默认 False, y_pred 为一个列表,如果 True 则 y_pred 是一个字典
可看这篇文章描述train_on_batch

3、了解tqdm,并使用tqdm实现可视化进度条

tqdm是 Python 进度条库,可以在 Python长循环中添加一个进度提示信息。用户只需要封装任意的迭代器,是一个快速、扩展性强的进度条工具库。
这篇文章介绍tqdm的使用

二、前言

我们的数据图片共有3400张,两个类别,类别即为文件夹名。
类别包括:[‘Dark’, ‘Green’, ‘Light’, ‘Medium’]
在我们使用tensorflow.keras.preprocessing.image_dataset_from_directory()函数读取后会弹出下列提示
Found 3400 files belonging to 2 classes.
Using 680 files for validation.
[‘cat’, ‘dog’]

三、电脑环境

电脑系统:Windows 10
语言环境:Python 3.8.8
编译器:Pycharm 2021.1.3
深度学习环境:TensorFlow 2.8.0,keras 2.8.0
显卡及显存:RTX 3070 8G

四、前期准备

1、导入相关依赖项

from keras.models import Sequential
from keras.layers import *
from tensorflow import keras
from keras.callbacks import ModelCheckpoint
import tensorflow as tf
import matplotlib.pyplot as plt

2、设置GPU(我下载的tensorflow-gpu 默认使用GPU)

只使用GPU

if gpus:
    gpu0 = gpus[0]                                        #如果有多个GPU,仅使用第0个GPU
    tf.config.experimental.set_memory_growth(gpu0, True)  #设置GPU显存用量按需使用
    tf.config.set_visible_devices([gpu0],"GPU")

使用cpu和gpu
os.environ[“CUDA_VISIBLE_DEVICES”] = “-1”

3、加载数据集和展示

(1)、数据集加载

# 数据集加载
traindatadir = "./dataset"
train = keras.preprocessing.image_dataset_from_directory(directory=traindatadir,
                                                           validation_split=0.2,
                                                           subset='training',
                                                           seed=469,
                                                           label_mode='categorical',
                                                           image_size=(224,224),
                                                           batch_size=32)
val = keras.preprocessing.image_dataset_from_directory(directory=traindatadir,
                                                           validation_split=0.2,
                                                           subset='validation',
                                                           seed=469,
                                                           label_mode='categorical',
                                                           image_size=(224,224),
                                                           batch_size=32)


class_names = train.class_names
print(class_names)

(2)、数据展示

图片展示

# 图片展示
plt.figure(figsize=(15, 10))  # 图形的宽为15高为10
for images, labels in train_ds.take(1):
    for i in range(32):
        ax = plt.subplot(5, 8, i + 1)
        plt.imshow(images[i])
        plt.title(class_names[labels[i]])
        plt.axis("off")

plt.show()  #使用pycharm的需要加入这行代码才能将图像显示出来
# train.take(i) 取出第i组图片数据和标签,即将所有图片打包后一个batch为32,

在这里插入图片描述

五、数据预处理

将数据归一化并加载入内存中

AUTOTUNE = tf.data.AUTOTUNE

def preprocess_image(image,label):
    return (image/255.0,label)

# 归一化处理
train_ds = train_ds.map(preprocess_image, num_parallel_calls=AUTOTUNE)
val_ds   = val_ds.map(preprocess_image, num_parallel_calls=AUTOTUNE)

train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)
val_ds   = val_ds.cache().prefetch(buffer_size=AUTOTUNE)

六、搭建CNN网络

# 网络模型
def vgg_net(num_layer,filter):
    blk = Sequential()
    for _ in range(num_layer):
        blk.add(Conv2D(filters=filter,kernel_size=3,padding='same',activation='relu'))
    blk.add(MaxPool2D(pool_size=(2,2),strides=2))
    return blk

conv_arch = [(2,64),(2,128),(3,256),(3,512),(3,512)]
# model = Sequential([Conv2D(filters=64,kernel_size=3,padding='same',activation='relu',input_shape=(224,224,1))])
model = Sequential()
for num_layer,filter in conv_arch:
    model.add(vgg_net(num_layer,filter))
# print(model.summary())
model.add(Sequential([
    Flatten(),
    Dense(4096,activation='relu'),
    Dropout(0.5),
    Dense(4096,activation='relu'),
    Dropout(0.5),
    Dense(len(class_names),activation='softmax')
]))

x = tf.random.uniform((1,224,224,3))
y = model(x)
print('y',y)
print(model.summary())
model.compile(optimizer="adam",
              loss     ='sparse_categorical_crossentropy',
              metrics  =['accuracy'])
from tqdm import tqdm
import tensorflow.keras.backend as K

epochs = 10
lr = 1e-4

# 记录训练数据,方便后面的分析
history_train_loss = []
history_train_accuracy = []
history_val_loss = []
history_val_accuracy = []

for epoch in range(epochs):
    train_total = len(train_ds)
    val_total = len(val_ds)

    """
    total:预期的迭代数目
    ncols:控制进度条宽度
    mininterval:进度更新最小间隔,以秒为单位(默认值:0.1)
    """
    with tqdm(total=train_total, desc=f'Epoch {epoch + 1}/{epochs}', mininterval=1, ncols=100) as pbar:

        lr = lr * 0.92
        K.set_value(model.optimizer.lr, lr)

        for image, label in train_ds:
            """
            训练模型,简单理解train_on_batch就是:它是比model.fit()更高级的一个用法

            想详细了解 train_on_batch 的同学,
            可以看看我的这篇文章:https://www.yuque.com/mingtian-fkmxf/hv4lcq/ztt4gy
            """
            history = model.train_on_batch(image, label)

            train_loss = history[0]
            train_accuracy = history[1]

            pbar.set_postfix({"loss": "%.4f" % train_loss,
                              "accuracy": "%.4f" % train_accuracy,
                              "lr": K.get_value(model.optimizer.lr)})
            pbar.update(1)
        history_train_loss.append(train_loss)
        history_train_accuracy.append(train_accuracy)

    print('开始验证!')

    with tqdm(total=val_total, desc=f'Epoch {epoch + 1}/{epochs}', mininterval=0.3, ncols=100) as pbar:

        for image, label in val_ds:
            history = model.test_on_batch(image, label)

            val_loss = history[0]
            val_accuracy = history[1]

            pbar.set_postfix({"loss": "%.4f" % val_loss,
                              "accuracy": "%.4f" % val_accuracy})
            pbar.update(1)
        history_val_loss.append(val_loss)
        history_val_accuracy.append(val_accuracy)

    print('结束验证!')
    print("验证loss为:%.4f" % val_loss)
    print("验证准确率为:%.4f" % val_accuracy)
Epoch 1/10: 100%|██████████| 85/85 [00:56<00:00,  1.50it/s, loss=0.6747, accuracy=0.5938, lr=9.2e-5]
Epoch 1/10:   0%|                                                            | 0/22 [00:00<?, ?it/s]开始验证!
Epoch 1/10: 100%|█████████████████████| 22/22 [00:05<00:00,  4.03it/s, loss=0.6325, accuracy=1.0000]
Epoch 2/10:   0%|                                                            | 0/85 [00:00<?, ?it/s]结束验证!
验证loss为:0.6325
验证准确率为:1.0000
Epoch 2/10: 100%|█████████| 85/85 [00:57<00:00,  1.48it/s, loss=0.5680, accuracy=0.6562, lr=8.46e-5]
Epoch 2/10:   0%|                                                            | 0/22 [00:00<?, ?it/s]开始验证!
Epoch 2/10: 100%|█████████████████████| 22/22 [00:06<00:00,  3.66it/s, loss=0.4805, accuracy=0.8750]
Epoch 3/10:   0%|                                                            | 0/85 [00:00<?, ?it/s]结束验证!
验证loss为:0.4805
验证准确率为:0.8750
Epoch 3/10: 100%|█████████| 85/85 [01:07<00:00,  1.26it/s, loss=0.5843, accuracy=0.7188, lr=7.79e-5]
开始验证!
Epoch 3/10: 100%|█████████████████████| 22/22 [00:04<00:00,  5.15it/s, loss=0.5533, accuracy=0.7500]
Epoch 4/10:   0%|                                                            | 0/85 [00:00<?, ?it/s]结束验证!
验证loss为:0.5533
验证准确率为:0.7500
Epoch 4/10: 100%|█████████| 85/85 [01:06<00:00,  1.28it/s, loss=0.0835, accuracy=0.9688, lr=7.16e-5]
Epoch 4/10:   0%|                                                            | 0/22 [00:00<?, ?it/s]开始验证!
Epoch 4/10: 100%|█████████████████████| 22/22 [00:05<00:00,  4.24it/s, loss=0.0185, accuracy=1.0000]
Epoch 5/10:   0%|                                                            | 0/85 [00:00<?, ?it/s]结束验证!
验证loss为:0.0185
验证准确率为:1.0000
Epoch 5/10: 100%|█████████| 85/85 [01:09<00:00,  1.22it/s, loss=0.0667, accuracy=0.9688, lr=6.59e-5]
Epoch 5/10:   0%|                                                            | 0/22 [00:00<?, ?it/s]开始验证!
Epoch 5/10: 100%|█████████████████████| 22/22 [00:05<00:00,  3.74it/s, loss=0.0099, accuracy=1.0000]
Epoch 6/10:   0%|                                                            | 0/85 [00:00<?, ?it/s]结束验证!
验证loss为:0.0099
验证准确率为:1.0000
Epoch 6/10: 100%|█████████| 85/85 [01:14<00:00,  1.14it/s, loss=0.0395, accuracy=0.9688, lr=6.06e-5]
Epoch 6/10:   0%|                                                            | 0/22 [00:00<?, ?it/s]开始验证!
Epoch 6/10: 100%|█████████████████████| 22/22 [00:05<00:00,  3.77it/s, loss=0.0012, accuracy=1.0000]
Epoch 7/10:   0%|                                                            | 0/85 [00:00<?, ?it/s]结束验证!
验证loss为:0.0012
验证准确率为:1.0000
Epoch 7/10: 100%|█████████| 85/85 [01:14<00:00,  1.14it/s, loss=0.0461, accuracy=1.0000, lr=5.58e-5]
Epoch 7/10:   0%|                                                            | 0/22 [00:00<?, ?it/s]开始验证!
Epoch 7/10: 100%|█████████████████████| 22/22 [00:05<00:00,  3.80it/s, loss=0.0012, accuracy=1.0000]
结束验证!
验证loss为:0.0012
验证准确率为:1.0000
Epoch 8/10: 100%|█████████| 85/85 [01:16<00:00,  1.10it/s, loss=0.0364, accuracy=1.0000, lr=5.13e-5]
Epoch 8/10:   0%|                                                            | 0/22 [00:00<?, ?it/s]开始验证!
Epoch 8/10: 100%|█████████████████████| 22/22 [00:05<00:00,  3.68it/s, loss=0.0031, accuracy=1.0000]
Epoch 9/10:   0%|                                                            | 0/85 [00:00<?, ?it/s]结束验证!
验证loss为:0.0031
验证准确率为:1.0000
Epoch 9/10: 100%|█████████| 85/85 [01:16<00:00,  1.11it/s, loss=0.0117, accuracy=1.0000, lr=4.72e-5]
开始验证!
Epoch 9/10: 100%|█████████████████████| 22/22 [00:06<00:00,  3.23it/s, loss=0.0005, accuracy=1.0000]
Epoch 10/10:   0%|                                                           | 0/85 [00:00<?, ?it/s]结束验证!
验证loss为:0.0005
验证准确率为:1.0000
Epoch 10/10: 100%|████████| 85/85 [01:16<00:00,  1.12it/s, loss=0.0004, accuracy=1.0000, lr=4.34e-5]
Epoch 10/10:   0%|                                                           | 0/22 [00:00<?, ?it/s]开始验证!
Epoch 10/10: 100%|████████████████████| 22/22 [00:05<00:00,  3.77it/s, loss=0.0008, accuracy=1.0000]
结束验证!
验证loss为:0.0008
验证准确率为:1.0000

七、绘制损失函数图像和准确度图像

绘制代码与前几周相同

# 画准确度图
epochs_range = range(epochs)

plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)

plt.plot(epochs_range, history_train_accuracy, label='Training Accuracy')
plt.plot(epochs_range, history_val_accuracy, label='Validation Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')

plt.subplot(1, 2, 2)
plt.plot(epochs_range, history_train_loss, label='Training Loss')
plt.plot(epochs_range, history_val_loss, label='Validation Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()

在这里插入图片描述

以上就是我本周的学习内容
在这里插入图片描述

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是使用TensorFlow实现猫狗识别的代码示例: ```python import tensorflow as tf from tensorflow.keras.preprocessing.image import ImageDataGenerator # 定义训练集和验证集的路径 train_dir = '/path/to/train' validation_dir = '/path/to/validation' # 进行数据增强 train_datagen = ImageDataGenerator( rescale=1./255, rotation_range=40, width_shift_range=0.2, height_shift_range=0.2, shear_range=0.2, zoom_range=0.2, horizontal_flip=True, fill_mode='nearest' ) test_datagen = ImageDataGenerator(rescale=1./255) # 定义训练集和验证集的生成器 train_generator = train_datagen.flow_from_directory( train_dir, target_size=(150, 150), batch_size=20, class_mode='binary' ) validation_generator = test_datagen.flow_from_directory( validation_dir, target_size=(150, 150), batch_size=20, class_mode='binary' ) # 构建模型 model = tf.keras.models.Sequential([ tf.keras.layers.Conv2D(32, (3,3), activation='relu', input_shape=(150, 150, 3)), tf.keras.layers.MaxPooling2D(2,2), tf.keras.layers.Conv2D(64, (3,3), activation='relu'), tf.keras.layers.MaxPooling2D(2,2), tf.keras.layers.Conv2D(128, (3,3), activation='relu'), tf.keras.layers.MaxPooling2D(2,2), tf.keras.layers.Conv2D(128, (3,3), activation='relu'), tf.keras.layers.MaxPooling2D(2,2), tf.keras.layers.Flatten(), tf.keras.layers.Dense(512, activation='relu'), tf.keras.layers.Dense(1, activation='sigmoid') ]) # 编译模型 model.compile(loss='binary_crossentropy', optimizer=tf.keras.optimizers.RMSprop(lr=1e-4), metrics=['accuracy']) # 训练模型 history = model.fit( train_generator, steps_per_epoch=100, epochs=100, validation_data=validation_generator, validation_steps=50, verbose=2 ) ``` 在上述代码中,我们使用了TensorFlow的`ImageDataGenerator`来进行数据增强,从而提高模型的泛化能力。然后,我们定义了训练集和验证集的生成器,并使用这些生成器训练我们的模型。模型的结构为4个卷积层和2个全连接层,使用了ReLU作为激活函数,并在输出层使用了sigmoid函数作为二元分类器的激活函数。最后,我们使用了RMSprop优化器和二元交叉熵作为损失函数进行模型的编译和训练。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

降花绘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值