用keras框架搭建神经网络——(五)识别交通标志
2019-03-13 09:45
761 查看
从这一个阶段开始,搭建的神经网络将用于更加贴近生活的实用场景,并逐步尝试优化用户体验做成某种“产品”。
源代码下载:https://download.csdn.net/download/rance_king/11015514
- 导入包,下载数据集
数据集来源:https://bitbucket.org/jadslim/german-traffic-signs ,其中包含一个csv文件和三个pickle文件,csv文件将不同的交通标志名称对应到不同的class数字标号分类中,三个csv文件分别对应着训练集,测试集合验证集。
import numpy as np import matplotlib.pyplot as plt import keras from keras.models import Sequential from keras.optimizers import Adam from keras.layers import Dense from keras.layers import Flatten, Dropout from keras.utils.np_utils import to_categorical from keras.layers.convolutional import Conv2D, MaxPooling2D import random import pickle import pandas as pd import cv2
- 载入数据集,查看了数据集dict的key之后发现有feature和label两个键,应该是分别作为图片和标签来使用的。
#pickle文件是一种二进制文件,这里pickle.load则将这种二进制文件反序列化变成dict,‘rb’的意思是read binary with open('german-traffic-signs/train.p', 'rb') as f: train_data = pickle.load(f) with open('german-traffic-signs/valid.p', 'rb') as f: val_data = pickle.load(f) with open('german-traffic-signs/test.p', 'rb') as f: test_data = pickle.load(f) X_train, y_train = train_data['features'], train_data['labels'] X_val, y_val = val_data['features'], val_data['labels'] X_test, y_test = test_data['features'], test_data['labels'] #验证一下数据集中图片和标签的一一对应关系 assert(X_train.shape[0] == y_train.shape[0]), "the number of the dataset is not equal to the number of the labels" #通过pandas载入data,然后马上可以发现交通信号一共有43个类别需要进行鉴别,对应编号0-42 data = pd.read_csv('german-traffic-signs/signnames.csv')
- 查看数据集中数据的分布情况,可以发现这个数据集中各个分类下的数据不是均匀的。
num_of_samples=[] cols = 5 num_classes = 43 fig, axs = plt.subplots(nrows=num_classes, ncols=cols, figsize=(5,50)) fig.tight_layout() #对这个循环意思的解读:循环每一列的i(一共有五列),并在每一列i中分别返回index=j(这个j是0-42中的一个数)#row,row是data这个dict下的以0-42标号对应的标签名称 for i in range(cols): for j, row in data.iterrows(): x_selected = X_train[y_train == j] axs[j][i].imshow(x_selected[random.randint(0,(len(x_selected) - 1)), :, :], cmap=plt.get_cmap('gray')) axs[j][i].axis("off") if i == 2: axs[j][i].set_title(str(j) + " - " + row["SignName"]) num_of_samples.append(len(x_selected))
plt.figure(figsize=(12, 4)) plt.bar(range(0, num_classes), num_of_samples) plt.title("Distribution of the train dataset") plt.xlabel("Class number") plt.ylabel("Number of images") plt.show()
- 对图片进行处理,将图片转换为特征更加容易突出的图片。
#用opencv库将BGR格式的图转化为灰度图片 def grayscale(img): img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) return img img = grayscale(X_train[1000]) plt.imshow(img) plt.axis("off")
#直方图同等化,这个方法用于改善图片的的对比度 def equalize(img): img = cv2.equalizeHist(img) return img img = equalize(img) plt.imshow(img) plt.axis("off") print(img.shape)
如此,图片的边界变得清晰,因而特征更加明显。
def preprocess(img): img = grayscale(img) img = equalize(img) img = img/255 return img
使用map()函数将预处理的功能映射给每一张图片
X_train = np.array(list(map(preprocess, X_train))) X_test = np.array(list(map(preprocess, X_test))) X_val = np.array(list(map(preprocess, X_val)))
预处理后的文件需要经过reshape增加一个维度,这样才能作为数据被CNN网络进行使用。
这里要特别注意,因为CNN网络需要一个深度来使用filter提取特征,所以,这里要reshape增加一层深度给filter使用。
X_train = X_train.reshape(X_train[0], 32, 32, 1) X_test = X_test.reshape(X_test[0], 32, 32, 1) X_val = X_val.reshape(X_val[0], 32, 32, 1) y_train = to_categorical(y_train, 43) y_test = to_categorical(y_test, 43) y_val = to_categorical(y_val, 43)
- 这里加入了一个新的步骤,data augmentation数据扩大化,这个步骤的作用是将现有的数据进行处理,变成更多的数据来作为学习材料,比如说将图片翻转,旋转等等来让计算机有更多的学习输入。使用kereas框架进行数据扩大化制造的图片不会在这个步骤生成图片,而是在实际训练的时候生成。
from keras.preprocessing.image import ImageDataGenerator #imagedatagenerater,使用这个东西来制造新的图片,制造出来的内容是一种generater,可以用next来唤出。 datagen = ImageDataGenerator(width_shift_range=0.1, height_shift_range=0.1, zoom_range=0.2, shear_range=0.1, rotation_range=10.) datagen.fit(X_train)
- 定义模型,这一步有反复调试参数的过程在内,注意数据之间的关联性,参数的数量对标的是计算量的大小,我发现在某些情况下增加卷积层甚至会减少整体的参数量,因为卷积层用特征替代像素点,可以有效缩减输入。
def modified_model(): model = Sequential() model.add(Conv2D(60, (5, 5), input_shape=(32, 32, 1), activation='relu')) model.add(Conv2D(60, (5, 5), activation='relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Conv2D(30, (3, 3), activation='relu')) model.add(Conv2D(30, (3, 3), activation='relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Flatten()) model.add(Dense(500, activation='relu')) model.add(Dropout(0.5)) model.add(Dense(43, activation='softmax')) model.compile(Adam(lr = 0.001), loss='categorical_crossentropy', metrics=['accuracy']) return model model = modified_model() print(model.summary())
- 训练开始!这一次要用data augmentation的方法来训练出模型来。
首先是用上fit_generator方法,实际上这一次使用的数据就是data augmentation制造出的generator,datagen.flow随着运行产生image数据,每批50个,规定每个epoch需要用2000步完成
history = model.fit_generator(datagen.flow(X_train, y_train, batch_size=50), steps_per_epoch=2000, epochs=10, validation_data=(X_val, y_val), shuffle = 1)
- 评估模型
score = model.evaluate(X_test, y_test, verbose=0) print('Test score:', score[0]) print('Test accuracy:', score[1])
得到的结果测试验证集这一次是百分之九十七的准确率。
9.实际输入一些图片来尝试一下能否被训练好的模型认出。
import requests from PIL import Image url = 'https://c8.alamy.com/comp/J2MRAJ/german-road-sign-bicycles-crossing-J2MRAJ.jpg' r = requests.get(url, stream=True) img = Image.open(r.raw) plt.imshow(img, cmap=plt.get_cmap('gray')) img = np.asarray(img) img = cv2.resize(img, (32, 32)) img = preprocess(img) plt.imshow(img, cmap = plt.get_cmap('gray')) print(img.shape) img = img.reshape(1, 32, 32, 1) print("predicted sign: "+ str(model.predict_classes(img)))
predicted sign: [30]
30号对应的是Beware of ice/snow
成功地认出了交通标志!
相关文章推荐
- 简单python神经网络从原理到搭建框架以及模板使用实例(python识别手写字体)
- 用户画像(2)使用keras框架搭建神经网络模型
- TensorFlow识别复杂验证码以及搭建生产环境(5)—— 设计神经网络
- 基于Tensorflow框架的卷集神经网络手写体数字识别
- 深度学习框架Keras学习系列(三):Keras神经网络框架
- keras —— 30秒搭建神经网络
- [置顶] 【python keras实战】用keras搭建卷起神经网络训练模型
- Keras搭建第一个CNN神经网络(mnist手写体数字分类)
- 对比学习用 Keras 搭建 CNN RNN 等常用神经网络
- 各框架下(tensorflow, pytorch, theano, keras)实现几个基础结构神经网络(mlp, autoencoder, CNNs, recurrent, recursive)
- 用Keras搭建, 编译和训练神经网络时,常见问题
- [深度学习框架] Keras上使用神经网络进行mnist分类
- 深度学习实践系列(3)- 使用Keras搭建notMNIST的神经网络
- 利用Keras搭建神经网络进行回归预测
- python keras 神经网络框架 的使用以及实例
- 深度学习入门实践_十行搭建手写数字识别神经网络
- Keras入门-搭建BP网络识别手写字符
- 基于Keras框架的简易验证码识别网络的构建
- 深度学习——利用学习框架TensorFlow搭建深层神经网络DNN
- 深度学习——残差神经网络ResNet在分别在Keras和tensorflow框架下的应用案例