使用 Carla 和 Python 的自动驾驶汽车第 4 部分 —— 强化学习Action
歡迎來到自動駕駛汽車的第五部分,并與Carla、Python和TensorFlow加強學習。
現在我們已經有了環境和代理,我們只需要添加更多的邏輯將它們連接在一起,這是我們接下來要做的。
首先,我們將從強化學習教程中復制粘貼修改后的張量板類:
from keras.callbacks import TensorBoard ... # Own Tensorboard class class ModifiedTensorBoard(TensorBoard):# Overriding init to set initial step and writer (we want one log file for all .fit() calls)def __init__(self, **kwargs):super().__init__(**kwargs)self.step = 1self.writer = tf.summary.FileWriter(self.log_dir)# Overriding this method to stop creating default log writerdef set_model(self, model):pass# Overrided, saves logs with our step number# (otherwise every .fit() will start writing from 0th step)def on_epoch_end(self, epoch, logs=None):self.update_stats(**logs)# Overrided# We train for one batch only, no need to save anything at epoch enddef on_batch_end(self, batch, logs=None):pass# Overrided, so won't close writerdef on_train_end(self, _):pass# Custom method for saving own metrics# Creates writer, writes custom metrics and closes writerdef update_stats(self, **stats):self._write_logs(stats, self.step)提醒一下,上面的代碼只是為了簡化TensorFlow/TensorBoard所做的日志量。通常,每個配置都有一個日志文件,每個步驟都有一個數據點,這很快就變得非常荒謬,隨著強化學習(在哪里適合每個步驟!)
讓我們添加以下導入:
import tensorflow as tf import keras.backend.tensorflow_backend as backend from threading import Thread在那之后,我們將去我們的腳本底部和:
if __name__ == '__main__':FPS = 60# For statsep_rewards = [-200]# For more repetitive resultsrandom.seed(1)np.random.seed(1)tf.set_random_seed(1)# Memory fraction, used mostly when trai8ning multiple agentsgpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=MEMORY_FRACTION)backend.set_session(tf.Session(config=tf.ConfigProto(gpu_options=gpu_options)))# Create models folderif not os.path.isdir('models'):os.makedirs('models')# Create agent and environmentagent = DQNAgent()env = CarEnv()首先,我們設置一些FPS值(每秒幀數)。當我們開始的時候,我們會有很高的,這意味著我們很有可能隨機選擇一個行動,而不是用我們的神經網絡預測它。隨機選擇要比預測操作快得多,所以我們可以通過設置某種一般FPS來任意延遲這一過程。當epsilon為0時,你應該將其設置為你實際的FPS。我們將為可重復的結果設置隨機種子,然后指定GPU內存比例。您可能不需要這樣做,但我的RTX Titan似乎有問題,至少在Windows上,當它試圖分配盡可能多的內存時,運行耗盡。
接下來,我們將創建模型目錄(如果它還不存在的話),這就是我們的模型的位置。然后創建代理和環境類。
# Start training thread and wait for training to be initializedtrainer_thread = Thread(target=agent.train_in_loop, daemon=True)trainer_thread.start()while not agent.training_initialized:time.sleep(0.01)開始訓練線程,并等待訓練被初始化,正如評論所說的!
# Initialize predictions - forst prediction takes longer as of initialization that has to be done# It's better to do a first prediction then before we start iterating over episode stepsagent.get_qs(np.ones((env.im_height, env.im_width, 3)))現在,我們準備開始迭代,不管我們設置了多少集:
# Iterate over episodesfor episode in tqdm(range(1, EPISODES + 1), ascii=True, unit='episodes'):#try:env.collision_hist = []# Update tensorboard step every episodeagent.tensorboard.step = episode# Restarting episode - reset episode reward and step numberepisode_reward = 0step = 1# Reset environment and get initial statecurrent_state = env.reset()# Reset flag and start iterating until episode endsdone = Falseepisode_start = time.time()我們的環境的一些初始值,現在我們可以運行了。基本上,一個環境會一直運行直到它完成,所以我們可以使用一個While True循環并在我們的done標志上中斷。
在游戲過程中,我們要么采取隨機行動,要么根據代理模型確定當前行動:
# Play for given number of seconds onlywhile True:# This part stays mostly the same, the change is to query a model for Q valuesif np.random.random() > epsilon:# Get action from Q tableaction = np.argmax(agent.get_qs(current_state))else:# Get random actionaction = np.random.randint(0, 3)# This takes no time, so we add a delay matching 60 FPS (prediction above takes longer)time.sleep(1/FPS)現在,我們將從環境的.step()方法中獲取信息,該方法將我們的action作為參數:
new_state, reward, done, _ = env.step(action)# Transform new continous state to new discrete state and count rewardepisode_reward += reward# Every step we update replay memoryagent.update_replay_memory((current_state, action, reward, new_state, done))current_state = new_statestep += 1if done:break一旦我們完成了,我們需要做什么?首先,我們需要擺脫演員:
# End of episode - destroy agentsfor actor in env.actor_list:actor.destroy()現在,對于一些具有良好獎勵的統計數據+保存模型(或任何其他你決定設置為if語句的規則):
# Append episode reward to a list and log stats (every given number of episodes)ep_rewards.append(episode_reward)if not episode % AGGREGATE_STATS_EVERY or episode == 1:average_reward = sum(ep_rewards[-AGGREGATE_STATS_EVERY:])/len(ep_rewards[-AGGREGATE_STATS_EVERY:])min_reward = min(ep_rewards[-AGGREGATE_STATS_EVERY:])max_reward = max(ep_rewards[-AGGREGATE_STATS_EVERY:])agent.tensorboard.update_stats(reward_avg=average_reward, reward_min=min_reward, reward_max=max_reward, epsilon=epsilon)# Save model, but only when min reward is greater or equal a set valueif min_reward >= MIN_REWARD:agent.model.save(f'models/{MODEL_NAME}__{max_reward:_>7.2f}max_{average_reward:_>7.2f}avg_{min_reward:_>7.2f}min__{int(time.time())}.model')接下來讓epsilon衰減:
# Decay epsilonif epsilon > MIN_EPSILON:epsilon *= EPSILON_DECAYepsilon = max(MIN_EPSILON, epsilon)最后,如果我們已經迭代了所有的目標章節,我們就可以退出了:
# Set termination flag for training thread and wait for it to finishagent.terminate = Truetrainer_thread.join()agent.model.save(f'models/{MODEL_NAME}__{max_reward:_>7.2f}max_{average_reward:_>7.2f}avg_{min_reward:_>7.2f}min__{int(time.time())}.model')讓我們繼續播放它,它將播放100集。在泰坦RTX上100集需要17分鐘。
你應該有一些日志文件,我們來看看。
tensorboard --logdir=logs/根據您的操作系統,您需要導航到的內容可能會有所不同。在linux上,無論它告訴您什么(應該在控制臺輸出中給您一個URL)都應該足夠了,可能127.0.0.1:6006也可以工作。在windows上,我發現唯一適合我的是localhost:6006。無論你做什么都要去那里!無論如何,一旦那里,我們可以搜索匹配以下正則表達式的標簽:\w(任何字母),并看到所有的圖形在一起。對我來說,我有:
所以,不足為奇的是,我們并沒有在100集節目中突然學會如何成為一名出色的司機(從我們的平均回報來看),所以我們可能應該取消那些投資會議,以推介下一家價值數十億美元的自動駕駛汽車初創公司。
我忘記添加模型了。保存到我第一次測試時的代碼中,所以我最終再次運行。這一次,我得到了更好看的結果。主要注意損失是如何從爆炸中恢復過來的。
現在,我們只拍了100集。我想我們需要10萬集才能看到像樣的東西,前提是我們的其他問題也都解決了。也就是說,“看到”您實際的代理運行是有幫助的。所以這里有一個快速的腳本,只是播放和看到你的模型在行動:
將導入tutorial5_code重命名為RL代理/env/培訓器腳本,然后修改MODEL_PATH = 'models/Xception__-118.00max_-179.10avg_-250.00min__1566603992。你使用的模型,因為你的模型名將與我的不同。
我需要再次強調,這只是100集。但是,我們可以看到代理只學會了做一件事。Agent可能只學習做一件事,因為你的Q值實際上是靜態的(模型輸出相同的Q值,不管輸入),或者,就像我們的例子,它們都是變化的,只是右轉總是更高。
我在這里看到的另一件事是,有時左轉比直轉高,有時直轉比左轉高。所以還是有希望的。我在《俠盜獵車手5》系列的自動駕駛汽車中學到的一件事是,你可以添加一個輸出層權重。
例如,在play腳本中,你可以這樣修改qs:
qs = model.predict(np.array(current_state).reshape(-1, *current_state.shape)/255)[0]qs *= [0.975, 1, 0.92]action = np.argmax(qs)這是網絡的最后一層。再說一遍,這對100集的模型沒有幫助。我們發現的下一件事是,保持獎勵為-1和正1可能會更好。沒有更多的-200。我們發現這可能會破壞Q值,而這似乎會破壞損失并導致混亂。我們甚至可以做進一步的剪輯。
我們所做的下一個改變是將我們的神經網絡簡化為一個2-3層的CNN,每個CNN有64-256個功能。還不確定,但越簡單越好,需要學習的參數越少。對于完全監督學習,我認為更多的參數更有效,因為一切都是“基本事實”。對于強化學習,我認為對于人工智能來說,要想讓自己從愚蠢的洞穴中解脫出來太難了,因為它一開始要嘗試訓練成千上萬的重量。
無論如何,這就是本教程的全部內容。在下一篇教程中,我將為您帶來一個工作模型,并告訴您我是如何做到的。
總結
以上是生活随笔為你收集整理的使用 Carla 和 Python 的自动驾驶汽车第 4 部分 —— 强化学习Action的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用 Carla 和 Python 的自
- 下一篇: 2019年第十届蓝桥杯 - 省赛 - C