-
Notifications
You must be signed in to change notification settings - Fork 277
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
274 additions
and
78 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# 利用训练好的模型操作小车,实现自动驾驶 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
# 将图片处理为npz格式 | ||
|
||
import os | ||
import numpy as np | ||
import matplotlib.image as mpimg | ||
from time import time | ||
import math | ||
from PIL import Image | ||
|
||
CHUNK_SIZE = 256 | ||
|
||
|
||
|
||
|
||
def process_img(img_path, key): | ||
|
||
print(img_path, key) | ||
image = Image.open(img_path) | ||
image_array = np.array(image) | ||
image_array = np.expand_dims(image_array, axis=0) | ||
|
||
|
||
|
||
|
||
#image_array = mpimg.imread(img_path) | ||
#image_array = np.expand_dims(image_array, axis=0) | ||
|
||
print(image_array.shape) | ||
|
||
if key == 2: | ||
label_array = [0., 0., 1., 0., 0.] | ||
elif key == 3: | ||
label_array = [0., 0., 0., 1., 0.] | ||
elif key == 0: | ||
label_array = [1., 0., 0., 0., 0.] | ||
elif key == 1: | ||
label_array = [0., 1., 0., 0., 0.] | ||
elif key == 4: | ||
label_array = [0., 0., 0., 0., 1.] | ||
|
||
return (image_array, label_array) | ||
# 返回图片的数据(矩阵),和对应的标签值 | ||
|
||
|
||
if __name__ == '__main__': | ||
path = "training_data" | ||
files = os.listdir(path) # 将该路径下的文件名都存入列表 | ||
turns = int(math.ceil(len(files) / CHUNK_SIZE)) | ||
print("number of files: {}".format(len(files))) | ||
print("turns: {}".format(turns)) | ||
|
||
for turn in range(0, turns): | ||
train_labels = np.zeros((1, 5), 'float') | ||
train_imgs = np.zeros([1, 120, 160, 3]) | ||
|
||
CHUNK_files = files[turn * CHUNK_SIZE: (turn + 1) * CHUNK_SIZE] | ||
print("number of CHUNK files: {}".format(len(CHUNK_files))) | ||
for file in CHUNK_files: | ||
if not os.path.isdir(file) and file[len(file) - 3:len(file)] == 'jpg': | ||
try: | ||
key = int(file[0]) | ||
image_array, label_array = process_img(path + "/" + file, key) | ||
train_imgs = np.vstack((train_imgs, image_array)) | ||
train_labels = np.vstack((train_labels, label_array)) | ||
except: | ||
print('prcess error') | ||
|
||
# 去掉第0位的全零图像数组,全零图像数组是 train_imgs = np.zeros([1,120,160,3]) 初始化生成的 | ||
train_imgs = train_imgs[1:, :] | ||
train_labels = train_labels[1:, :] | ||
file_name = str(int(time())) | ||
directory = "/Volumes/Seagate Expansion Drive/tianhangz/project/selfdrive/training_data_npz" | ||
|
||
if not os.path.exists(directory): | ||
os.makedirs(directory) | ||
try: | ||
np.savez(directory + '/' + file_name + '.npz', train_imgs=train_imgs, train_labels=train_labels) | ||
except IOError as e: | ||
print(e) | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
# 搭建深度学习模型 | ||
# 导入库 | ||
import keras | ||
import tensorflow | ||
import sys | ||
import os | ||
import h5py | ||
import numpy as np | ||
import glob | ||
from sklearn.model_selection import train_test_split | ||
from keras.models import Sequential | ||
from keras.layers import Lambda, Conv2D, MaxPooling2D, Dropout, Dense, Flatten | ||
from keras.models import load_model, Model, Input | ||
from keras.callbacks import ModelCheckpoint, EarlyStopping, TensorBoard | ||
from keras.optimizers import Adam, SGD | ||
|
||
|
||
# 全局变量 | ||
IMAGE_HEIGHT, IMAGE_WIDTH, IMAGE_CHANNELS = 120, 160, 3 | ||
INPUT_SHAPE = (IMAGE_HEIGHT, IMAGE_WIDTH, IMAGE_CHANNELS) | ||
|
||
|
||
# step1,载入数据,并且分割为训练和验证集 | ||
def load_data(): | ||
|
||
# load | ||
image_array = np.zeros((1, 120, 160, 3)) | ||
label_array = np.zeros((1, 5), 'float') | ||
training_data = glob.glob('training_data_npz/*.npz') # 匹配所有的符合条件的文件,并将其以list的形式返回。 | ||
|
||
# 为空 | ||
if not training_data: | ||
print('文件内没有训练数据了,退出') | ||
sys.exit() | ||
# 遍历训练文件 | ||
for single_nzp in training_data: | ||
with np.load(single_nzp) as data: | ||
print(data.keys()) | ||
train_temp = data['train_imgs'] | ||
train_labels_temp = data['train_labels'] | ||
image_array = np.vstack((image_array, train_temp)) | ||
label_array = np.vstack((label_array, train_labels_temp)) | ||
X = image_array[1:, :] | ||
y = label_array[1:, :] | ||
print('Image array shape: '+ str(X.shape)) | ||
print('Label array shape: '+ str(y.shape)) | ||
print(np.mean(X)) | ||
print(np.var(X)) | ||
|
||
# 将数据分割为训练集(80),测试集(20),验证集 | ||
X_train, X_valid, y_train, y_valid = train_test_split(X, y, test_size=0.2, random_state=0) | ||
|
||
return X_train, X_valid, y_train, y_valid | ||
|
||
|
||
# step2 建立模型 | ||
def build_model(keep_prob): | ||
model = Sequential | ||
model.add(Lambda(lambda x: (x/102.83 - 1), input_shape = INPUT_SHAPE)) | ||
model.add(Conv2D(24, (5, 5), activation='elu', strides=(2, 2))) | ||
model.add(Conv2D(36, (5, 5), activation='elu', strides=(2, 2))) | ||
model.add(Conv2D(48, (5, 5), activation='elu', strides=(2, 2))) | ||
|
||
#model.add(Dropout(0.5)) | ||
model.add(Conv2D(64, (3, 3),activation='elu')) | ||
#model.add(Dropout(0.3)) | ||
model.add(Conv2D(64, (3, 3),activation='elu')) | ||
model.add(Dropout(keep_prob)) # Dropout将在训练过程中每次更新参数时随机断开一定百分比(p)的输入神经元连接 | ||
model.add(Flatten()) | ||
model.add(Dense(500, activation='elu')) | ||
model.add(Dropout(0.1)) | ||
model.add(Dense(250, activation='elu')) | ||
model.add(Dropout(0.1)) | ||
model.add(Dense(50, activation='elu')) | ||
model.add(Dropout(0.1)) | ||
model.add(Dense(5)) | ||
model.summary() | ||
|
||
return model | ||
|
||
# step3 训练模型 | ||
def train_model(model, learning_rate, nb_epoch, samples_per_epoch, | ||
batch_size, X_train, X_valid, y_train, y_valid): | ||
checkpoint = ModelCheckpoint('model-{epoch:03d}.h5', monitor='val_loss', | ||
verbose=0, | ||
save_best_only=True, | ||
mode='min') | ||
# EarlyStopping patience:当earlystop被激活(如发现loss相比上一个epoch训练没有下降), | ||
# 则经过patience个epoch后停止训练。 | ||
# mode:‘auto’,‘min’,‘max’之一,在min模式下,如果检测值停止下降则中止训练。在max模式下,当检测值不再上升则停止训练。 | ||
early_stop = EarlyStopping(monitor='val_loss', min_delta=.0005, patience=4, | ||
verbose=1, mode='min') | ||
tensorboard = TensorBoard(log_dir='./logs', histogram_freq=0, batch_size=20, write_graph=True, | ||
write_images=True, embeddings_freq=0, embeddings_layer_names=None, | ||
embeddings_metadata=None) | ||
# 编译神经网络模型,loss损失函数,optimizer优化器, metrics列表,包含评估模型在训练和测试时网络性能的指标 | ||
model.compile(loss='mean_squared_error', optimzier=Adam(lr=learning_rate), metrics=['accuracy']) | ||
# 训练神经网络模型,batch_size梯度下降时每个batch包含的样本数,epochs训练多少轮结束, | ||
# verbose是否显示日志信息,validation_data用来验证的数据集 | ||
model.fit_generator(batch_generator(X_train, y_train, batch_size), | ||
steps_per_epoch=samples_per_epoch/batch_size, | ||
max_queue_size=1, | ||
validation_data=batch_generator(X_valid, y_valid, batch_size), | ||
validation_steps=len(X_valid)/batch_size, | ||
callbacks=[tensorboard, checkpoint, early_stop], | ||
verbose=2) | ||
|
||
|
||
|
||
|
||
|
||
# step4 | ||
|
||
def batch_generator(X, y, batch_size): | ||
images = np.empty([batch_size, IMAGE_HEIGHT, IMAGE_WIDTH, IMAGE_CHANNELS]) | ||
steers = np.empty(batch_size, 5) | ||
while True: | ||
i = 0 | ||
for index in np.random.permutation(X.shape[0]): | ||
images[i] = X[index] | ||
steers[i] = y[index] | ||
i += 1 | ||
if i == batch_size: | ||
break | ||
yield (images, steers) | ||
|
||
|
||
# step5 评估模型 | ||
#def evaluate(x_test, y_test): | ||
#score = model.evaluate(x_test, y_test, verbose=0) | ||
#print('Test loss:', score[0]) | ||
#print('Test accuracy:', score[1]) | ||
|
||
|
||
|
||
|
||
|
||
# step6 | ||
|
||
|
||
|
||
|
||
# step7 | ||
|
||
|
||
|
||
|
||
def main(): | ||
# 打印出超参数 | ||
|
||
print('-'*30) | ||
print('parameters') | ||
print('-'*30) | ||
|
||
|
||
keep_prob = 0.5 | ||
learning_rate = 0.0001 | ||
nb_epoch = 100 | ||
samples_per_epoch = 3000 | ||
batch_size = 40 | ||
|
||
print('keep_prob = %f', keep_prob) | ||
print('learning_rate = %f', learning_rate) | ||
print('nb_epoch = %d', nb_epoch) | ||
print('samples_per_epoch = %d', samples_per_epoch) | ||
print('batch_size = %d', batch_size) | ||
print('-' * 30) | ||
|
||
# 开始载入数据 | ||
data = load_data() | ||
# 编译模型 | ||
model = build_model(keep_prob) | ||
# 在数据集上训练模型,保存成model.h5 | ||
train_model(model, learning_rate, nb_epoch, samples_per_epoch, batch_size, *data) | ||
|
||
|
||
if __name__ == '__main__': | ||
main() | ||
|
||
|
||
|
||
|
||
|
||
|