TensorFlow入门教程(21)分心驾驶行为检测
#
#作者:韦访
#博客: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
下载完数据集以后,解压,根目录得到一个文件夹个两个文件。
先来看文件夹下有什么。
根据以往的经验,根据文件名大致也能猜出,test用于测试的,train用于训练的。先来看train文件夹,
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文件夹,
Test文件夹下直接是图片,接近8万张,但是每个文件分别属于哪类并不知道。
一般需要有个验证集来验证模型准确率,而且验证集的数据不能是训练集里的数据,所以我们新建一个valid的文件夹,跟train文件夹一样包含10个文件名为c0到c9的子文件夹,
为了简单起见,将train文件夹下的每个子文件夹下的30张图片剪切到valid文件夹下对应的子文件夹。
这样,我们就做好了验证集。
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()
运行结果如下,
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函数就可以打印网络结构。运行结果如下,
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]])
运行结果,
可以看到,在训练集中的准确率能到99.58%,在测试集中的准确率为98.72%。
8、完整代码
完整代码链接如下,
上一篇: 深度模型调参
下一篇: 【时间序列】ARIMA模型做分类