AI/ML, Robotics

World Model

看到一篇跟之前想過的想法很像的論文,先記錄一下:

https://worldmodels.github.io/

Advertisements
AI/ML, Robotics

深入淺出 End-to-End Learning on Robotics

前言

隨著機器人不斷地發展,機器人已經越來越聰明,可以漸漸學習執行更高複雜度的任務。在實作如此複雜的機器人時,參考人類的學習能力是很自然的一件事情。人類學習是一大黑盒子,從五官收到 sensory input,對應到所有肌肉的 control output。學習藉著 raw sensory input ,產生最後的 control output,就稱為 end-to-end learning。

相較來說,傳統方法常傾向把過程中的每一個功能都拆分成一個個 module,再將這些 module 串成一個 pipeline,無法評論哪個好,只是呈現給大家看。

end-tp-end

接下來我們會帶大家一起來讀 End-to-End Training of Deep Visuomotor Policies,對這類方法有簡單的認識。雖然這篇論文提出的架構並沒有辦法讓機器人像人類般聰明地做事情(光是接收到的 sensor input 就還比人類少很多,起碼缺少了聽覺、觸覺、味覺、嗅覺),但是這篇論文仍然提出了一個很好的架構,有初步的廣泛應用能力(e.g. 學會怎麼掛上衣架後,就算衣架上有毛巾還是可以掛上)、並且可以處理用 hand crafted 程式很難做到的複雜任務(像是旋緊瓶蓋、把方塊放進大小接近的洞裡),相當值得一讀。

可以做到的成果

他們用來實驗的 task 包含了下圖中的幾種任務,我們可以先看看下面的影片

gps-task.JPG

由此影片應該看得出這個架構有它厲害的地方,接著就讓我們來看看它是怎麼做到的!

黑盒子架構簡介

這篇論文的目標,是希望可以讓機器人學習從 raw image input 擷取出重要的資訊,來決定要怎麼產生 action。所以可以預期,我們應該要有一個黑盒子,接收 raw image input,直接產生機器人的 motor control output(就像我們控制各種肌肉一般),而這個黑盒子,就由 DNN 來實作。

先上個黑盒子的架構圖;

gps-architecture.JPG

架構圖跟我們一開始認為的目標是相合的,最左邊的 input 接收的是 240 x 240 的 raw image input,經過了中間的 7 層 layer 之後,產生最後的 motor torque(就是馬達要做什麼 action)。前面的 4 層 layer 都是在處理影像、抽取特徵,後面的 3 個 layer 則是將特徵對應到 motor torque。

這個黑盒子就是這篇論文提到的 policy,policy 的定義如下圖,基本上就是會根據 observation o,產生 action u 的機率分布(採取各種不同 action 的機率):

gps-head.JPG

gps-policy

gps-u_and_o

如果您是對 DNN 有些了解的讀者,您一定會想問,這看起來不就只是個 supervised learning 嗎?好像也沒什麼特別的啊?

其實,只要牽扯到機器人,要收集海量的 training data 就是一件很困難的事情,不過答案沒有這麼簡單!要可以做到影片中的結果,就算你真的認真地收集了海量的 data,透過 supervised learning 來訓練上面這個 DNN 也還是會失敗。換句話說,這篇論文完全不是直接使用大量的 training data 來訓練上面這個黑盒子。

之所以不這樣訓練是因為,就算用海量的資料訓練出了一個 fitting error 很小的黑盒子,在實際執行的過程中,肯定還是會因為觀察到的 observation 跟 training data 不同、採取的 action 有誤差等等,逐漸產生在 training 過程中沒看過的 state,最後就很容易導致在 testing 過程中發生各種錯誤。(我們把這個問題簡稱為 training data 不是從 policy 來的問題)舉例來說,如果我們要訓練一個自動駕駛的系統,我們會提供很多人類開車的 training data,但是人類開車通常都是處在很正常的狀態,轉彎的時候也通常會離牆壁很遠,但如果自動駕駛系統在遇到彎道時,有一些控制誤差,使車子很靠近牆壁,這種狀況就是 training data 中不太會有的 state,這時候就有點恐怖了,因為你沒 train 過它這種狀況,你就不知道它會採取什麼行為。

要避免這個問題,就是要在 training 時,讓上面的黑盒子自己產生 training data,這樣在訓練時,就真的是看到自己採取的各個 action 是好還是不好。這就很像是我們在學習的過程中,自己動手下去做,才會真正知道自己有什麼問題。譬如我們可以看很多諸葛亮的故事,覺得他好聰明,但是知道他在那些狀況下會採取的行動,對我們的幫助通常不大,基本上就只是在看故事而已,因為我們不太可能碰到司馬懿帶兵來打、自己兵又很少,可以使用空城計的狀況,重點應該是我們在日常生活中碰到狀況,要能用諸葛亮的智慧來採取行動。

這就是避免 training data 不是從 policy 來的問題 的核心精神,必須用我們自己的 policy 去採取行動,並透過這些行動造成的結果好壞,來改進我們的 policy,這個概念可以簡化如下圖:

gps-rl.JPG

既然講到這邊,就讓我延伸一下,做完行動,該怎麼評判自己做得好不好(estimate return)就是眼界問題了。同樣做一件事,不同格局的人所下的評價可能天差地別,例如有一個學生 A 想要全力發展自己的強項,有的老師可能覺得將一項專長磨練到頂尖很好、有的老師可能認為應該先補足弱項才好。假設 A 只有兩種 action (發展強項 or 發展弱項)可以採取,當他的 observation 是看到自己的強項有好的表現 & 有些弱項表現得不好,他得把發展強項帶來的好處的 return 估計得更高,把弱項減損的 return 下修,他才會去發展強項。若是走發展強項之路,他最後很可能會成為某領域的頂尖專家,而非各項都平平的人。這也是為什麼有好的老師(or mentor)很重要,因為他們可以用更高的眼界來 estimate return(用 Reinforcement Learning 的名詞來說,就是他們的 reward function 更好)。好了,題外話講完,讓我們繼續往下看。

Training 方法簡介

看到這邊大家應該很好奇,上面的概念講起來很簡單,在這篇論文是怎麼實際 train 那個 7 層的黑盒子呢?

讓我們先看這篇論文的 training 方法概念圖:

gps-train.JPG

核心的概念是這樣,首先我們先有一個 RL 的演算法,幫助我們產生一個可以拿來當作指導者的 guiding distribution – Pi(就是上圖最左下角的 optimize local controller Pi),這個 guiding distribution 就可以產生一系列的 action 與 state pair(也就是上圖中的 collect samples from Pi),然後,我們再將這一些由指導者產生的 sample,拿來訓練我們的 policy(上圖右下角的 train global policy to match local controller,也就是單純的 supervised learning),使 policy 無限逼近指導者。

原本要直接訓練上面的黑盒子很困難,因為要產生大量的 training data 非常困難,但是因為有了 Guided Policy Search(GPS)的架構,我們就可以同時滿足:

  1. Training data 是來自於 policy 本身(雖然實際上是來自於指導者的 guiding distribution,但是經過 GPS 訓練,policy 跟指導者會有相同的行為,所以沒問題)
  2. 有了可以拿來產生 supervised sample 的指導者,解決不知道哪來 data 可以 train 的問題

我們可以看一下這一小段論文加強理解:

一開始的 avoid this issue 指的是要避免 training data 不是從 policy 來的問題,所以他們交互使用 RL 跟 supervised learning,加上又已經有理論(Wang and Banerjee, 2014)證實這種訓練方法可以讓 policy 跟指導者的 guiding distribution 有相同行為,所以訓練可行。

gps-theory.JPG

接下來您可能會想問,我們憑什麼相信指導者的 guiding distribution 可以產生 supervised learning 的 training data?

Guided Policy Search 方法簡介

上一段最後的問題已經逼近核心了,最後就讓我們再回答這個問題。我們之所以可以相信指導者的 guiding distribution,是因為 guiding distribution 是透過 system dynamics 來優化的。而 system dynamics 就是真實世界的運行法則(接下來,guiding distribution == controller,為了符合論文的語言,方便待會閱讀)。

system dynamics 可以告訴我們, given 某個 state 跟 action,下一個 state 的機率分布會是什麼。換句話說,state dynamics 跟你說若你種了這些因,你會得到什麼果。而 controller 是為了達到某個 goal state,而採取 action,也就是可以告訴你為了達到某個果,你要種什麼因。所以 state dynamics 可以用來修正 controller 對因果關係的了解。

舉個生活化的例子,假設今天是星期天,你想吃飽,你就走去附近的小吃店 A 買食物,但是你走到那邊發現,那間小吃店 A 星期天公休。這個過程就是:

  1. 一開始,你處在星期天的飢餓 state,所以你要採取 action
  2. 你的 controller 跟你說,星期天飢餓時,走去附近某小吃店 A 就對啦!讚讚
  3. 走到某小吃店 A,才由 system dynamics 無情地跟你說,你在星期天飢餓時,走去小吃店,你會看到的下一個 state 是,小吃店 A 沒開
  4. 於是你就可以修正自己的 controller,知道下次星期天飢餓時,不要走去小吃店 A 了

也就是說,只要您實際嘗試,您一定可以透過這個世界的真實狀態(system dynamics),修正自己的認知(controller),不再天真地認為走去小吃店 A 就有東西吃。

這就是為什麼我們可以相信 guiding distribution 的直觀原因。上述概念完全可以在下圖中重新印證,您可以看看下圖中的論文原文再強化一下觀念。

gps-policy-1gps-policy-2

詳細為何可以 optimize linear-Gaussian controllers 就不提了,有點太過理論,若有興趣可以自行去看論文中 Section 4.2 的數學說明!

總結

今天我們跟大家簡單介紹了 End-to-End learning 的概念,並用一篇論文來詳細地介紹這種概念怎麼在機器人上運用(利用 guided policy search)。

此外,在過程中我順便 demo 了一下可以比較快速地了解一篇論文的閱讀法(先看動機 -> 看結果可以做到什麼 -> 問他們憑什麼可以做到 -> 直接找到關鍵答案,所以像 related work 就會在此閱讀方法中被忽略),希望對各位有幫助!

延伸閱讀

  1. Guided Policy Search 網頁
  2. Policy gradients introduction

如果您對機器人或是 ROS 相關文章有興趣,歡迎到 我的首頁 看更多文章!

Robotics, ROS

How to solve ResourceNotFound: gazebo_worlds error when running simulated PR2 for gps?

When I tried to launch the simulated PR2 by

roslaunch gps_agent_pkg pr2_gazebo.launch

This error occurred:

 

gazebo_worlds_error

ros@ros-K401UB:~/research/gps/src/gps_agent_pkg$ roslaunch gps_agent_pkg pr2_gazebo.launch
... logging to /home/ros/.ros/log/10b10e84-bbe8-11e7-944c-82ea96c4b45e/roslaunch-ros-K401UB-7307.log
Checking log directory for disk usage. This may take awhile.
Press Ctrl-C to interrupt
Done checking log file disk usage. Usage is <1GB.

Traceback (most recent call last):
 File "/opt/ros/indigo/lib/python2.7/dist-packages/roslaunch/__init__.py", line 307, in main
 p.start()
 File "/opt/ros/indigo/lib/python2.7/dist-packages/roslaunch/parent.py", line 268, in start
 self._start_infrastructure()
 File "/opt/ros/indigo/lib/python2.7/dist-packages/roslaunch/parent.py", line 217, in _start_infrastructure
 self._load_config()
 File "/opt/ros/indigo/lib/python2.7/dist-packages/roslaunch/parent.py", line 132, in _load_config
 roslaunch_strs=self.roslaunch_strs, verbose=self.verbose)
 File "/opt/ros/indigo/lib/python2.7/dist-packages/roslaunch/config.py", line 451, in load_config_default
 loader.load(f, config, verbose=verbose)
 File "/opt/ros/indigo/lib/python2.7/dist-packages/roslaunch/xmlloader.py", line 746, in load
 self._load_launch(launch, ros_config, is_core=core, filename=filename, argv=argv, verbose=verbose)
 File "/opt/ros/indigo/lib/python2.7/dist-packages/roslaunch/xmlloader.py", line 718, in _load_launch
 self._recurse_load(ros_config, launch.childNodes, self.root_context, None, is_core, verbose)
 File "/opt/ros/indigo/lib/python2.7/dist-packages/roslaunch/xmlloader.py", line 682, in _recurse_load
 val = self._include_tag(tag, context, ros_config, default_machine, is_core, verbose)
 File "/opt/ros/indigo/lib/python2.7/dist-packages/roslaunch/xmlloader.py", line 95, in call
 return f(*args, **kwds)
 File "/opt/ros/indigo/lib/python2.7/dist-packages/roslaunch/xmlloader.py", line 625, in _include_tag
 default_machine, is_core, verbose)
 File "/opt/ros/indigo/lib/python2.7/dist-packages/roslaunch/xmlloader.py", line 682, in _recurse_load
 val = self._include_tag(tag, context, ros_config, default_machine, is_core, verbose)
 File "/opt/ros/indigo/lib/python2.7/dist-packages/roslaunch/xmlloader.py", line 95, in call
 return f(*args, **kwds)
 File "/opt/ros/indigo/lib/python2.7/dist-packages/roslaunch/xmlloader.py", line 587, in _include_tag
 inc_filename = self.resolve_args(tag.attributes['file'].value, context)
 File "/opt/ros/indigo/lib/python2.7/dist-packages/roslaunch/xmlloader.py", line 183, in resolve_args
 return substitution_args.resolve_args(args, context=context.resolve_dict, resolve_anon=self.resolve_anon)
 File "/opt/ros/indigo/lib/python2.7/dist-packages/roslaunch/substitution_args.py", line 316, in resolve_args
 resolved = _resolve_args(resolved, context, resolve_anon, commands)
 File "/opt/ros/indigo/lib/python2.7/dist-packages/roslaunch/substitution_args.py", line 329, in _resolve_args
 resolved = commands[command](resolved, a, args, context)
 File "/opt/ros/indigo/lib/python2.7/dist-packages/roslaunch/substitution_args.py", line 142, in _find
 source_path_to_packages=source_path_to_packages)
 File "/opt/ros/indigo/lib/python2.7/dist-packages/roslaunch/substitution_args.py", line 188, in _find_executable
 full_path = _get_executable_path(rp.get_path(args[0]), path)
 File "/usr/lib/python2.7/dist-packages/rospkg/rospack.py", line 203, in get_path
 raise ResourceNotFound(name, ros_paths=self._ros_paths)
ResourceNotFound: gazebo_worlds
ROS path [0]=/opt/ros/indigo/share/ros
ROS path [1]=/home/ros/rosbuild_ws/package_dir
ROS path [2]=/opt/ros/indigo/share
ROS path [3]=/opt/ros/indigo/stacks
ROS path [4]=/home/ros/research/gps
ROS path [5]=/home/ros/research/gps/src/gps_agent_pkg

This happened because gazebo_worlds only exists in the version before ROS Groovy. So,  you can modify the launch file by rosed gps_agent_pkg pr2_gazebo_no_controller.launch :

<launch>
 <!-- Use the following for ROS hydro or later: <include file="$(find gazebo_ros)/launch/empty_world.launch"> -->
 <include file="$(find gazebo_ros)/launch/empty_world.launch">
 </include>
 <include file="$(find pr2_gazebo)/launch/pr2_no_controllers.launch" />
</launch>

After modification, the error changes. Obviously, this is another problem (import glob error).

import_glob_error

 

Robotics, ROS

How to solve caffe.hpp: No such file or directory error when compiling gps_agent_pkg?

When I was make -j the gps_agent_pkg package, I met this error:

caffe_error

[100%] Building CXX object CMakeFiles/gps_agent_lib.dir/src/util.cpp.o
Building CXX object CMakeFiles/gps_agent_lib.dir/src/neuralnetworkcaffe.cpp.o
Building CXX object CMakeFiles/gps_agent_lib.dir/src/caffenncontroller.cpp.o
/home/ros/research/gps/src/gps_agent_pkg/src/caffenncontroller.cpp:1:27: fatal error: caffe/caffe.hpp: No such file or directory
#include "caffe/caffe.hpp"
^
compilation terminated.
make[2]: *** [CMakeFiles/gps_agent_lib.dir/src/caffenncontroller.cpp.o] Error 1
make[2]: *** Waiting for unfinished jobs....
In file included from /home/ros/research/gps/src/gps_agent_pkg/src/neuralnetworkcaffe.cpp:1:0:
/home/ros/research/gps/src/gps_agent_pkg/include/gps_agent_pkg/neuralnetworkcaffe.h:10:27: fatal error: caffe/caffe.hpp: No such file or directory
#include "caffe/caffe.hpp"
^
compilation terminated.
In file included from /home/ros/research/gps/src/gps_agent_pkg/include/gps_agent_pkg/caffenncontroller.h:10:0,
from /home/ros/research/gps/src/gps_agent_pkg/src/robotplugin.cpp:16:
/home/ros/research/gps/src/gps_agent_pkg/include/gps_agent_pkg/neuralnetworkcaffe.h:10:27: fatal error: caffe/caffe.hpp: No such file or directory
#include "caffe/caffe.hpp"
^
compilation terminated.

And this error should be solved bymake distribute in the caffe dir. Aftermake distribute successfully in the caffe dir, I compiledgps_agent_pkg.

gps_success.png

Robotics, ROS

Solving rospkg import error for gps (guided policy search)

I was trying to install gps on Ubuntu 14.04. Yet, an import error of rospkg popped out when I was compiling the gps package.

This link is useful, for users who do not understand the system very well, it is useful to solve problem. For me, all I need to do is to add the

vim ~/.bashrc 
export PYTHONPATH=$PYTHONPATH:/usr/lib/python2.7/dist-packages 
source ~/.bashrc

The root cause of this error is that Python packages in /usr path do not exist in PYTHONPATH variable.