活动地址:CSDN21天学习挑战赛
目录
1.跑通代码
2.代码分析
2.1
2.2
2.3
2.4
2.5
2.6
3.补充
tensorflow零基础入门学习_重邮研究森的博客-CSDN博客_tensorflow 学习https://blog.csdn.net/m0_60524373/article/details/124143223>- 本文为[365天深度学习训练营](https://mp.weixin.qq.com/s/k-vYaC8l7uxX51WoypLkTw) 中的学习记录博客
>- 参考文章地址: [深度学习100例-卷积神经网络(CNN)识别眼睛状态 | 第17天](深度学习100例-卷积神经网络(CNN)识别眼睛状态 | 第17天_K同学啊的博客-CSDN博客)
本文开发环境:tensorflowgpu2.5,经过验证,2.4也可以运行
我这个人对于任何代码,我都会先去跑通之和才会去观看内容,哈哈哈,所以第一步我们先不管37=21,直接把博主的代码复制黏贴一份运行结果。(PS:做了一些修改,因为原文是jupyter,而我在pycharm)
model.py(生成模型文件)
import tensorflow as tf
gpus = tf.config.list_physical_devices("GPU")
if gpus:
tf.config.experimental.set_memory_growth(gpus[0], True) #设置GPU显存用量按需使用
tf.config.set_visible_devices([gpus[0]],"GPU")
# 打印显卡信息,确认GPU可用
print(gpus)
import os,PIL
os.environ['TF_XLA_FLAGS'] = '--tf_xla_enable_xla_devices'
os.environ['TF_CPP_MIN_LOG_LEVEL']='2'
from tensorflow import keras
keras.backend.clear_session()
import matplotlib.pyplot as plt
# 支持中文
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
# 设置随机种子尽可能使结果可以重现
import numpy as np
np.random.seed(1)
# 设置随机种子尽可能使结果可以重现
import tensorflow as tf
tf.random.set_seed(1)
import pathlib
data_dir ="E:/2021_Project_YanYiXia/AI/21/卷积神经网络识别眼睛状态/017_Eye_dataset"
data_dir = pathlib.Path(data_dir)
image_count = len(list(data_dir.glob('*/*')))
print("图片总数为:",image_count)
batch_size = 64
img_height = 224
img_width = 224
"""
关于image_dataset_from_directory()的详细介绍可以参考文章:https://mtyjkh.blog.csdn.net/article/details/117018789
"""
train_ds = tf.keras.preprocessing.image_dataset_from_directory(
data_dir,
validation_split=0.2,
subset="training",
seed=12,
image_size=(img_height, img_width),
batch_size=batch_size)
"""
关于image_dataset_from_directory()的详细介绍可以参考文章:https://mtyjkh.blog.csdn.net/article/details/117018789
"""
val_ds = tf.keras.preprocessing.image_dataset_from_directory(
data_dir,
validation_split=0.2,
subset="validation",
seed=12,
image_size=(img_height, img_width),
batch_size=batch_size)
class_names = train_ds.class_names
print(class_names)
plt.figure(figsize=(10, 5)) # 图形的宽为10高为5
plt.suptitle("数据展示")
# for images, labels in train_ds.take(1):
# for i in range(8):
# ax = plt.subplot(2, 4, i + 1)
#
# ax.patch.set_facecolor('yellow')
#
# plt.imshow(images[i].numpy().astype("uint8"))
# plt.title(class_names[labels[i]])
#
# plt.axis("off")
for image_batch, labels_batch in train_ds:
print(image_batch.shape)
print(labels_batch.shape)
break
AUTOTUNE = tf.data.AUTOTUNE
train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)
val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)
model = tf.keras.applications.VGG16()
# # 打印模型信息
model.summary()
# 设置初始学习率
initial_learning_rate = 1e-4
lr_schedule = tf.keras.optimizers.schedules.ExponentialDecay(
initial_learning_rate,
decay_steps=20, # 敲黑板!!!这里是指 steps,不是指epochs
decay_rate=0.96, # lr经过一次衰减就会变成 decay_rate*lr
staircase=True)
# 将指数衰减学习率送入优化器
optimizer = tf.keras.optimizers.Adam(learning_rate=lr_schedule)
model.compile(optimizer=optimizer,
loss ='sparse_categorical_crossentropy',
metrics =['accuracy'])
epochs = 10
history = model.fit(
train_ds,
validation_data=val_ds,
epochs=epochs
)
# 保存模型
model.save('model/17_model.h5')
acc = history.history['accuracy']
val_acc = history.history['val_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs_range = range(epochs)
plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)
plt.plot(epochs_range, acc, label='Training Accuracy')
plt.plot(epochs_range, val_acc, label='Validation Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')
plt.subplot(1, 2, 2)
plt.plot(epochs_range, loss, label='Training Loss')
plt.plot(epochs_range, val_loss, label='Validation Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()
main.py(加载模型,进行预测)
import tensorflow as tf
gpus = tf.config.list_physical_devices("GPU")
if gpus:
tf.config.experimental.set_memory_growth(gpus[0], True) #设置GPU显存用量按需使用
tf.config.set_visible_devices([gpus[0]],"GPU")
# 打印显卡信息,确认GPU可用
print(gpus)
import os,PIL
os.environ['TF_XLA_FLAGS'] = '--tf_xla_enable_xla_devices'
os.environ['TF_CPP_MIN_LOG_LEVEL']='2'
from tensorflow import keras
keras.backend.clear_session()
import matplotlib.pyplot as plt
# 支持中文
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
# 设置随机种子尽可能使结果可以重现
import numpy as np
np.random.seed(1)
# 设置随机种子尽可能使结果可以重现
import tensorflow as tf
tf.random.set_seed(1)
import pathlib
data_dir ="E:/2021_Project_YanYiXia/AI/21/卷积神经网络识别眼睛状态/017_Eye_dataset"
data_dir = pathlib.Path(data_dir)
image_count = len(list(data_dir.glob('*/*')))
print("图片总数为:",image_count)
batch_size = 64
img_height = 224
img_width = 224
"""
关于image_dataset_from_directory()的详细介绍可以参考文章:https://mtyjkh.blog.csdn.net/article/details/117018789
"""
train_ds = tf.keras.preprocessing.image_dataset_from_directory(
data_dir,
validation_split=0.2,
subset="training",
seed=12,
image_size=(img_height, img_width),
batch_size=batch_size)
"""
关于image_dataset_from_directory()的详细介绍可以参考文章:https://mtyjkh.blog.csdn.net/article/details/117018789
"""
val_ds = tf.keras.preprocessing.image_dataset_from_directory(
data_dir,
validation_split=0.2,
subset="validation",
seed=12,
image_size=(img_height, img_width),
batch_size=batch_size)
class_names = train_ds.class_names
print(class_names)
plt.figure(figsize=(10, 5)) # 图形的宽为10高为5
plt.suptitle("数据展示")
# for images, labels in train_ds.take(1):
# for i in range(8):
# ax = plt.subplot(2, 4, i + 1)
#
# ax.patch.set_facecolor('yellow')
#
# plt.imshow(images[i].numpy().astype("uint8"))
# plt.title(class_names[labels[i]])
#
# plt.axis("off")
for image_batch, labels_batch in train_ds:
print(image_batch.shape)
print(labels_batch.shape)
break
AUTOTUNE = tf.data.AUTOTUNE
train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)
val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)
# 加载模型
new_model = tf.keras.models.load_model('model/17_model.h5')
# 采用加载的模型(new_model)来看预测结果
plt.figure(figsize=(10, 5)) # 图形的宽为10高为5
plt.suptitle("预测结果展示")
for images, labels in val_ds.take(1):
for i in range(8):
ax = plt.subplot(2, 4, i + 1)
# 显示图片
plt.imshow(images[i].numpy().astype("uint8"))
# 需要给图片增加一个维度
img_array = tf.expand_dims(images[i], 0)
# 使用模型预测图片中的人物
predictions = new_model.predict(img_array)
plt.title(class_names[np.argmax(predictions)])
plt.axis("off")
plt.show()
先运行model文件,即可生成模型,然后运行main文件即可运行出最后的预测结果!
神经网络的整个过程我分为如下六部分,而我们也会对这六部分进行逐部分分析。那么这6部分分别是:
六步法:
1->import
2->train test(指定训练集的输入特征和标签)
3->class MyModel(model) model=Mymodel(搭建网络结构,逐层描述网络)
4->model.compile(选择哪种优化器,损失函数)
5->model.fit(执行训练过程,输入训练集和测试集的特征+标签,batch,迭代次数)
6->验证
导入:这里很容易理解,也就是导入本次实验内容所需要的各种库。在本案例中主要包括以下部分:
注意事项:这里我们发现比和普通代码多了两句os.environ。这是因为当时运行的时候有个报错,我去网上找的解决办法,但是不写两句也可以训练模型(tensorflow只要不影响训练,可以不管)
蓝框1:
设置GPU各种方式,直接复制即可
篮筐2:
参考注意事项
蓝框3:
这里是我开始运行的时候,由于数据集太大了,我的电脑跑不了,然后据说这句话可以清楚缓存什么的,但是我最后的解决部分是删除部分数据集
蓝框4:
设置图片的中文显示设置
对于这里的话我们可以直接复制黏贴,当需要一些其他函数时,只需要添加对应的库文件即可。
设置训练集和测试集:对于神经网络的训练包括了两种数据集合,一个是训练集,一个是测试集。其中训练集数据较多,测试集较少,因为训练一个模型数据越多相对的模型更准确。
本文中利用的数据集在文章下方,该数据集是一个眼睛转向的灰色图像数据集合
本文中数据集处理较为复杂,包括了随机数,显示图片,数据集设置等,我们将分别对代码进行解释
蓝框1:
为随机数种子的设置,神经网络的方法起始我感觉就是扩展变量法,所以为了保证初始情况都一样,因此设置随机数种子。
蓝框2:
本文数据集和之前数字识别和服装识别利用的minist数据集不一样,是存在与本地文件夹中,因此这里数据集的调用方法也不一样。这里利用了文件夹函数,首先找到数据集的路径,然后通过函数设置路径文件夹,相当于图中的data_dir就是数据集的位置了
蓝框3:
取上诉data_dir文件夹中所有的文件,因为data_dir是一个文件夹,我们现在取这个文件夹下所有文件,并且输出数量
蓝框4:
设置图片的长和宽为224x224,以及batch_size为64,batch_size的意思是:每次训练时,我们投入64个图片为一次的数据
这里就是设置训练集和测试集了。利用了image_dataset_from_directory()
很明显可以看出来,这是一个图像数据来自文件夹函数。而这个文件夹就是data_dir。
蓝框1:
为训练集dataset的设置
蓝框2:
为测试集dataset的设置
蓝框3:
利用该函数下,可以调用一个标签函数,输出标签的类型。
蓝框1:
输出现在的训练集,打印现在它的形状看是否满足我们的设置
蓝框2:
这里是对数据进行乱序,以及加速数据的处理。其中第一句是自动设置线程数量的意思,cache是为了把数据丢入缓存中,其实不要这个框也没事。
到这里,数据集的设置就结束了。我们可以发现相对于来说,代码多了很多,而这是因为数据集来源不一样,以及对于数据显示我们多显示了一下。但核心内容还是设置数据集
注意事项:对于数据集像是一个文件夹下又分几个文件夹,文件夹就是标签的话,采用该函数进行分类。而如果是一个文件夹下,文件名字是其标签,采用另外一种方式,可以参考我的验证码识别文章
网络模型搭建:这里也是神经网络的重点了!废话不多说,直接开始!
本文的神经网络的结构图如下:
对于这个类似官方模型,我们不需要自己设置(也可以手动按图片进行设置),直接调用该模块即可。
# 加载模型
new_model = tf.keras.models.load_model('model/17_model.h5')
但是有两个重要的地方需要注意,一个是输入的设置和输出的设置。
输入:
我们看到输入图片的要求是224x224x3的,这也是为什么我们要设置图片的格式为这么大,而3是通道数的意思,我们在 image_dataset_from_directory()下面进行了设置。
输出:
这里输出是1000,可我们的数据类型明明只有4类,这是为什么呢?其实是因为它把4分为了1000,在1000里面找到数最大的那个,得到的4种中的某一个,当然了,你可以修改vgg16,得到输出为4的,也就是在最后一层加一个dense层
到此,网络模型我们变分析完了。
该部分也同样重要,主要完成模型训练过程中的优化器,损失函数,准确率的设置。
我们结合本文来看。
其中:对于这部分内容的含义可以参考我的文章开头的另外一篇基础博文进行了详细的介绍。
注意事项:我们注意到,这里和我们之前使用方式不一样,这是因为我们采用了动态学习率的设置,利用
tf.keras.optimizers.schedules.ExponentialDecay实现。因为前面刚学习时,可以慢点,学的更充分,到了后面可以快点!。
该部分就是执行训练了,那么执行训练肯定需要设置训练集数据及其标签,测试集数据及其标签,训练的epoch
当训练执行完毕,我们就可以拿一个测试集合中或者其他满足格式的数据进行验证了
这里就是绘制训练集和测试集的准确率和损失函数图像
可以看到效果极差,这是因为我的电脑GOU更不上了,只能把1000张的数据集改为100,从而实现“能够训练”。
我们取测试集合的前6张图片进行验证,代码在main文件中
可以看到这个训练没任何意义!哈哈哈,电脑问题,没办法!
今天引入一个新东西,可以方便我们进行查看测试集合。名字叫做混淆矩阵!
话不多说,先上图。下图就是混淆矩阵画出来的预测值
从上图中我们可以看出,预测和真实值清晰明了的放出来了,但是可惜我们这个本来模型准确率不敢苟同,所以效果差,但这不影响我们简单的使用,代码我放在下面了。
from sklearn.metrics import confusion_matrix
import seaborn as sns
import pandas as pd
# 定义一个绘制混淆矩阵图的函数
def plot_cm(labels, predictions):
# 生成混淆矩阵
conf_numpy = confusion_matrix(labels, predictions)
# 将矩阵转化为 DataFrame
conf_df = pd.DataFrame(conf_numpy, index=class_names, columns=class_names)
plt.figure(figsize=(8, 7))
sns.heatmap(conf_df, annot=True, fmt="d", cmap="BuPu")
plt.title('混淆矩阵', fontsize=15)
plt.ylabel('真实值', fontsize=14)
plt.xlabel('预测值', fontsize=14)
plt.show()
val_pre = []
val_label = []
for images, labels in val_ds:#这里可以取部分验证数据(.take(1))生成混淆矩阵
for image, label in zip(images, labels):
# 需要给图片增加一个维度
img_array = tf.expand_dims(image, 0)
# 使用模型预测图片中的人物
prediction = model.predict(img_array)
val_pre.append(class_names[np.argmax(prediction)])
val_label.append(class_names[label])
plot_cm(val_label, val_pre)
plt.show()