基于GTSRB数据集的交通标志识别实验(Tensorflow)

一、数据

官网下载太慢,然后我找到了一个整理好的数据集
链接: GTSRB-德国交通标志识别图像数据 .
数据集很干净,直接用就好了,它把所有的数据信息单独列了一个csv文件。
数据集有43个大类 。
每个类按规律排列,需要将其打乱顺序。
在这里插入图片描述
训练集:
在这里插入图片描述
在这里插入图片描述

测试集:在这里插入图片描述
如图,虽然数据集要干净一些,但是读取测试集和训练集的方法不一样

数据读取

1、训练数据
因为训练集是按规律排列的,而且数据量很大,所以先打乱顺序,将其划分出一个训练集一个测试集。(原数据集里边的测试集不是按类别分的,读出来格式不太一样,就直接用这个了)

#%%
#划分训练集和测试集
import os
import random
import shutil
path = 'F:\GTSRB-德国交通标志识别图像数据\Train'
dirs = []
split_percentage = 0.2
for dirpath, dirnames, filenames in os.walk(path, topdown=False):
   for dirname in dirnames:
       fullpath = os.path.join(dirpath, dirname)
       fileCount = len([name for name in os.listdir(fullpath) if os.path.isfile(os.path.join(fullpath, name))])
       files = os.listdir(fullpath)
       for index in range((int)(split_percentage * fileCount)):
           newIndex = random.randint(0, fileCount - 1)
           fullFilePath = os.path.join(fullpath, files[newIndex])
           newFullFilePath = fullFilePath.replace('Train', 'Final_Validation')
           base_new_path = os.path.dirname(newFullFilePath)
           if not os.path.exists(base_new_path):
               os.makedirs(base_new_path)
           # move the file
           try:
               shutil.move(fullFilePath, newFullFilePath)
           except IOError as error:
               print('skip moving from %s => %s' % (fullFilePath, newFullFilePath))

然后就可以对数据开始处理准备训练:

#%%
import shutil
import os
import matplotlib.pyplot as plt

train_set_base_dir = 'F:\GTSRB-德国交通标志识别图像数据\Train'
validation_set_base_dir = 'F:\GTSRB-德国交通标志识别图像数据\Final_Validation'

# 数据处理
from keras.preprocessing.image import ImageDataGenerator

train_datagen = ImageDataGenerator(
    rescale=1. / 255
)
train_data_generator = train_datagen.flow_from_directory(
    directory=train_set_base_dir,
    target_size=(48, 48),
    batch_size=32,
    class_mode='categorical')


validation_datagen = ImageDataGenerator(
    rescale=1. /255
)

validation_data_generator = validation_datagen.flow_from_directory(
    directory=validation_set_base_dir,
    target_size=(48, 48),
    batch_size=32,
    class_mode='categorical'
)

2、验证数据:
因为老是奇奇怪怪的报错,所以干脆用它给出来的Test文件夹里的测试集验证预测了。

#%%

path = 'F:\GTSRB-德国交通标志识别图像数据'

csv_files = []
for dirpath, dirnames, filenames in os.walk(path, topdown=False):
    for filename in filenames:
        if filename.endswith('.csv'):
            csv_files.append(os.path.join(dirpath, filename))
            

#%%
import matplotlib.image as mpimg
test_image=[]
test_lable=[]
x=''
csv=csv_files[1] #F:\GTSRB-德国交通标志识别图像数据\Test.csv
base_path = os.path.dirname(csv)
# read csv data
trafficSigns = []
with open(csv,'r',newline='') as file:
    header = file.readline()
    header = header.strip()
    header_list = header.split(',')

    print(header_list)
    #print(header_list[6])
    for row in file.readlines():
        row_data = row.split(',')
        x=row_data[7]
        x='F:/GTSRB-德国交通标志识别图像数据/'+x
        x=x.strip('\n')
        test_lable.append(row_data[6])
        test = Image.open(x)
        test = test.resize((48,48),Image.ANTIALIAS)
        test = np.array(test)
        test_image.append(test)
test_data = np.array(test_image)

注:关于Test文件夹里的数据,因为读出来不是generator格式,所以最开始使用训练集抽取出来的20%作为测试集的,最后用test文件预测时出现了这个问题:
训练集:
在这里插入图片描述
模型评估的分非常高,然后预测时就变成了这样
在这里插入图片描述
准确率直接掉到了6%
关于用test文件夹里的数据做评估时,最开始分别输入数据和标签老是报错,最后找到原因是,label数据不能自动进行one-hot编码,所以需要手动进行。
所以我重新做了一下数据处理,干脆将其转换成generator对象。

二、搭建网络

#%%
import tensorflow as tf
from keras.models import Sequential
from keras.layers import Conv2D, MaxPool2D, Flatten, Dense, Dropout

#模型使用简单四层卷积,加flatten和dense层作为分类器,对其进行分类
model = Sequential()

# layers.conv2D
#此处选择四层二维卷积,并做全局池化
model.add(Conv2D(filters=32, kernel_size=(3, 3), activation='relu', input_shape=(48, 48, 3)))
model.add(MaxPool2D(pool_size=(2, 2), padding='valid'))

model.add(Conv2D(filters=64, kernel_size=(3, 3), activation='relu'))
model.add(MaxPool2D(pool_size=(2, 2), padding='valid'))

model.add(Conv2D(filters=128, kernel_size=(3, 3), activation='relu'))
model.add(MaxPool2D(pool_size=(2, 2), padding='valid'))

model.add(Conv2D(filters=128, kernel_size=(3, 3), activation='relu'))
model.add(MaxPool2D(pool_size=(2, 2), padding='valid'))

#分类器
model.add(Flatten())
# dropOut layer
model.add(Dropout(0.2))
model.add(Dense(units=512, activation='relu'))
model.add(Dense(units=43, activation='softmax'))

#编译
#多分类单标签问题,loss选择的'categorical_crossentropy'
model.compile(loss='categorical_crossentropy', optimizer='rmsprop', metrics=['acc'])

# 打印模型
model.summary()
json_str = model.to_json()
print(json_str)
#%%

# fit_generator to fill in the dataset
#设置训练次数为30
history = model.fit_generator(
    generator=train_data_generator,
    steps_per_epoch=100,
    epochs=27,#在训练30次的过程中可以发现,在第27次时就已经过拟合
    validation_data=validation_data_generator,
    validation_steps=50)

#保存模型
model.save('F:/MLCourse/model27epoch.h5')

#%%
#绘制训练情况
acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']

epochs = range(1, len(acc) + 1)
plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.legend()

plt.figure()

plt.plot(epochs, loss, 'bo', label='Training loss')
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.legend()

plt.show()

这里只是在测试写的程序,模型就用的普通的卷积层,验证效果并不好,建议下载一些预训练模型。
这里最开始训练了30次:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

可以看出来27次就过拟合了,训练精度还是蛮高的,可能是数据比较规律。

三、模型预测

因为一直在整数据,不想太麻烦,就把模型单独训练的。在这里加了一层softmax层做概率输出。

#%%
#下载训练好的模型
#import keras
new_model = keras.models.load_model('F:/MLCourse/model27epoch.h5')
#test_loss, test_acc = new_model.evaluate(test_image, test_lable)
#print('\nTest accuracy:', test_acc)
#附加一个 softmax 层,将 logits 转换成更容易理解的概率
probability_model = tf.keras.Sequential([new_model, 
                                         tf.keras.layers.Softmax()])
#%%
#预测测试集中所有模型的标签
predictions = probability_model.predict(test_data)

然后,我就发现差不多只预测对了很少qaq|。所以过了一天我突然想改一改,所以上面重新处理了一下测试集数据,将其进行one-hot编码之后,转化成generator对象。然后重新训练了一次。
然后我又训练了一次,无论是将混乱的测试集作为训练输入,还是将比较规律的测试集作为输入,最后评估效果都很差,所以我决定重新设计网络。使用VGG16进行预训练。
然后训练完之后,如果用test里的文件和Train里的文件一个验证一个训练的话,验证精度依旧上不去。所以我就混合了一下,做了交叉验证。
然后验证精度就变成了:
在这里插入图片描述

四、附录

模块导入

因为怕麻烦,所以分开了很多文件搞的,搞了个大集合

#%%
import shutil
import os
import matplotlib.pyplot as plt
import keras
import tensorflow as tf
from PIL import Image
import numpy as np
from keras.preprocessing.image import ImageDataGenerator
from keras.preprocessing import image
import sys
import numpy as np
from tensorflow.keras import datasets, layers, models
from keras.models import Sequential
from keras.layers import Conv2D, MaxPool2D, Flatten, Dense, Dropout

Code

#%%Train文件划分后的数据处理
train_set_base_dir = 'F:\GTSRB-德国交通标志识别图像数据\Train'
validation_set_base_dir = 'F:\GTSRB-德国交通标志识别图像数据\Final_Validation'
#%%
train_datagen = ImageDataGenerator(
    rescale=1. / 255
)
train_data_generator = train_datagen.flow_from_directory(
    directory=train_set_base_dir,
    target_size=(48, 48),
    batch_size=32,
    class_mode='categorical')
#%%

validation_datagen = ImageDataGenerator(
    rescale=1. /255
)

validation_data_generator = validation_datagen.flow_from_directory(
    directory=validation_set_base_dir,
    target_size=(48, 48),
    batch_size=32,
    class_mode='categorical'
)





#%%Test文件数据处理

path = 'F:\GTSRB-德国交通标志识别图像数据'

csv_files = []
for dirpath, dirnames, filenames in os.walk(path, topdown=False):
    for filename in filenames:
        if filename.endswith('.csv'):
            csv_files.append(os.path.join(dirpath, filename))
            

#%%
import matplotlib.image as mpimg
test_image=[]
test_lable=[]
x=''
csv=csv_files[1] #F:\GTSRB-德国交通标志识别图像数据\Test.csv
base_path = os.path.dirname(csv)
# read csv data
trafficSigns = []
with open(csv,'r',newline='') as file:
    header = file.readline()
    header = header.strip()
    header_list = header.split(',')

    print(header_list)
    #print(header_list[6])
    for row in file.readlines():
        row_data = row.split(',')
        x=row_data[7]
        x='F:/GTSRB-德国交通标志识别图像数据/'+x
        x=x.strip('\n')
        m=row_data[6]
        test_lable.append(int(row_data[6]))
        test = Image.open(x)
        test = test.resize((48,48),Image.ANTIALIAS)
        test = np.array(test)
        test_image.append(test)

#%%
test_data = np.array(test_image)
#%%
test_lable = np.array(test_lable)
#%%
#标签进行one-hot编码
labels = test_lable
one_hot_labels = tf.one_hot(indices=labels,depth=43, on_value=1, off_value=0, axis=-1, dtype=tf.int32, name="one-hot")
#%%
#print(one_hot_labels.shape)
test_datagen = ImageDataGenerator(
    rescale=1. /255
)

test_data_generator = test_datagen.flow(
    x=test_data,
    y=one_hot_labels,
    #target_size=(48, 48),
    batch_size=32
    #class_mode='categorical'
)


#%%
print(test_lable)        


#%%训练
import tensorflow as tf
from keras.models import Sequential
from keras.layers import Conv2D, MaxPool2D, Flatten, Dense, Dropout

#模型使用简单四层卷积,加flatten和dense层作为分类器,对其进行分类
model = Sequential()

# layers.conv2D
#此处选择四层二维卷积,并做全局池化
model.add(Conv2D(filters=32, kernel_size=(3, 3), activation='relu', input_shape=(48, 48, 3)))
model.add(MaxPool2D(pool_size=(2, 2), padding='valid'))

model.add(Conv2D(filters=64, kernel_size=(3, 3), activation='relu'))
model.add(MaxPool2D(pool_size=(2, 2), padding='valid'))

model.add(Conv2D(filters=128, kernel_size=(3, 3), activation='relu'))
model.add(MaxPool2D(pool_size=(2, 2), padding='valid'))

model.add(Conv2D(filters=128, kernel_size=(3, 3), activation='relu'))
model.add(MaxPool2D(pool_size=(2, 2), padding='valid'))

#分类器
model.add(Flatten())
# dropOut layer
model.add(Dropout(0.2))
model.add(Dense(units=512, activation='relu'))
model.add(Dense(units=43, activation='softmax'))

#编译
#多分类单标签问题,loss选择的'categorical_crossentropy'
model.compile(loss='categorical_crossentropy', optimizer='rmsprop', metrics=['acc'])

# 打印模型
model.summary()
json_str = model.to_json()
print(json_str)

#%%

# fit_generator to fill in the dataset
#设置训练次数为30
history = model.fit_generator(
    generator=train_data_generator,
    steps_per_epoch=100,
    epochs=27,#在训练30次的过程中可以发现,在第27次时就已经过拟合
    validation_data=validation_data_generator,
    validation_steps=50)

#保存模型
model.save('F:/MLCourse/model27epoch.h5')

#%%
#绘制训练情况
acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']

epochs = range(1, len(acc) + 1)
plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.legend()

plt.figure()

plt.plot(epochs, loss, 'bo', label='Training loss')
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.legend()

plt.show()

#%%

print(train_data_generator[0])



#%%
#下载训练好的模型
#import keras
new_model = keras.models.load_model('F:/MLCourse/model27epoch.h5')
#test_loss, test_acc = new_model.evaluate(test_image, test_lable)
#print('\nTest accuracy:', test_acc)
#附加一个 softmax 层,将 logits 转换成更容易理解的概率
probability_model = tf.keras.Sequential([new_model, 
                                         tf.keras.layers.Softmax()])

#%%
#test_loss, test_acc = new_model.evaluate_generator(validation_data_generator)
#print('\nTest accuracy:', test_acc)
new_model.compile(loss='categorical_crossentropy', optimizer='rmsprop', metrics=['acc'])
new_model.summary()
#%%
#划分出来的测试集评估
scores = new_model.evaluate(validation_data_generator)
print(scores)

#%%
#test评估
scores2 = new_model.evaluate(test_data,one_hot_labels, verbose=2)
print(scores2)



#%%
#预测测试集中所有模型的标签
predictions = probability_model.predict(test_data)

结语

各种奇怪的报错姿势,小细节really重要。
PS.我去瞅了瞅测试集,有些图片都黑成一坨了,我都看不出来有东西。
PPS.本来考研好累,想搞搞这个放松放松,结果更自闭了.jpg
QAQ|、、、

04-03
### GTSRB 数据集概述 德国交通标志识别基准 (German Traffic Sign Recognition Benchmark, GTSRB)[^1] 是一种广泛应用于计算机视觉领域中的数据集,主要用于训练和测试机器学习模型对交通标志的分类能力。该数据集由来自真实世界场景的图像组成,这些图像是通过摄像头拍摄得到的。 #### 数据集结构 GTSRB 数据集中包含了超过 **50,000 张图片**[^2] ,涵盖了 **43 类不同的交通标志类别**。每张图片都标注了一个对应的标签,表示它属于哪一类交通标志。这些类别的范围从警告标志到指示牌不等,几乎覆盖了所有的常见交通信号类型。 #### 图像特点 由于采集自真实的驾驶环境,因此 GTSRB 的图像具有较高的复杂性和多样性。例如,它们可能受到天气条件、光照变化以及遮挡等因素的影响。这种特性使得基于此数据集开发出来的算法能够更好地适应实际应用场景下的挑战[^3]。 ### 使用案例分析 #### 训练深度学习模型 研究人员经常利用 GTSRB 来构建并优化卷积神经网络(Convolutional Neural Networks,CNNs),用于解决多分类问题。CNN 结构可以自动提取特征,并有效处理大规模的数据量,在此类任务上表现优异[^4]。 下面是一个简单的 TensorFlow/Keras 实现 CNN 进行交通标志分类的例子: ```python import tensorflow as tf from tensorflow.keras import layers, models def create_cnn_model(input_shape=(32, 32, 3), num_classes=43): model = models.Sequential() # 添加第一个卷积层与池化操作 model.add(layers.Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=input_shape)) model.add(layers.MaxPooling2D(pool_size=(2, 2))) # 第二个卷积层与池化操作 model.add(layers.Conv2D(64, kernel_size=(3, 3), activation='relu')) model.add(layers.MaxPooling2D(pool_size=(2, 2))) # 展平层 model.add(layers.Flatten()) # 全连接层 model.add(layers.Dense(128, activation='relu')) # 输出层采用 softmax 函数实现多分类预测 model.add(layers.Dense(num_classes, activation='softmax')) return model ``` 上述代码定义了一种基础架构来完成针对 GTSRB 数据集的任务需求[^5]。 #### 安全监控系统集成 除了学术研究外,工业界也将这项技术应用到了自动驾驶汽车的安全保障机制当中。通过对道路状况实时监测并与预存数据库对比匹配,车辆能够在遇到特定情况时迅速做出反应决策,从而提升行车安全性水平[^6]。 ### 总结说明 综上所述,GTSRB 不仅作为科研探索的重要资源存在,同时也促进了现代智能运输系统的进步与发展。随着人工智能技术不断革新升级,相信未来会有更多创新成果涌现出来服务于人类社会各个层面的需求之中。
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值