基于Keras的交通标志识别

腾讯云
入门
0 个任务
剩余 1 个名额

你还可以 创建 或者 使用已有 云主机不限时上机

实验内容

交通领域中由于摄像头的大量使用,人工智能的图像处理算法使用广泛,且在特定领域可以实现很好的效果,具备较高的社会价值。本课程将带领大家完成交通标志的识别,应用图像分类模型判断当前图片是否是交通标志,如左转、右转、调头、限行等。我们通过自定义的简单数据集,应用人工智能算法,可以实现较高准确率的输出。

首次可免费使用云主机 2 小时 30 分钟 ,到期后云主机将被重置并退库,若想保留成果请及时留用。

实验资源

云服务器

软件环境

-

目录

# 基于Keras的交通标志识别 ## 1. 实验准备 > <time>4 min</time> ### 1.1 实验背景 近些年AI发展迅猛,已经广泛应用在了很多行业,且近几年已经呈现出了爆发性的增长趋势。 本课程希望能够结合热点,以交通标志识别为出发点,给大家讲解图像分类算法的实现 实验目录在[/traffic_symbol 目录][locate-base]下 该目录下的[/data 文件夹][locate-data]存放实验需要使用到的数据集 我们最终将在该目录下完成train.py,用于完成训练与预测任务 > <locate for="locate-base" path="/traffic_symbol" hint="本课程实验目录"></locate> > <locate for="locate-data" path="/traffic_symbol/data" hint="存放数据集的目录"></locate> ### 1.2 实验步骤 本实验分为训练与测试两个环节 回顾一下前面视频中讲到的训练过程流程及实现: * 解析脚本输入参数:使用argparse解析,由args变量持有 * 创建模型:自定义函数create_model(),返回使用keras.models.Model类创建的实例 * 模型编译:执行Model实例的compile() * 数据增强:自定义函数create_image_generator() * 模型训练与保存:自定义函数train()完成模型训练,使用keras.callbacks.ModelCheckpoint类的实例完成模型保存 回顾一下前面视频中讲到的测试过程流程及实现: * 解析脚本输入参数:使用argparse解析,由args变量持有 * 创建模型:自定义函数create_model() * 模型加载:使用keras.models.load_model() * 数据读取:自定义函数create_image_generator() * 预测与评估:自定义函数test() 在下面输入代码的过程中,可以结合这部分内容进行理解,知识点有遗忘可以重新看一下之前的视频,其中讲解了这些代码的具体实现思路。 ## 2 环境搭建 > <time>16 min</time> ### 2.1 升级pip版本 输入下述命令升级pip ``` python -m pip install --upgrade pip ``` ### 2.2 安装TensorFlow 输入下述命令安装TensorFlow ``` pip install tensorflow==1.14 ``` > <checker type="output-contains" command="pip list | grep tensorflow" hint="安装 TensorFlow"> > <keyword regex="tensorflow" /> > </checker> ### 2.3 安装Keras 输入下述命令安装Keras ``` pip install keras==2.3.1 ``` > <checker type="output-contains" command="pip list | grep Keras" hint="安装 Keras"> > <keyword regex="Keras" /> > </checker> ### 2.4 安装opencv-python 输入下述命令安装opencv-python ``` pip install opencv-python ``` > <checker type="output-contains" command="pip list | grep opencv-python" hint="安装 opencv-python"> > <keyword regex="opencv-python" /> > </checker> ### 2.5 安装numpy 输入下述命令安装numpy ``` pip install numpy==1.19 ``` > <checker type="output-contains" command="pip list | grep numpy" hint="安装 numpy"> > <keyword regex="numpy" /> > </checker> ## 3. 完成训练代码 > <time>40 min</time> ### 3.1 创建文件 进入工程目录 ``` cd /traffic_symbol ``` 创建train.py文件,本实验的后续代码都将在此文件中完成 ``` touch train.py ``` <checker type="output-contains" command="ls /traffic_symbol" hint="请先创建 train.py"> <keyword regex="train.py" /> </checker> ### 3.2 输入引用文件 [打开 train.py][edit-train] > <edit for="edit-train" file="/traffic_symbol/train.py"></edit> 在文件顶部输入下述内容 ```python #! /usr/bin/env python3 # -*- coding: UTF-8 -*- import os import argparse import shutil import cv2 import random import numpy as np import keras from keras.applications.mobilenet import preprocess_input, MobileNet from keras.preprocessing.image import ImageDataGenerator from keras.models import Model, load_model from keras.layers import * from keras.callbacks import ModelCheckpoint ``` 然后保存 保存方法:Windows系统点击Ctrl+s,mac OS点击command+s保存 > <checker type="output-contains" command="tail /traffic_symbol/train.py" hint="完成代码输入"> > <keyword regex="ModelCheckpoint" /> > </checker> ### 3.3 完成模型构建代码 继续在train.py中输入下面的内容 ```python # 创建模型 def create_model(height, width, channel, num_class): # 加载预训练模型 base_model = MobileNet(input_shape=(height, width, channel), weights='imagenet', include_top=False) # 把基础模型后部替换成GAP + FC x = base_model.output x = GlobalAveragePooling2D()(x) x = Dropout(0.5)(x) x = Dense(256, activation='relu')(x) predictions = Dense(num_class, activation='softmax')(x) # 创建模型 return Model(inputs=base_model.input, outputs=predictions) ``` 然后保存 > <checker type="output-contains" command="tail /traffic_symbol/train.py" hint="完成代码输入"> > <keyword regex="base_model.input" /> > </checker> ### 3.4 完成数据处理代码 继续输入下述代码 ```python # 图片增强 def preprocess(image): # 图片格式转换为HSV image = cv2.cvtColor(image, cv2.COLOR_RGB2HSV) # 无关信息增强:随机改变色调、饱和度、明度 h, s, v = cv2.split(image) shift_h = cv2.addWeighted(h, 1, h, 0, random.randint(-10, 10)) shift_hsv = cv2.merge([shift_h, s, v]) image = cv2.cvtColor(shift_hsv, cv2.COLOR_HSV2RGB) brightness = random.randint(-50, 50) contrast = random.uniform(0.8, 1.2) image = cv2.addWeighted(image, contrast, image, 0, brightness) # mobilenet的图片加速处理方式 image = preprocess_input(image) return image # 创建ImageDataGenerator def create_image_generator(args, type): classes = [str(i) for i in range(args.n_classes)] if type == 0: # 训练集数据处理 generator = ImageDataGenerator( preprocessing_function=preprocess, shear_range=0.2, # 裁剪 zoom_range=0.2, # 缩放 rotation_range=20, # 旋转 vertical_flip=False,# 纵向对称变换 horizontal_flip=True# 横向对称变换 ).flow_from_directory( args.dataset + '/train', target_size=(model.inputs[0].shape[1], model.inputs[0].shape[2]), batch_size=args.batch_size, classes=classes, class_mode='categorical' ) elif type == 1: # 验证集集数据处理 generator = ImageDataGenerator( preprocessing_function=preprocess_input # 数据不做任何增强 ).flow_from_directory( args.dataset + '/validation', target_size=(model.inputs[0].shape[1], model.inputs[0].shape[2]), batch_size=args.batch_size, classes=classes, class_mode='categorical', shuffle=False, seed=0 ) return generator ``` 然后保存 > <checker type="output-contains" command="tail /traffic_symbol/train.py" hint="完成代码输入"> > <keyword regex="return generator" /> > </checker> ### 3.5 完成训练流程代码 ```python # 训练模型 def train(args, model): # 训练数据处理 train_generator = create_image_generator(args, 0) # 验证集数据处理 validation_generator = create_image_generator(args, 1) # 编译模型 model.compile(optimizer=keras.optimizers.Adam(), metrics=['accuracy'], loss='categorical_crossentropy') # 模型保存 model_save_path = os.path.join(args.output, 'model.h5') saver = ModelCheckpoint(model_save_path, monitor='val_loss', verbose=1, save_best_only=True) # 开始训练 model.fit_generator( generator=train_generator, epochs=args.epochs, validation_data=validation_generator, callbacks=[saver]) ``` 然后保存 > <checker type="output-contains" command="tail /traffic_symbol/train.py" hint="完成代码输入"> > <keyword regex="model.fit_generator" /> > </checker> ### 3.6 完成参数处理代码 ```python if __name__ == "__main__": # 参数解析 parser = argparse.ArgumentParser() # 定义路径 parser.add_argument("--dataset", type=str, default="./data") parser.add_argument("--output", type=str, default="./results") parser.add_argument("--resume_model_path", type=str, default="") # 定义模型参数 parser.add_argument("--n_classes", type=int, default=2) parser.add_argument("--input_width", type=int, default=128) parser.add_argument("--input_height", type=int, default=128) parser.add_argument("--input_channel", type=int, default=3) # 定义超参数 parser.add_argument("--epochs", type=int, default=5) parser.add_argument("--batch_size", type=int, default=4) # 过程控制。test为0表示训练,test为1表示测试 parser.add_argument("--test", type=int, default=0) args = parser.parse_args() print("args: ", args) # 创建输出路径所指文件夹 os.makedirs(args.output, exist_ok=True) # 创建模型 model = create_model(args.input_height, args.input_width, args.input_channel, args.n_classes) # 打印模型结构 model.summary() # 加载模型 if args.resume_model_path != "": try: model = load_model(args.resume_model_path) except Exception as e: print('No saved model, using init weights!') if args.test: # 预测测试图片 test(args, model) else: # 开始训练 train(args, model) ``` 然后保存 > <checker type="output-contains" command="tail /traffic_symbol/train.py" hint="完成代码输入"> > <keyword regex="args.test" /> > </checker> ## 4. 模型训练 > <time>25 min</time> ### 4.1 使用脚本进行训练 输入下述命令执行脚本训练过程 ``` python train.py ``` 本实验数据较少,训练时间较快,请等待训练完成 你能够看到训练过程输出日志的最后,看到类似下面的结果。 ``` Epoch 1/5 109/109 [==============================] - 18s 165ms/step - loss: 0.6315 - accuracy: 0.7936 - val_loss: 0.7480 - val_accuracy: 0.8750 Epoch 00001: val_loss improved from inf to 0.74797, saving model to ./results/model.h5 Epoch 2/5 109/109 [==============================] - 16s 144ms/step - loss: 0.3618 - accuracy: 0.8601 - val_loss: 0.0037 - val_accuracy: 0.8500 Epoch 00002: val_loss improved from 0.74797 to 0.00373, saving model to ./results/model.h5 Epoch 3/5 109/109 [==============================] - 16s 149ms/step - loss: 0.2079 - accuracy: 0.9243 - val_loss: 0.1375 - val_accuracy: 0.9000 Epoch 00003: val_loss did not improve from 0.00373 Epoch 4/5 109/109 [==============================] - 15s 142ms/step - loss: 0.2598 - accuracy: 0.9266 - val_loss: 0.0314 - val_accuracy: 1.0000 Epoch 00004: val_loss did not improve from 0.00373 Epoch 5/5 109/109 [==============================] - 16s 150ms/step - loss: 0.1935 - accuracy: 0.9335 - val_loss: 0.0285 - val_accuracy: 0.9500 Epoch 00005: val_loss did not improve from 0.00373 ``` 注意:你的数值很可能会给这里给出的数值不相同,并且由于训练过程的随机性,下面两句日志的输出顺序也可能会有差异 ``` val_loss improved from inf to xxx, saving model to ./results/model.h5 val_loss did not improve from xxx ``` 训练完成后,会在 /traffic_symbol/results 下生成model.h5,这是我们训练好的模型 特别说明,model.h5是二级制形式存储的模型文件,且文件较大,请不要直接打开它,避免设备卡住 > <checker type="output-contains" command="ls /traffic_symbol/results" hint="生成model.h5文件"> > <keyword regex="model.h5" /> > </checker> ### 4.2 调整超参数观察输出日志 输入下述命令重新训练模型 ``` python train.py --epochs 1 ``` 观察训练日志输出的val_loss与之前默认的epochs为5时对比,会发现默认参数效果很可能更好一些 将epochs调高,并不会再显著提升val_loss,是因为我们的训练数据较小且任务较为简单(交通标志和非交通标志的图片特征差别明显) > <checker type="output-contains" command="ls /traffic_symbol/results" hint="生成model.h5文件"> > <keyword regex="model.h5" /> > </checker> ## 5. 完成测试代码 > <time>15 min</time> ### 5.1 输入测试数据处理函数 [打开 /traffic_symbol/train.py][edit-train] > <edit for="edit-train" file="/traffic_symbol/train.py"></edit> 找到create_image_generator,在`return generator`前面输入下述代码,`注意缩进` ```python else: # 测试集数据处理 generator = ImageDataGenerator( preprocessing_function=preprocess_input # 数据不做任何增强 ).flow_from_directory( args.dataset + '/test', target_size=(model.inputs[0].shape[1], model.inputs[0].shape[2]), batch_size=args.batch_size, classes=classes, class_mode='categorical', shuffle=False, seed=0 ) ``` 然后保存 > <checker type="output-contains" command="cat /traffic_symbol/train.py" hint="完成代码输入"> > <keyword regex="/test" /> > </checker> ### 5.2 输入测试流程函数 在`if __name__ == "__main__":`前,继续输入下面的代码 ```python # 模型测试 def test(args, model): # 生成结果解析路径 result_folder = args.output + '/test' if os.path.exists(result_folder): shutil.rmtree(result_folder) os.makedirs(result_folder) # 生成测试数据集 test_generator = create_image_generator(args, 2) # 初始化变量 total_images = 0 right_images = 0 n_val_batch = len(test_generator) # 批量预测图片 for b in range(n_val_batch): vx, vy = test_generator.next() pred = model.predict(vx) vy = np.argmax(vy, -1) pred = np.argmax(pred, -1) if test_generator.batch_index > 0: idx = (test_generator.batch_index - 1) * test_generator.batch_size else: idx = (n_val_batch - 1) * test_generator.batch_size files = test_generator.filepaths[idx: idx + test_generator.batch_size] indices = [i for i, v in enumerate(pred) if pred[i] != vy[i]] total_images += len(files) right_images += len(files) - len(indices) for i in range(len(files)): img = cv2.imread(files[i], cv2.IMREAD_UNCHANGED) text = "label" + str(vy[i]) + "_pred" + str(pred[i]) + "_" save_path = os.path.join(result_folder, text + os.path.basename(files[i])) cv2.imwrite(save_path, img) print('accuracy', right_images / total_images) ``` 然后保存 > <checker type="output-contains" command="cat /traffic_symbol/train.py" hint="完成代码输入"> > <keyword regex="def test" /> > </checker> ## 6. 模型测试 > <time>20 min</time> ### 6.1 使用脚本进行测试 输入下述命令 ``` python train.py --test 1 --resume_model_path ./results/model.h5 ``` 等待测试完成,可以看到类似这样的输出 ``` Found 16 images belonging to 2 classes. accuracy 1.0 ``` > <checker type="output-contains" command="ls /traffic_symbol/results" hint="请完成测试任务"> > <keyword regex="test" /> > </checker> ### 6.2 查看测试图片数据结果 打开[test 文件夹][locate-test],查看测试输出图片效果 > <locate for="locate-test" path="/traffic_symbol/results/test" hint="模型测试结果"></locate> 可以在这里看到所有图片的标注和预测结果。 如label0_pred0_43-0-0.jpg,意味着标注类别是0,预测结果0,原图名称是43-0-0.jpg ## 课程学习已完成 > <time>1 min</time> 恭喜,你已经完成了本实验的全部模型训练与预测任务 接下来,你还可以通过修改代码加深对代码的理解 # 基于Keras的交通标志识别 ## 1. 实验准备 > <time>4 min</time> ### 1.1 实验背景 近些年AI发展迅猛,已经广泛应用在了很多行业,且近几年已经呈现出了爆发性的增长趋势。 本课程希望能够结合热点,以交通标志识别为出发点,给大家讲解图像分类算法的实现 实验目录在[/traffic_symbol 目录][locate-base]下 该目录下的[/data 文件夹][locate-data]存放实验需要使用到的数据集 我们最终将在该目录下完成train.py,用于完成训练与预测任务 > <locate for="locate-base" path="/traffic_symbol" hint="本课程实验目录"></locate> > <locate for="locate-data" path="/traffic_symbol/data" hint="存放数据集的目录"></locate> ### 1.2 实验步骤 本实验分为训练与测试两个环节 回顾一下前面视频中讲到的训练过程流程及实现: * 解析脚本输入参数:使用argparse解析,由args变量持有 * 创建模型:自定义函数create_model(),返回使用keras.models.Model类创建的实例 * 模型编译:执行Model实例的compile() * 数据增强:自定义函数create_image_generator() * 模型训练与保存:自定义函数train()完成模型训练,使用keras.callbacks.ModelCheckpoint类的实例完成模型保存 回顾一下前面视频中讲到的测试过程流程及实现: * 解析脚本输入参数:使用argparse解析,由args变量持有 * 创建模型:自定义函数create_model() * 模型加载:使用keras.models.load_model() * 数据读取:自定义函数create_image_generator() * 预测与评估:自定义函数test() 在下面输入代码的过程中,可以结合这部分内容进行理解,知识点有遗忘可以重新看一下之前的视频,其中讲解了这些代码的具体实现思路。 ## 2 环境搭建 > <time>16 min</time> ### 2.1 升级pip版本 输入下述命令升级pip ``` python -m pip install --upgrade pip ``` ### 2.2 安装TensorFlow 输入下述命令安装TensorFlow ``` pip install tensorflow==1.14 ``` > <checker type="output-contains" command="pip list | grep tensorflow" hint="安装 TensorFlow"> > <keyword regex="tensorflow" /> > </checker> ### 2.3 安装Keras 输入下述命令安装Keras ``` pip install keras==2.3.1 ``` > <checker type="output-contains" command="pip list | grep Keras" hint="安装 Keras"> > <keyword regex="Keras" /> > </checker> ### 2.4 安装opencv-python 输入下述命令安装opencv-python ``` pip install opencv-python ``` > <checker type="output-contains" command="pip list | grep opencv-python" hint="安装 opencv-python"> > <keyword regex="opencv-python" /> > </checker> ### 2.5 安装numpy 输入下述命令安装numpy ``` pip install numpy==1.19 ``` > <checker type="output-contains" command="pip list | grep numpy" hint="安装 numpy"> > <keyword regex="numpy" /> > </checker> ## 3. 完成训练代码 > <time>40 min</time> ### 3.1 创建文件 进入工程目录 ``` cd /traffic_symbol ``` 创建train.py文件,本实验的后续代码都将在此文件中完成 ``` touch train.py ``` <checker type="output-contains" command="ls /traffic_symbol" hint="请先创建 train.py"> <keyword regex="train.py" /> </checker> ### 3.2 输入引用文件 [打开 train.py][edit-train] > <edit for="edit-train" file="/traffic_symbol/train.py"></edit> 在文件顶部输入下述内容 ```python #! /usr/bin/env python3 # -*- coding: UTF-8 -*- import os import argparse import shutil import cv2 import random import numpy as np import keras from keras.applications.mobilenet import preprocess_input, MobileNet from keras.preprocessing.image import ImageDataGenerator from keras.models import Model, load_model from keras.layers import * from keras.callbacks import ModelCheckpoint ``` 然后保存 保存方法:Windows系统点击Ctrl+s,mac OS点击command+s保存 > <checker type="output-contains" command="tail /traffic_symbol/train.py" hint="完成代码输入"> > <keyword regex="ModelCheckpoint" /> > </checker> ### 3.3 完成模型构建代码 继续在train.py中输入下面的内容 ```python # 创建模型 def create_model(height, width, channel, num_class): # 加载预训练模型 base_model = MobileNet(input_shape=(height, width, channel), weights='imagenet', include_top=False) # 把基础模型后部替换成GAP + FC x = base_model.output x = GlobalAveragePooling2D()(x) x = Dropout(0.5)(x) x = Dense(256, activation='relu')(x) predictions = Dense(num_class, activation='softmax')(x) # 创建模型 return Model(inputs=base_model.input, outputs=predictions) ``` 然后保存 > <checker type="output-contains" command="tail /traffic_symbol/train.py" hint="完成代码输入"> > <keyword regex="base_model.input" /> > </checker> ### 3.4 完成数据处理代码 继续输入下述代码 ```python # 图片增强 def preprocess(image): # 图片格式转换为HSV image = cv2.cvtColor(image, cv2.COLOR_RGB2HSV) # 无关信息增强:随机改变色调、饱和度、明度 h, s, v = cv2.split(image) shift_h = cv2.addWeighted(h, 1, h, 0, random.randint(-10, 10)) shift_hsv = cv2.merge([shift_h, s, v]) image = cv2.cvtColor(shift_hsv, cv2.COLOR_HSV2RGB) brightness = random.randint(-50, 50) contrast = random.uniform(0.8, 1.2) image = cv2.addWeighted(image, contrast, image, 0, brightness) # mobilenet的图片加速处理方式 image = preprocess_input(image) return image # 创建ImageDataGenerator def create_image_generator(args, type): classes = [str(i) for i in range(args.n_classes)] if type == 0: # 训练集数据处理 generator = ImageDataGenerator( preprocessing_function=preprocess, shear_range=0.2, # 裁剪 zoom_range=0.2, # 缩放 rotation_range=20, # 旋转 vertical_flip=False,# 纵向对称变换 horizontal_flip=True# 横向对称变换 ).flow_from_directory( args.dataset + '/train', target_size=(model.inputs[0].shape[1], model.inputs[0].shape[2]), batch_size=args.batch_size, classes=classes, class_mode='categorical' ) elif type == 1: # 验证集集数据处理 generator = ImageDataGenerator( preprocessing_function=preprocess_input # 数据不做任何增强 ).flow_from_directory( args.dataset + '/validation', target_size=(model.inputs[0].shape[1], model.inputs[0].shape[2]), batch_size=args.batch_size, classes=classes, class_mode='categorical', shuffle=False, seed=0 ) return generator ``` 然后保存 > <checker type="output-contains" command="tail /traffic_symbol/train.py" hint="完成代码输入"> > <keyword regex="return generator" /> > </checker> ### 3.5 完成训练流程代码 ```python # 训练模型 def train(args, model): # 训练数据处理 train_generator = create_image_generator(args, 0) # 验证集数据处理 validation_generator = create_image_generator(args, 1) # 编译模型 model.compile(optimizer=keras.optimizers.Adam(), metrics=['accuracy'], loss='categorical_crossentropy') # 模型保存 model_save_path = os.path.join(args.output, 'model.h5') saver = ModelCheckpoint(model_save_path, monitor='val_loss', verbose=1, save_best_only=True) # 开始训练 model.fit_generator( generator=train_generator, epochs=args.epochs, validation_data=validation_generator, callbacks=[saver]) ``` 然后保存 > <checker type="output-contains" command="tail /traffic_symbol/train.py" hint="完成代码输入"> > <keyword regex="model.fit_generator" /> > </checker> ### 3.6 完成参数处理代码 ```python if __name__ == "__main__": # 参数解析 parser = argparse.ArgumentParser() # 定义路径 parser.add_argument("--dataset", type=str, default="./data") parser.add_argument("--output", type=str, default="./results") parser.add_argument("--resume_model_path", type=str, default="") # 定义模型参数 parser.add_argument("--n_classes", type=int, default=2) parser.add_argument("--input_width", type=int, default=128) parser.add_argument("--input_height", type=int, default=128) parser.add_argument("--input_channel", type=int, default=3) # 定义超参数 parser.add_argument("--epochs", type=int, default=5) parser.add_argument("--batch_size", type=int, default=4) # 过程控制。test为0表示训练,test为1表示测试 parser.add_argument("--test", type=int, default=0) args = parser.parse_args() print("args: ", args) # 创建输出路径所指文件夹 os.makedirs(args.output, exist_ok=True) # 创建模型 model = create_model(args.input_height, args.input_width, args.input_channel, args.n_classes) # 打印模型结构 model.summary() # 加载模型 if args.resume_model_path != "": try: model = load_model(args.resume_model_path) except Exception as e: print('No saved model, using init weights!') if args.test: # 预测测试图片 test(args, model) else: # 开始训练 train(args, model) ``` 然后保存 > <checker type="output-contains" command="tail /traffic_symbol/train.py" hint="完成代码输入"> > <keyword regex="args.test" /> > </checker> ## 4. 模型训练 > <time>25 min</time> ### 4.1 使用脚本进行训练 输入下述命令执行脚本训练过程 ``` python train.py ``` 本实验数据较少,训练时间较快,请等待训练完成 你能够看到训练过程输出日志的最后,看到类似下面的结果。 ``` Epoch 1/5 109/109 [==============================] - 18s 165ms/step - loss: 0.6315 - accuracy: 0.7936 - val_loss: 0.7480 - val_accuracy: 0.8750 Epoch 00001: val_loss improved from inf to 0.74797, saving model to ./results/model.h5 Epoch 2/5 109/109 [==============================] - 16s 144ms/step - loss: 0.3618 - accuracy: 0.8601 - val_loss: 0.0037 - val_accuracy: 0.8500 Epoch 00002: val_loss improved from 0.74797 to 0.00373, saving model to ./results/model.h5 Epoch 3/5 109/109 [==============================] - 16s 149ms/step - loss: 0.2079 - accuracy: 0.9243 - val_loss: 0.1375 - val_accuracy: 0.9000 Epoch 00003: val_loss did not improve from 0.00373 Epoch 4/5 109/109 [==============================] - 15s 142ms/step - loss: 0.2598 - accuracy: 0.9266 - val_loss: 0.0314 - val_accuracy: 1.0000 Epoch 00004: val_loss did not improve from 0.00373 Epoch 5/5 109/109 [==============================] - 16s 150ms/step - loss: 0.1935 - accuracy: 0.9335 - val_loss: 0.0285 - val_accuracy: 0.9500 Epoch 00005: val_loss did not improve from 0.00373 ``` 注意:你的数值很可能会给这里给出的数值不相同,并且由于训练过程的随机性,下面两句日志的输出顺序也可能会有差异 ``` val_loss improved from inf to xxx, saving model to ./results/model.h5 val_loss did not improve from xxx ``` 训练完成后,会在 /traffic_symbol/results 下生成model.h5,这是我们训练好的模型 特别说明,model.h5是二级制形式存储的模型文件,且文件较大,请不要直接打开它,避免设备卡住 > <checker type="output-contains" command="ls /traffic_symbol/results" hint="生成model.h5文件"> > <keyword regex="model.h5" /> > </checker> ### 4.2 调整超参数观察输出日志 输入下述命令重新训练模型 ``` python train.py --epochs 1 ``` 观察训练日志输出的val_loss与之前默认的epochs为5时对比,会发现默认参数效果很可能更好一些 将epochs调高,并不会再显著提升val_loss,是因为我们的训练数据较小且任务较为简单(交通标志和非交通标志的图片特征差别明显) > <checker type="output-contains" command="ls /traffic_symbol/results" hint="生成model.h5文件"> > <keyword regex="model.h5" /> > </checker> ## 5. 完成测试代码 > <time>15 min</time> ### 5.1 输入测试数据处理函数 [打开 /traffic_symbol/train.py][edit-train] > <edit for="edit-train" file="/traffic_symbol/train.py"></edit> 找到create_image_generator,在`return generator`前面输入下述代码,`注意缩进` ```python else: # 测试集数据处理 generator = ImageDataGenerator( preprocessing_function=preprocess_input # 数据不做任何增强 ).flow_from_directory( args.dataset + '/test', target_size=(model.inputs[0].shape[1], model.inputs[0].shape[2]), batch_size=args.batch_size, classes=classes, class_mode='categorical', shuffle=False, seed=0 ) ``` 然后保存 > <checker type="output-contains" command="cat /traffic_symbol/train.py" hint="完成代码输入"> > <keyword regex="/test" /> > </checker> ### 5.2 输入测试流程函数 在`if __name__ == "__main__":`前,继续输入下面的代码 ```python # 模型测试 def test(args, model): # 生成结果解析路径 result_folder = args.output + '/test' if os.path.exists(result_folder): shutil.rmtree(result_folder) os.makedirs(result_folder) # 生成测试数据集 test_generator = create_image_generator(args, 2) # 初始化变量 total_images = 0 right_images = 0 n_val_batch = len(test_generator) # 批量预测图片 for b in range(n_val_batch): vx, vy = test_generator.next() pred = model.predict(vx) vy = np.argmax(vy, -1) pred = np.argmax(pred, -1) if test_generator.batch_index > 0: idx = (test_generator.batch_index - 1) * test_generator.batch_size else: idx = (n_val_batch - 1) * test_generator.batch_size files = test_generator.filepaths[idx: idx + test_generator.batch_size] indices = [i for i, v in enumerate(pred) if pred[i] != vy[i]] total_images += len(files) right_images += len(files) - len(indices) for i in range(len(files)): img = cv2.imread(files[i], cv2.IMREAD_UNCHANGED) text = "label" + str(vy[i]) + "_pred" + str(pred[i]) + "_" save_path = os.path.join(result_folder, text + os.path.basename(files[i])) cv2.imwrite(save_path, img) print('accuracy', right_images / total_images) ``` 然后保存 > <checker type="output-contains" command="cat /traffic_symbol/train.py" hint="完成代码输入"> > <keyword regex="def test" /> > </checker> ## 6. 模型测试 > <time>20 min</time> ### 6.1 使用脚本进行测试 输入下述命令 ``` python train.py --test 1 --resume_model_path ./results/model.h5 ``` 等待测试完成,可以看到类似这样的输出 ``` Found 16 images belonging to 2 classes. accuracy 1.0 ``` > <checker type="output-contains" command="ls /traffic_symbol/results" hint="请完成测试任务"> > <keyword regex="test" /> > </checker> ### 6.2 查看测试图片数据结果 打开[test 文件夹][locate-test],查看测试输出图片效果 > <locate for="locate-test" path="/traffic_symbol/results/test" hint="模型测试结果"></locate> 可以在这里看到所有图片的标注和预测结果。 如label0_pred0_43-0-0.jpg,意味着标注类别是0,预测结果0,原图名称是43-0-0.jpg ## 课程学习已完成 > <time>1 min</time> 恭喜,你已经完成了本实验的全部模型训练与预测任务 接下来,你还可以通过修改代码加深对代码的理解