东方耀AI技术分享
标题:
【项目】02、基于Keras训练代码框架实现
[打印本页]
作者:
东方耀
时间:
2019-10-21 09:15
标题:
【项目】02、基于Keras训练代码框架实现
1、模型构建 def get_model
2、数据生成器 def batch_generator
3、开始训练网络 model.fit_generator
4、可视化 callbacks.TensorBoard plt.savefig('train_test_loss.jpg')
5、图像预处理 数据增强等都没有实现
根据车载摄像头的画面,自动判断如何打方向盘?使用端到端(end-to-end)的深度神经网络CNN
Data Generator:无需预先生成所有图像增强后的图像,会占用太多的硬盘空间,会增加读取硬盘文件所需的时间
数据driving_log.csv文件中右 center left right steering角度 throttle油门 brake刹车 speed速度
我们这里只用 center 和 steering角度
csv文件的读取:
data_path = 'F:\\AI_Study_dfy\\项目:自动驾驶之方向盘转动角度预测data\\'
with open(data_path + 'driving_log.csv', 'r') as csvfile:
file_reader = csv.reader(csvfile, delimiter=',')
log = []
for row in file_reader:
log.append(row)
log = np.array(log)
# 二维矩阵里面都是字符串
print(log.shape)
print(log.ndim)
print(log.dtype)
print(log[:5, :])
遇到问题:OpenCV无法读取中文路径
解决:
http://www.ai111.vip/thread-861-1-1.html
# -*- coding: utf-8 -*-
__author__ = u'东方耀 微信:dfy_88888'
__date__ = '2019/10/18 11:49'
__product__ = 'PyCharm'
__filename__ = 'train_dfy'
import tensorflow as tf
import numpy as np
import torch as T
from keras.layers import Conv2D, MaxPooling2D, Flatten, PReLU
from keras.layers.core import Dense, Dropout, Activation
from keras.optimizers import SGD, Adam
from keras.models import Model, Sequential
from keras import backend as K
from keras.regularizers import l2
import os.path
import cv2
import skimage.io as iio
import csv
import glob
import pickle
from sklearn.utils import shuffle
from sklearn.model_selection import cross_validate
from sklearn.model_selection import train_test_split
import json
from keras import callbacks
import math
import matplotlib.pyplot as plt
SEED = 666
print(tf.__version__)
print(T.__version__)
def get_model(shape):
"""
预测方向盘角度,以图像为输入,预测方向盘的转动角度
:param shape: 图像尺寸 (128, 128, 3) NHC
:return:
"""
model = Sequential(name='dfy_seq_model')
# 第一层需要指定input_shape 后面不需要
model.add(Conv2D(filters=24, kernel_size=(5, 5), strides=(2, 2),
padding='valid', data_format='channels_last', activation='relu', input_shape=shape))
model.add(Conv2D(filters=36, kernel_size=(5, 5), strides=(2, 2),
padding='valid', data_format='channels_last', activation='relu'))
model.add(Conv2D(filters=48, kernel_size=(5, 5), strides=(2, 2),
padding='valid', data_format='channels_last', activation='relu'))
model.add(Conv2D(filters=64, kernel_size=(3, 3), strides=(1, 1),
padding='valid', data_format='channels_last', activation='relu'))
model.add(Conv2D(filters=64, kernel_size=(3, 3), strides=(1, 1),
padding='valid', data_format='channels_last', activation='relu'))
model.add(Flatten(data_format='channels_last'))
model.add(Dense(units=1164, activation='relu'))
model.add(Dense(units=100, activation='relu'))
model.add(Dense(units=50, activation='relu'))
model.add(Dense(units=10, activation='relu'))
# 由于输出的角度是 (-pi/2, pi/2) 要选择好的激活函数
model.add(Dense(units=1, activation='linear'))
# compile: 1、指定优化器 2、损失函数
model.compile(optimizer=Adam(learning_rate=0.001), loss='mean_squared_error')
return model
# 开始数据增强(基于现有样本数据产生新的更多的训练数据)
def random_brightness(img, degree):
"""
随机调整输入图像的亮度,调整强度于0.1(变黑)和1(无变化)之间
:param img: 输入图像
:param degree: 输入图像对应的转动角度
:return:
"""
return (img, degree)
def horizontal_flip(img, degree):
"""
按照50%的概率水平翻转图像
:param img: 输入图像
:param degree: 输入图像对应的转动角度
:return:
"""
pass
return (img, degree)
def left_right_random_swap(img_address, degree, degree_corr=1.0 / 4):
"""
随机从左、中、右图像中选择一张图像,并相应调整转动的角度
:param img_address: 中间图像的文件路径
:param degree: 中间图像对应的方向盘转动角度
:param degree_corr: 方向盘转动角度调整的值
:return:
"""
return (img_address, degree)
def discard_zero_steering(degrees, rate):
"""
从角度为0的index中随机选择部分index返回
:param degrees: 输入的角度值
:param rate: 丢弃率 rate=0.8 表示80%的index返回
:return:
"""
return degrees
def image_transformation(img_address, degree, data_dir):
# img_address, degree = left_right_random_swap(img_address, degree)
# opencv 读出来的图像是 bgr的
# print('开始读的图片地址(路径有中文):', data_dir+img_address)
img = iio.imread(data_dir + img_address)
# cvt convert 颜色空间的转换
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# img, degree = random_brightness(img, degree)
# img, degree = horizontal_flip(img, degree)
return (img, degree)
def batch_generator(x, y, batch_size, shape, training=True, data_dir='data/', discard_rate=0.95):
"""
产生批处理的数据Generator 高效读取数据
Data Generator 无需预先生成所有图像增强后的图像,会占用太多的硬盘空间与增加读取硬盘文件所需的时间
:param x: 图像文件路径list
:param y: 方向盘的角度
:param batch_size:
:param shape: 输入图像的尺寸(HWC)
:param training: True时产生训练数据 False时产生validation数据
:param data_dir: 数据目录,包含一个IMG文件夹
:param discard_rate: 随机丢弃角度=0的训练数据的比率
:return:
"""
if training:
x, y = shuffle(x, y)
rand_zero_idx = discard_zero_steering(y, rate=discard_rate)
new_x = np.delete(x, rand_zero_idx, axis=0)
new_y = np.delete(y, rand_zero_idx, axis=0)
else:
new_x = x
new_y = y
offset = 0
while True:
X = np.empty(shape=(batch_size, *shape))
Y = np.empty(shape=(batch_size, 1))
for example in range(batch_size):
img_address, img_steering = new_x[example + offset], new_y[example + offset]
if training:
img, img_steering = image_transformation(img_address, img_steering, data_dir)
else:
img = iio.imread(data_dir + img_address)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 先截取图像 后resize 再 归一化到[-0.5, 0.5]
# [NHWC] 四维
X[example, :, :, :] = cv2.resize(img[80:140, 0:320], (shape[0], shape[1])) / 255 - 0.5
Y[example] = img_steering
if (example + 1) + offset > len(new_y) - 1:
# 达到了原来数据的尾部,从头开始
x, y = shuffle(x, y)
rand_zero_idx = discard_zero_steering(y, rate=discard_rate)
new_x = x
new_y = y
new_x = np.delete(new_x, rand_zero_idx, axis=0)
new_y = np.delete(new_y, rand_zero_idx, axis=0)
offset = 0
yield (X, Y) # 类似return 但有区别
offset = offset + batch_size
if __name__ == '__main__':
data_path = 'F:\\AI_Study_dfy\\项目:自动驾驶之方向盘转动角度预测data\\'
with open(data_path + 'driving_log.csv', 'r') as csvfile:
file_reader = csv.reader(csvfile, delimiter=',')
log = []
for row in file_reader:
log.append(row)
log = np.array(log)
# 二维矩阵里面都是字符串
print(log.shape)
print(log.ndim)
print(log.dtype)
print(log[:5, :])
# 去掉第一行 表头数据
log = log[1:, :]
ls_imgs = glob.glob(data_path + 'IMG/*.jpg')
print('一共有%d张图片(包括中间、左边、右边)' % len(ls_imgs))
assert len(ls_imgs) == len(log) * 3, 'number of images does not match!'
# 使用20%的数据作为测试数据集
test_ratio = 0.2
shape = (128, 128, 3)
batch_size = 20
# 所有的数据跑多少轮?epoch
nb_epoch = 30
# 中间摄像头的图片路径 str
x_ = log[:, 0]
# steering str---> float
y_ = log[:, 3].astype(float)
x_, y_ = shuffle(x_, y_)
X_train, X_test, y_train, y_test = train_test_split(x_, y_, random_state=SEED, test_size=test_ratio)
print('训练集大小:{}, 测试集大小:{}'.format(len(X_train), len(X_test)))
steps_per_epoch = 20
# 使得test数据集大小为batch_size的整数倍
nb_test_samples = len(y_test) - len(y_test) % batch_size
print('nb_test_samples size:', nb_test_samples)
model = get_model(shape)
# 生成模型结构汇总 挺好!
print(model.summary())
# 根据test loss保存最优模型
save_best = callbacks.ModelCheckpoint(filepath='best_model.h5', monitor='val_loss', verbose=1,
save_best_only=True, mode='min')
# 如果训练连续patience=15(向后看多少步)val_loss did not improve(网络不收敛),提前结束训练
# if (last_loss - current_loss) > min_delta 才算网络是在优化 否则表示loss没有在下降
early_stop = callbacks.EarlyStopping(monitor='val_loss', min_delta=1e-5, patience=15, verbose=0, mode='auto')
tb_callback = callbacks.TensorBoard(log_dir='./Graph', write_graph=True)
callback_lists = [early_stop, save_best, tb_callback]
# 开始训练网络
history = model.fit_generator(
generator=batch_generator(X_train, y_train, batch_size, shape, training=True, data_dir=data_path),
steps_per_epoch=steps_per_epoch, validation_steps=nb_test_samples // batch_size,
validation_data=batch_generator(X_test, y_test, batch_size, shape, training=False, data_dir=data_path),
epochs=nb_epoch, verbose=1, callbacks=callback_lists)
with open('./trainHistoryDict.pickle', 'wb') as file_pickle:
pickle.dump(history.history, file_pickle)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('model train vs test loss')
plt.xlabel('epoch')
plt.ylabel('loss')
plt.legend(['train', 'test'], loc='upper right')
plt.savefig('train_test_loss.jpg')
# 模型保存
with open('model.json', 'w') as f:
f.write(model.to_json())
model.save('model.h5')
print('Done!')
复制代码
东方老师AI官网:
http://www.ai111.vip
有任何问题可联系东方老师微信:dfy_88888
【微信二维码图片】
作者:
xsoft
时间:
2020-2-3 15:41
谢谢老师提供的资料。
作者:
ljdxls111
时间:
2022-3-18 00:35
dsffdsfsdfdsfds
作者:
ljdxls111
时间:
2022-3-18 00:36
dsfsfsdfdsfsdfsdfds
欢迎光临 东方耀AI技术分享 (http://www.ai111.vip/)
Powered by Discuz! X3.4