工程師用 Python 寫了能辨識動作的神經網路,只因為懶得爬下床關電燈!

【為什麼我們要挑選這篇文章】當你已經在床上耍廢一陣子,想要床關燈的確是很痛苦的一件事(特別是在冬天)。然而,有個工程師訓練了一個神經網路,它可以辨識肢體動作,進而開關電燈,使用者不需要走到開關旁邊。

以下是該工程師訓練神經網路的程式碼,有興趣的朋友就試試看吧!(責任編輯:郭家宏)

對於上了床就再也不想下來的人來說,關燈成為睡覺前面臨的最大挑戰!

然而網友永遠不會讓人失望,他們開發出了各種關燈大法:

當然少不了豆豆先生最簡單粗暴的關燈方式:

然而,一個來自義大利那不勒斯的網友,決定利用「舞步」(身體姿勢)來控制自己家的燈,整個過程利用一個神經網路來實現,就像這樣:

下面是該網友寫的教程,文摘菌(本文作者)在不改變原意的基礎上進行了編譯。

訓練神經網路,用「舞步」來開關電燈

在今天的文章裡,我將手把手教大家訓練一個神經網路模型,用來識別鏡頭拍下的「舞步」,從而控制燈的開關。

我們將在已有的 OpenPose 深度學習模型之上建立我們自己的模型,來識別身體的位置,然後,我們會建立一些樣本來代表各種身體的各種姿態。

當我們建立好舞步(包括嘻哈超人舞步、T-Pose 舞步)和其他身體姿態的樣本後,我們會清理數據集,然後利用這些樣例訓練我們的神經網路。

當神經網路訓練好之後,我們會用它來控制燈光。

今天的文章包括很多步驟,不過,所有的程式碼都在 Github 上,上面還包括了我已經蒐集到的原始數據樣例。

GitHub 傳送門

使用卡內基梅隆大學的數據集,建立自己的神經網路

首先就是數據 —— 大量數據。

我們今天即將採用的神經網路模型,卡內基梅隆大學的團隊也曾經使用過,他們用自己的全景數據集來訓練該模型。該數據集包括五個半小時的影片,影片中包含了 150 萬個手動添加的代表人體骨骼位置的標籤。

整個全景工作室的圓屋頂上裝有 500 個鏡頭,所有鏡頭都對準人,從不同角度記錄他們的動作。

這個全景工作室用構造訓練數據集幾乎是完美的,很方便進行電腦視覺的實驗。

今天,我們將在他們的工作基礎之上開始我們的工作。

首先我們會用他們的工具來創建一個很小的數據集。我們最終的神經網路只會使用 171 個姿勢,包括記錄的嘻哈超人舞步、T-Pose 舞步和其他姿態。每一個姿態都是從卡內基梅隆大學已有的工作中提取出來的。

神經網路的一個好處,就是你可以使用別人已經建成的模型,然後加入一些新的神經網路層,以此來擴展該模型。這個過程被稱之為遷移學習,因此我們可以用有限的資源來進行遷移學習。

從技術上來說,我們不會在這個項目中使用遷移學習,因為我們會對 OpenPose 的工作做一些細微的修改,然後建立一個獨立的神經網路。

那麼問題來了,我們該如何獲取數據呢?

寫一個程式,並利用 OpenCV 來收集帶標籤的數據

使用 OpenPose 的成果,我們得到了 25 個代表人體骨骼架構的標籤。我們可以寫一個程式來控制網絡鏡頭,在圖像上運行 OpenPose,然後將動作與鍵盤上的按鍵相對應。

也就是說,我們做出一個 T-Pose 的動作,然後在鍵盤上點擊 M 鍵,那麼這個動作就被歸到 T-Pose 那一類裡。我們按照這個方法去添加 171 個不同的姿勢,這樣一來,我們就有數據訓練神經網路了。以下是用於數據收集的程式碼範例(完整版請看 GitHub):

然後用 NumPy 的數組來儲存特徵,並用 np.save 函數把特徵保存為二進制文件以便後續使用。我個人傾向於使用 Jupyter notebook 來觀察和處理數據。

當數據收集好之後,我們可以觀察並清理數據,以便更好地去訓練模型。

觀察、清理並使用數據訓練模型

這部分看上去很複雜,但是透過使用 Jupyter notebook、NumPy 和 Keras,我們就可以很直觀地去觀察數據、清理數據,並且使用數據來訓練神經網路。

根據我們的截圖,我們可以發現 npy 文件中保存的數據和 OpenPose 模型本身都有三個維度,25 個已知的身體位置坐標點,X、Y、以及 Confidence。

我們的模型訓練工作不需要用到 confidence。如果某個身體位置坐標點被命名了,我們就保留它,否則,我們就直接讓它為 0。

我們已經把(絶大部分)數據整理好了,現在我們需要把數據特徵和標籤結合起來。

我們用 0 代表其他姿勢,1 代表嘻哈超人舞步、2 代表 T-Pose 舞步。

接下來,我們可以使用獨熱編碼處理我們的數字標籤。也就是說,我們將標籤 0、1、2 轉換成 [1,0,0]、[0,1,0]、[0,0,1]。之後,我們可以使用 sklearn 的 shuffle 函數將數據標籤和特徵打亂(數據標籤和特徵仍保持原有的對應關係)

我們的輸入數據代表著鼻子、手等等的位置,而它們的是介於 0 到 720 和 0 到 1280 之間的像素值,所以我們需要把數據單一化,這樣一來,我們可以重複使用我們的模型而不用考慮輸入圖片數據的解析度。(完整版請看 GitHub

在最後一步中,我們將把我們的多維數據變成一維。我們會分批向模型輸入 50 個位置資訊(25 個部位,每個部位的 X 和 Y 值)。

建構並訓練動作辨識模型

在 Jupyter notebook 中使用 Keras,可以把訓練和測試神經網路模型的工作變得十分簡單,這也是我最喜歡 Keras 的地方。

現在我們的數據已經貼上標籤準備就緒了,我們可以開始訓練一個簡單的模型了,只需要幾行程式碼。

現在我們導入 Keras 庫,然後訓練一個簡單的神經網路模型。

搞定!

這裡有個稍微需要注意的地方,輸入層的大小為 50,提醒大家一下,這個數字是 OpenPose 模型中,位置點的 X 坐標和 Y 坐標數量之和。

最後我們用到了 Softmax 層,它是用來分類的。我們將 y.shape[1] 傳入該層,這樣我們的模型就知道不同類別的數量了。

最後的最後,我們使用輸入數據,用 model.fit() 的方法去訓練模型。這裡,我已經做了 2000 次疊代(全部樣本訓練一次為一次疊代)。2000 次疊代貌似有點多了,500 次左右的疊代可能更好,因為疊代次數過多可能使我們的模型出現一些過度擬合問題。但是不論是哪一種情況,你都需要經過多次嘗試來確定疊代次數。

當我們運行這段程式碼時,我們會看到準確度在提高。如果你看不到,請再次確認當你打亂數據時,數據標籤和數據特徵的對應關係是不變的。此外,也要確認數據裡的數值是不是在 0 到 1 之間。

最後,我們可以保存訓練後的模型,也可以使用樣本數據集來測試該模型,保存模型的程式碼很簡單(完整版請看 GitHub):

一切就緒,用模型來控制燈光吧!

我們現在已經有了可以識別姿勢的模型,接下來要做的只是把這個模型和無線燈光控制連結起來就行了。

在我的這個例子中,我使用 Aeotec Z-Stick 來發送 Z-Wave 指令,並配有兩個 GE Z-Wave 的室外開關。USB 插到 NVIDIA TX2 人工智能模組,其實 NVIDIA 的 Jestson Nano 也能勝任,儘管 Jetson Nano 所能提供的解析度要低於我範例中 1280×720 的解析度。當 Z-Stick 插到 ARM 設備後,你首先需要把開關調到 Z-Wave 模式,可能需要多按幾下 USB Stick 上的按鈕和燈的開關。

程式碼並不複雜,基本上就是訓練環境再加上一個額外的步驟。現在,我們導入 Keras,然後使用整理過的數據訓練模型。(完整版請看 GitHub

到了這一步,工作基本上就算完成了!

我們成功地訓練了一個用於識別嘻哈超人舞步、T-Pose 舞步的神經網路模型,然後我們可以讓它根據我們的舞步來製造可互動的燈。

太棒了,給自己按個讚!

建議:在 Jupyter notebook 上測試

所有程式碼、模型以及訓練數據都免費公佈在 Github 上。

我建議你們在 Jupyter notebook 上試試這個項目。我的程式碼中有個 bug,我一直無法從自己的工作簿中找出來。這個漏洞導致我的原始的 X 和 Y 標籤並沒有被正確地標記。如果你找到了解決這個 bug 的方法,記得在 Github 上建立一個 Pull Request(PR)。

另外,我們今天建構的基礎模型可以用來訓練很多類型的舞蹈動作。儘管我的模型每秒只能捕捉很少的畫面,但我們可以開始建立一個有關舞步的數據集,然後再建構一個能識別這些不同舞步的神經網路模型。

我還為剛開始學寫程式的人寫了本書,歡迎你們來看看這本書。

原文報導 傳送門

(本文經合作夥伴 大數據文摘 授權轉載,並同意 TechOrange 編寫導讀與修訂標題,原文標題為 〈程序员深夜用 Python 跑神经网络,只为用中二动作关掉台灯!〉。圖片來源: 大數據文摘

更多寫程式的技巧

工程師好用資源來了!超完整 Python 查詢表,程式碼複製貼上不用自己寫
【稱霸 GitHub 熱門榜】菜鳥也懂的 Python 教學,手把手打造「哄女友回話神器」
Netflix 幕後最大功臣是 Python!工程師: 每個數據工具都靠 Python 建構


我們正在找夥伴!

2019 年我們的團隊正在大舉擴張,需要你的加入跟我們一起找出台灣創新原動力! 我們正在徵 《採訪社群編輯》、《助理編輯》,詳細職缺與應徵辦法 請點我

點關鍵字看更多相關文章: