项目来源:https://github.com/Jerry2001Qu/Self-Driving-Car
此项目源码运行时会报以下错误:
AttributeError: 'NoneType' object has no attribute 'center'
源码以下部分有问题。暂未解决。
class Game(Widget):
car = ObjectProperty(None)
ball1 = ObjectProperty(None)
ball2 = ObjectProperty(None)
ball3 = ObjectProperty(None)
def serve_car(self):
self.car.center = self.center
self.car.velocity = Vector(6, 0)
强化学习使机器(或者称为智能体)通过实验学习。就像人类学习走路。起初,你以一定的方式移动你的腿,但是你会跌倒。你跌倒了很多次,但最终,经过多次尝试,你会慢慢学会如何移动你的腿来走路。强化学习的原则与此相同!
比较正式的说法是,具有特定状态的环境中的智能体具有可以执行的一组动作。在执行这些动作后,它会收到一个奖励 ,让智能体知道这个动作有多好。当然,我们希望得到与我们目标相符的最高的奖励。贝尔曼方程用于说明未来的奖励,它通常是一系列导致积极结果的动作。在Q学习函数(Q-Learning)中,我们使用这些奖励来更新可以告诉我们某个状态有好坏的Q值。在深度Q学习(Deep Q-Learning)中,我们使用可以近似Q值的深度神经网络来代替Q值。当下次我们的智能体在环境中移动时,它将使用深度Q网络(Deep Q-Network)为每个动作生成Q值,并采用具有最高Q值的动作。
我们采取的行动会产生正面或反面的后果。如果它是正面的,我们会再次采取行动,反之亦然。
此强化学习算法从屏幕的左上角驱动到右下角,一旦到达角落就会朝另一个方向移动。它将保持从左上角到右下角,然后从右下角到左上角并重复。这些点将被称为汽车的目标。
您可以在屏幕上绘制“沙子”,算法将尝试避免那些沙子(它会收到负面奖励)。
该算法利用具有5个输入的深度Q学习。前3个输入来自汽车前部,左侧和右侧的3个传感器,它们返回周围的沙块数量。最后2个输入返回汽车的方向,值为-1到1,表示对应于目标的-180到180度之间的值。
从一张空地图开始。“汽车”的目标是在地图的左上角到右下角之间来回移动。
但是,我可以在地图上绘制“沙地”。如果汽车碰到了沙地,就会被视为出了车祸!
我们将使用强化学习(RL),特别是深度Q-Learning来制造我们的自动驾驶汽车。RL算法都有3个关键元素,状态(State),动作(Action)和奖励(Reward)。以下程序中定义这些元素的方式:
汽车所处的状态包括5个变量:
前三个来自汽车前部的3个传感器。每个传感器(红色,黄色,蓝色)都能探测到距离自身10像素半径内的沙地的像素。从逻辑上讲,也就是说,如果汽车左侧有一堵沙墙,蓝色传感器会比黄色传感器探测到的沙地更多。这使汽车可以确定沙地的位置,从而确定行进的方向。最后2个变量代表汽车的方向。以角度衡量,0度将指向上方。我们还添加了负方向方便优化和提升性能。
有三种可能的行动:
主要奖励包括:
这些只是主要的奖励。我还根据汽车的性能定义了其他奖励。例如,我后来意识到汽车离地图的边缘太近了,所以每当距离边缘10个像素内时我就给它一个负奖励。在实践中,你可以自行定义奖励,以获得自己想要达到的效果。
该算法获得了向对象前进的小奖励以及用于离开的小额负奖励。这些值设置为0.1和-0.1。这些值保持较小,以便汽车可以自由地向相反方向驱动一点,以避免沙子而不会受到严重的惩罚。相比之下,如果汽车越过沙子,汽车将获得-5奖励。此外,如果汽车靠近地图的两侧,汽车将获得-1奖励。最后,每当算法达到由previous_steps- current_steps定义的目标时,就接收变量/缩放奖励。这个额外的奖励将确保算法因为采用比前一次运行更长的路线而受到惩罚,并且如果它采用更短的路线将会得到奖励。
使用强化学习,特别是深度Q学习。这是我的神经网络的架构:
一个隐藏层通常足以解决这类简单的问题。再进行训练需要更长的时间,并且不会带来显著的性能提升。
class Network(nn.Module):
def __init__(self, input_size, nb_action):
super(Network, self).__init__()
self.input_size = input_size
self.nb_action = nb_action
self.fc1 = nn.Linear(input_size, 30)
self.fc2 = nn.Linear(30, nb_action)
def forward(self, state):
x = F.relu(self.fc1(state))
q_values = self.fc2(x)
return q_values
训练时,汽车开始行驶,并逐渐适应环境。我添加了按钮来保存,并将以前的模型加载到当前的自动驾驶汽车中。以下是我们实际学习的代码片段:
def learn(self, batch_state, batch_next_state, batch_reward, batch_action):
outputs = self.model(batch_state).gather(1, batch_action.unsqueeze(1)).squeeze(1)
next_outputs = self.model(batch_next_state).detach().max(1)[0]
target = self.gamma*next_outputs + batch_reward
td_loss = F.smooth_l1_loss(outputs, target)
self.optimizer.zero_grad()
td_loss.backward(retain_variables = True)
self.optimizer.step()
智能体每次接近目标时都获得+1奖励,远离则获得-1奖励。这由+0.1和-0.1累积而来。训练在1500个时间步后达到稳定水平。
当智能体视离目标的远近分别获得+0.1和-0.1奖励。如你所见,奖励在2000步之后稳定了,而不是这次的1500步。这两个图平均需要10个不同的训练周期。结果表明,+1和-1奖励训练速度比+0.1和-0.1奖励更快。
对该模型进行了许多其他更改。比如:
预测
现在,通过优化模型。汽车可以无碰撞地进行自动驾驶!这里开发了RL驱动的自动驾驶汽车的基础架构,现实生活中的汽车将更难进行编码。
参考:http://www.atyun.com/32420.html