欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

TensorFlow入门教程(21)分心驾驶行为检测

程序员文章站 2022-07-11 23:47:16
...

#
#作者:韦访
#博客:https://blog.csdn.net/rookie_wei
#微信:1007895847
#添加微信的备注一下是CSDN的
#欢迎大家一起学习
#

1、概述

通过前面20讲的内容,应该对TensorFlow有一点了解了。很久没更新博客了,现在早已换了人间,已经开始属于TensorFlow2的时代了。那么,这讲就做个分心驾驶行为检测来初识TensorFlow2,顺便学习怎么通过微调别人的模型来用到自己的任务中。

环境配置:

操作系统:Win10 64位

显卡:GTX 1080ti

Python:Python3.7

TensorFlow:2.3.0

2、数据集

我们这里用kaggle的state-farm-distracted-driver-detection数据集。网址如***册个账号就可以下载了:

https://www.kaggle.com/c/state-farm-distracted-driver-detection

下载完数据集以后,解压,根目录得到一个文件夹个两个文件。

TensorFlow入门教程(21)分心驾驶行为检测

先来看文件夹下有什么。

TensorFlow入门教程(21)分心驾驶行为检测

根据以往的经验,根据文件名大致也能猜出,test用于测试的,train用于训练的。先来看train文件夹,

TensorFlow入门教程(21)分心驾驶行为检测

TensorFlow入门教程(21)分心驾驶行为检测

Train文件夹下共有10个子文件夹,每个子文件夹下的图片属于同类,每类共有两千多张图片。这10类及其含义如下:

  • c0: safe driving
  • c1: texting - right
  • c2: talking on the phone - right
  • c3: texting - left
  • c4: talking on the phone - left
  • c5: operating the radio
  • c6: drinking
  • c7: reaching behind
  • c8: hair and makeup
  • c9: talking to passenger

再来看test文件夹,

TensorFlow入门教程(21)分心驾驶行为检测

Test文件夹下直接是图片,接近8万张,但是每个文件分别属于哪类并不知道。

一般需要有个验证集来验证模型准确率,而且验证集的数据不能是训练集里的数据,所以我们新建一个valid的文件夹,跟train文件夹一样包含10个文件名为c0到c9的子文件夹,

为了简单起见,将train文件夹下的每个子文件夹下的30张图片剪切到valid文件夹下对应的子文件夹。

TensorFlow入门教程(21)分心驾驶行为检测

TensorFlow入门教程(21)分心驾驶行为检测

这样,我们就做好了验证集。

3、导入数据

数据集做好以后,我们就来写代码,导入它们。使用image_dataset_from_directory函数很容易就可以导入了,比较简单,代码如下,

import matplotlib.pyplot as plt
import numpy as np
import os
import tensorflow as tf

from tensorflow.keras.preprocessing import image_dataset_from_directory

# 数据集中的训练和验证数据集
ROOT_DIR = "./dataset"
train_dir = os.path.join(ROOT_DIR, 'train')
valid_dir = os.path.join(ROOT_DIR, 'valid')


# 设置送入模型的图片的尺寸
IMG_SIZE = (160, 160)
# 因为我们验证集中每类只有30张图片,所以这里batch size就设置得小些,直接设置成10就好了
train_dataset = image_dataset_from_directory(train_dir, shuffle=True, batch_size=32, image_size=IMG_SIZE)
valid_dataset = image_dataset_from_directory(train_dir, shuffle=True, batch_size=10, image_size=IMG_SIZE)

# 默认文件名即为我们的类别名,这里打印出来看看
class_names = train_dataset.class_names
num_classes = len(class_names)
print(class_names)
print(valid_dataset.class_names)

# prefetch提供了pipeline的方式读取数据,更高效
# 参考: https://tensorflow.google.cn/guide/data_performance
AUTOTUNE = tf.data.experimental.AUTOTUNE
train_dataset = train_dataset.prefetch(buffer_size=AUTOTUNE)
valid_dataset = valid_dataset.prefetch(buffer_size=AUTOTUNE)

# 把它们显示出来看看对不对
plt.figure(figsize=(10, 10))
for images, labels in train_dataset.take(1):
  for i in range(9):
    ax = plt.subplot(3, 3, i + 1)
    plt.imshow(images[i].numpy().astype("uint8"))
    plt.title(class_names[labels[i]])
    plt.axis("off")

plt.show()

运行结果如下,

TensorFlow入门教程(21)分心驾驶行为检测

TensorFlow入门教程(21)分心驾驶行为检测

4、导入MobileNetV2模型

因为这里做的是分类任务,分类任务中有很多优秀、成熟的网络,比如MobileNet,VGG,ResNet等等,我们直接拿来用就好了,而且我们也不需要从头到尾自己训练,可以用别人通过ImageNet这种大型数据集训练好的模型。我们这里使用MobileNet网络,TensorFlow2也集成了这些API,很方便调用,代码如下,

#Create the base model from the pre-trained model MobileNet V2
IMG_SHAPE = IMG_SIZE + (3,)
base_model = tf.keras.applications.MobileNetV2(input_shape=IMG_SHAPE, include_top=False, weights='imagenet')
base_model.summary()

如果第一次运行,TensorFlow会自动将已经训练好的网络下载并加载。通过summary函数就可以打印网络结构。运行结果如下,

TensorFlow入门教程(21)分心驾驶行为检测

5、构建网络

上面的MobileNet网络只是我们网络中的一部分,所以现在我们要结合它来构建我们的网络,

# 数据增强操作
data_augmentation = tf.keras.Sequential([
  tf.keras.layers.experimental.preprocessing.RandomFlip('horizontal'),
  tf.keras.layers.experimental.preprocessing.RandomRotation(0.2),
])

# 数据进入MobileNetV2之前要先经过preprocess_input处理
preprocess_input = tf.keras.applications.mobilenet_v2.preprocess_input
# 全局平均池化层,参考: https://www.cnblogs.com/hutao722/p/10008581.html
global_average_layer = tf.keras.layers.GlobalAveragePooling2D()
# 输出层
prediction_layer = tf.keras.layers.Dense(num_classes)
# 输入
inputs = tf.keras.Input(shape=IMG_SHAPE)
x = data_augmentation(inputs)
x = preprocess_input(x)
x = base_model(x, training=False)
x = global_average_layer(x)
x = tf.keras.layers.Dropout(0.2)(x)
outputs = prediction_layer(x)
model = tf.keras.Model(inputs, outputs)
# 让MobileNetV2变得可训练
base_model.trainable = True
# 但是,前100层的参数让它冻结,我们只训练后面层的参数
fine_tune_at = 100
# Freeze all the layers before the `fine_tune_at` layer
for layer in base_model.layers[:fine_tune_at]:
  layer.trainable =  False

6、定义损失函数,优化器

接下来定义损失函数和优化器,

# 定义损失函数
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)
# 定义学习率
base_learning_rate = 0.00001
# 定义优化器
optimizer = tf.keras.optimizers.RMSprop(lr=base_learning_rate)

7、训练和保存模型

最后,训练和保存模型即可,

model.compile(loss=loss,
              optimizer = optimizer,
              metrics=['accuracy'])

# 开始训练
total_epochs =  50
history = model.fit(train_dataset,
                    epochs=total_epochs,
                    validation_data=valid_dataset)


# 在验证集里验证模型准确率
loss0, accuracy0 = model.evaluate(valid_dataset)
print("initial loss: {:.2f}".format(loss0))
print("initial accuracy: {:.2f}".format(accuracy0))

# 模型保存路径
MODEL_DIR = "./models/"
if not os.path.exists(MODEL_DIR):
  os.makedirs(MODEL_DIR)

# 保存模型
h5_dir = os.path.join(MODEL_DIR, 'ddd_mobilenet_v2.h5')
model.save(h5_dir)

# 我们将保持好的模型再导入,再在验证集里查看它的准确率
new_model = tf.keras.models.load_model(h5_dir)
for images, labels in valid_dataset.take(1):
  for i in range(10):
    img = np.expand_dims(images[i], axis=0)
    predictions = new_model.predict(img)    
    predictions = np.argmax(predictions[0])
    print("pred:", class_names[predictions], " label:" , class_names[labels[i]])

运行结果,

TensorFlow入门教程(21)分心驾驶行为检测

可以看到,在训练集中的准确率能到99.58%,在测试集中的准确率为98.72%。

8、完整代码

完整代码链接如下,

https://mianbaoduo.com/o/bread/aZqUkpY=