Udacity利用深度学习玩赛车小游戏

Udacity利用深度学习玩赛车小游戏

  • 简单介绍
  • 准备工作
  • 训练网络
  • 效果

简单介绍

这是Udacity无人驾驶课程里一个利用深度学习实现的玩赛车小游戏,
附上链接:github项目
原理就是玩家手动让赛车在赛道上跑几圈,赛车上的三个摄像头捕捉到照片,并记录下照片对应的转角、速度信息。训练好后,玩家可以通过drive.py运行脚本实现赛车自己在赛道上跑。
当然,这只是游戏中能这样做,现实情况复杂太多,不可能用这种方式实现”无人驾驶“。但我觉得这依然是一个很有趣的深度学习小项目。可以帮助初学者很好地理解深度学习训练中的步骤,以及各种基本调优手段。

准备工作

下图就是游戏的启动界面,选择training model即可开始训练,快捷键”R“可以帮助纪录保存下训练集(赛车上的三个摄像头捕捉的图像和对应的速度转角信息)。
Udacity利用深度学习玩赛车小游戏_第1张图片

训练网络

首先是读取数据,并将数据转化为keras需要的numpy的array形式。其中要注意的是,左右两边的摄像头对应的转角应该会存在一些偏差。这里做一些简单的加减处理即可。

lines = []
images = []
measurements = []
with open('../../data_game/driving_log.csv') as csvfile:
    reader = csv.reader(csvfile)
    for line in reader:
        lines.append(line)
for line in lines:
    current_centre_path = line[0]
    current_left_path = line[1]
    current_right_path = line[2]
    image_centre = cv2.imread(current_centre_path)
    image_left = cv2.imread(current_left_path)
    image_right = cv2.imread(current_right_path)
    images.append(image_centre)
    images.append(image_left)
    images.append(image_right)
    measurement_centre = float(line[3])
    measurement_left = measurement_centre + 0.2
    measurement_right = measurement_centre - 0.2
    measurements.append(measurement_centre)
    measurements.append(measurement_left)
    measurements.append(measurement_right)
X_train = np.array(images)
y_train = np.array(measurements)

很显然,上述操作是非常粗糙简单的,我们都知道一个好的结果一定是需要充足的、良好的数据做支撑的,因此在训练之前,需要做一些简单的图像增强工作。比如将图片进行对称变换,随机给一些图片增加亮度或增加阴影,又或者对图像做一些随机偏移并改变相应的转角。

def random_shift(img, steering, shift_range=20):
    ht, wd, ch = img.shape
    
    shift_x = shift_range * (np.random.rand()- 0.5)
    shift_y = shift_range * (np.random.rand()- 0.5)
    shift_m = np.float32([[1, 0, shift_x], [0, 1, shift_y]])
    img = cv2.warpAffine(img, shift_m, (wd, ht))
    
    steering += shift_x * 0.002
    return img, steering

def flip(img, steering):
    if np.random.rand() < 0.5:
        img = cv2.flip(img, 1)
        if(steering != 0):
            steering = -steering 
    return img, steering

当然这样简单的处理还是不够的,为了让模型更好地收敛,在放入神经网络训练之前,还应当注意的是对原始数据做一个normalization和mean to centre

model.add(Lambda(lambda x:x/255.0 - 0.5, input_shape=(160,320,3)))

在训练之前,还有一点需要注意,那就是由于我们采集的图片相当于是连续视频中截取的,因此在训练时,最好可以打乱。同时,也可以做一个batch normalization
下面的函数可以完成这一工作,读取的是csv文件(以图片路径为索引)。乱序后进行batch的工作。(我自己训练的最好的模型实际并没有用这个函数)

def generator_batch(df, bs=32):
    total = len(df)
    while 1:
        sklearn.utils.shuffle(df)
        for offset in range(0, total, bs):
            batch = df[offset:offset+bs]
            images, angles = get_train_test_labels(batch, 0.2, 0.2)
            X_train = np.array(images)
            y_train = np.array(angles)
            yield sklearn.utils.shuffle(X_train, y_train)

最后就是模型的结构的训练步骤了,利用keras可以很轻易的写出

model = Sequential()
model.add(Lambda(lambda x:x/255.0 - 0.5, input_shape=(160,320,3)))
model.add(Cropping2D(cropping=((70,25), (0,0))))
model.add(Convolution2D(24,5,5, subsample=(2,2), activation="relu"))
model.add(Convolution2D(36,5,5, subsample=(2,2), activation="relu"))
model.add(Convolution2D(48,5,5, subsample=(2,2), activation="relu"))
model.add(Convolution2D(64,3,3, activation="relu"))
model.add(Convolution2D(64,3,3, activation="relu"))
model.add(Flatten())
model.add(Dense(100))
model.add(Dense(50))
model.add(Dense(10))
model.add(Dense(1))


model.compile(loss='mse', optimizer='adam')
model.fit(X_train, y_train, validation_split=0.2, shuffle=True, nb_epoch=5)

model.save('model.h5')

最后的最后,还是那句话,好的结果一定需要好的数据,如果训练效果不好,不妨尝试人工多跑两圈(正反),务必确保车都是在路中间行驶。

效果

利用文章开头的脚本,在终端里输入一下命令,并打开游戏客户端选择自动驾驶,即可开始自动玩游戏啦!

python drive.py model.h5

你可能感兴趣的:(Udacity利用深度学习玩赛车小游戏)