RK-JETBOT 避開障礙物功能多類別辨識教學 – 訓練模型與下場比賽篇

前言

前一篇介紹了如何將 NVIDIA Jetbot 原廠避障範例從雙類別改為多類別,由於篇幅關係只講到收集資料,本文接續把後續兩大步驟,也就是訓練模型與實際展示一口氣講完喔!來看看 CAVEDU YTshort 吧,歡迎按讚訂閱分享開啟小鈴鐺喔

CAVEDU 教育團隊針 對 Jetbot 已辦理過多次 Jetbot 道路識別競賽,有興趣的單位歡迎洽詢,我們可提供研習、師資訓練與比賽相關設備!

本文

本文接續 [RK-JETBOT 避開障礙物功能多類別辨識教學 – 收集資料篇],介紹訓練模型與實際展示兩大階段,希望各位都能從中體驗機器人的魅力!

撰寫/攝影 郭俊廷
時間 2 小時 材料表
難度 3(滿分5)

訓練模型

在畫面左側的畫面中,開啟 home > jetbot_CAVEDU/collision_avoidance/train_modelC3.ipynb,這個檔案負責把前一個步驟所收集的資料集訓練成 pytorch 模型檔 (.pth)。

以下區塊是解壓縮資料集壓縮檔,如果不需要解壓縮的話可以跳過這一步驟。更改以下語法中的 dataset.zip 檔名來對應到您實際的檔案名稱。預設是註解掉程式無法執行,如要執行請取消註解即可。

第1個區塊設定訓練用資料集的資料夾名稱,更改底下的 class3 來對應實際名稱。

第2個區塊設定訓練後的模型檔名稱,請自由更改 ‘ ‘ 中內容來對應您要的模型檔名。第3個區塊設定訓練回合數預設是20回合,建議也訓練20回合以上。

執行第4個區塊,匯入PyTorch, NumPy, Python Imaging Library等函式庫,在此無需修改,日後等您對於程式架構更佳掌握之後再回頭試試看吧!

第5、6個區塊設定功率模式以及開啟風扇,這裡的語法同樣不需要也不建議修改。設定功率模式為 5W,是因為當訓練時Jetson Nano功率會使用到最大功率,如果使用MICRO USB供電時會因為輸出功率不足而斷電,如果改用 DC接頭供電就可以使用10W功率訓練。

第7個區塊會建立一個 dataset 實例,把 dataset 資料夾中的資料使用 torchvision.datasets 套件包與 torchvision.transforms數據包來分類跟轉換資料。

第8個區塊將資料集拆分為訓練集和測試集。

第9個區塊設定訓練集和測試集的參數

第10個區塊是定義神經網路,在此使用 alexnet 模型,初次使用會下載alexnet模型,實際下載時間根據您的網路速度而異,請耐心等候,並區塊前面顯示*號。(如果是使用 CAVEDU 所提供的映像檔,則都已經預先下載好囉!)

第11個區塊是將 alexnet 模型原本的1000個類別標籤輸出,改為3個。之所以為 3 是因為本範例共要辨識三個不同的障礙物,如果您希望辨識更多類別則請修改這個數字。

第12個區塊是將模型搬到在GPU上執行。

第13個區塊即開始將資料集訓練成模型檔,預設訓練20回合,根據建議各類別100張左右的照片訓練時間大約為十分鐘。訓練完成會產生一個一開始設定好名稱best_model3class.pth的模型檔(訓練完成後會如下圖所示顯示Done!)

最後一個區塊執行後會關閉風扇。

Live Demo 下場試車啦

這是一系列範例中的第三個 ipynb,也是最後一個,您的車子會使用先前所訓練好的 .pth 模型檔來執行視覺辨識任務。

在畫面左側的畫面中,開啟 home >jetbot_CAVEDU/collision_avoidance/live_demoC3.ipynb,就能看到 Collision Avoidance – Live Demo 畫面。

這份程式負責執行訓練好的模型檔,也就是根據攝影機畫面進行推論為某個類別,並做出您所設定的動作。

請注意:在此需要有相對應的模型檔才可以執行該檔案,換言之,如果您已經有現成模型的話,就可以直接開車啦!實際跑車時,場地的背景跟燈光不能與收集資料集的狀況差異太多,否則視覺辨識的效果會不好喔。

第2個區塊使用 best_model_3class.pth 這個模型,請自行修改為您實際的檔名。

第2個區塊定義馬達參數,CAVEDU 目前採用 DFRobot 馬達驅動板所以不需要修改,如果您使用其他板子例如 waveshare 請自行修改。
執行後看到下圖 board begin success 代表馬達驅動板正常啟動,如果顯示失敗請檢查板子有無正確插上Jetson Nano上的GPIO以及正確接上電源。

第3、4個區塊設定功率模式以及開啟風扇,設定功率模式到 10W 可以提高系統效能。

第5個區塊是設定 PyTorch 的 alexnet 模型參數,請注意下圖數字 3 需對應先前所訓練模型的資料類別,如果您希望更多類別則記得要修改為對應的數字。

第6個區塊是載入模型檔,第7個區塊是把模型權重從 CPU 記憶體搬到 GPU 來執行。

第8個區塊是定義影像預處理方法,依序執行了以下內容

  • 從BGR轉換為RGB模式
  • 從HWC佈局轉換為CHW佈局
  • 使用與訓練期間相同的參數進行正規化(攝影機像素範圍是[0,255],因此要 / 255 將其調整到範圍內的值,並在[0,1]範圍內訓練加載的圖像,因此我們需要縮放255.0
  • 將資料從 CPU 搬到 GPU
  • 針對批 (batch) 新增一個維度

第9個區塊建立一個大小為 224 * 224 的攝影機畫面,並針對每一個類別都有一個對應的滑桿,以視覺效果來呈現攝影機目前畫面所對應的類別機率 (機率值為 0~1 之間的小數),如下圖。

根據之前蒐集的資料分為a b c三個滑桿對應other blue red 三種類別的機率
a_slider = widgets.FloatSlider(description='other', min=0.0, max=1.0, orientation='vertical')
b_slider = widgets.FloatSlider(description='blue', min=0.0, max=1.0, orientation='vertical')
c_slider = widgets.FloatSlider(description='red', min=0.0, max=1.0, orientation='vertical')

並且在最後顯示出來的畫面也需要對應:
display(widgets.HBox([image, a_slider, b_slider, c_slider]))

第10個區塊,執行後機器人就會動了,請注意不要將JetBot放在桌上或是容易摔落撞到的地方(心疼)。修改程式碼說明如下:

首先在全域變數宣告,把新增的prob_a , prob_b, prob_c, a_slider, b_slider, c_slider變數跟滑桿都加上 global:
global robot, prob_a , prob_b, prob_c, a_slider, b_slider, c_slider

接著宣告 prob_a , prob_b, prob_c是對應系統陣列裡的哪個參數。float(y.flatten()[0])、float(y.flatten()[1])、float(y.flatten()[2])排序是根據蒐集類別名稱的英文字母順序,如果是按照類別取名稱可能會造成排序錯亂,建議是按照英文字母順序取名。接著讓三個 slider.value 對應到各自的機率值。

prob_a = float(y.flatten()[0])
prob_b = float(y.flatten()[1])
prob_c = float(y.flatten()[2])

a_slider.value = prob_a
b_slider.value = prob_b
c_slider.value = prob_c

最後是修改程式碼將對應類別執行對應的動作,如下方程式會執行以下動作,您可以根據實際使用情境來修改機率門檻值與機器人動作:

  • 當判斷類別a(other)的機率大於0.5的時候就以40%的速度前進
  • 當判斷類別b(blue)的機率大於0.7就以70%的速度左轉
  • 當判斷類別c(red)的機率大於0.7就以70%的速度右轉

if prob_a > 0.5:
    robot.forward(0.4)
elif  prob_b > 0.7:
    robot.left(0.7)
elif  prob_c > 0.7:
    robot.right(0.7)

第11個區塊會更新攝影機畫面,如果沒有執行這一步驟,攝影機的畫面將無法同步,執行完這個區塊請往上拉回到第9個區塊來看看 JetBot 避障的效果如何。

第12個區塊,這裡會停止同步畫面,JetBot也會停止。第13個區塊是中斷攝影機的連結。

第14個區塊執行後會關閉風扇,風扇將會慢慢減速不會瞬間關閉請耐心等候。

總結

本文根據 JetBot 原廠教學,將原本的雙類別辨識擴充為多類別。機器人在製作過程有許多要注意的細節,幸好 NVIDIA Jetson 與 Jetbot 專案已經幫我們打通很多關節,期待您與我們分享您的機器人最新功能喔!

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *