您對人工智能 (AI) 和機器學習 (ML) 感到好奇嗎?您想知道如何在您已經使用過的微控制器上使用它嗎?在本文中,我們向您介紹了微控制器上的機器學習。該主題也稱為微型機器學習 (TinyML)。準備好在石頭、紙、剪刀上輸給 ESP-EYE。您將了解數據收集和處理、如何設計和訓練 AI 以及如何使其在 MCU 上運行。這個示例為您提供了從頭到尾完成您自己的 TinyML 項目所需的一切。
我為什么要關心 TinyML?
您肯定聽說過 DeepMind 和 OpenAI 等科技公司。他們憑借專家和 GPU 能力在 ML 領域占據主導地位。為了給人一種規模感,最好的人工智能,比如谷歌翻譯使用的人工智能,需要幾個月的訓練。他們并行使用數百個高性能 GPU。TinyML 通過變小來扭轉局面。由于內存限制,大型 AI 模型不適合微控制器。下圖顯示了硬件要求之間的差異。
與在云端使用 AI 服務相比,MCU 上的機器學習有哪些優勢?我們發現了七個主要優勢。
成本
微控制器的購買和運行都很便宜。
環保
在微控制器上運行 AI 消耗的能量很少。
一體化
微控制器很容易集成到現有環境中,例如生產線。
隱私和安全
數據可以在本地、在設備上處理。數據不必通過互聯網發送。
快速原型制作
TinyML 使您能夠在短時間內開發概念驗證解決方案。
自主可靠
即使沒有基礎設施,微型設備也可以在任何地方使用。
即時的
數據在微控制器上進行處理,沒有延遲。唯一的限制是 MCU 的處理速度。
剪刀石頭布
你有沒有在石頭、紙、剪刀上輸給人工智能?或者你想通過擊敗人工智能來給你的朋友留下深刻印象?您將使用 TinyML 與 ESP-EYE 板對戰。要使這樣的項目成為可能,您需要學習五個步驟。以下部分提供了必要步驟的高級概述。如果您想仔細查看,請參閱我們項目存儲庫中的文檔。它解釋了漂亮的細節。
收集資料
收集數據是機器學習的關鍵部分。為了讓事情運行起來,你需要拍攝你的手形成石頭、紙、剪刀手勢的圖像。圖片越獨特越好。AI 將了解到您的手可以處于不同的角度、位置或光線變化。數據集包含記錄的圖像和每個圖像的標簽。這被稱為監督學習。
最好使用與訓練 AI 相同的傳感器和環境來運行您的 AI。這將確保模型熟悉傳入的數據。例如,考慮由于制造差異,溫度傳感器在相同溫度下具有不同的電壓輸出。就我們而言,這意味著使用 ESP-EYE 相機在統一的背景上記錄圖像是理想的選擇。在部署期間,人工智能將在類似的背景下工作得最好。您還可以使用網絡攝像頭記錄圖像,但可能會犧牲一些準確性。由于 MCU 容量有限,我們記錄和處理 96×96 像素的灰度圖像。
收集數據后,將數據拆分為訓練集和測試集非常重要。我們這樣做是為了看看我們的模型如何識別它以前從未見過的手勢圖像。該模型自然會在訓練期間已經看到的圖像上表現良好。
以下是一些示例圖像。如果您現在不想收集數據,可以在這里下載我們現成的數據集。
預處理數據
識別數據中的模式不僅對人類來說很困難。為了讓 AI 模型更容易做到這一點,通常依賴于預處理算法。在我們的數據集中,我們使用 ESP-EYE 和網絡攝像頭記錄圖像。由于 ESP-EYE 可以捕獲 96×96 分辨率的灰度圖像,因此我們不需要在這里進行太多進一步的處理。但是,我們需要將網絡攝像頭圖像縮小并裁剪為 96×96 像素,并將它們從 RGB 轉換為灰度格式。最后,我們對所有圖像進行歸一化。下面,您將看到我們處理的中間步驟。
設計模型
設計一個模型是相當棘手的!詳細的處理超出了本文的范圍。我們將描述模型的基本組件以及我們如何設計我們的模型。在引擎蓋下,我們的 AI 依賴于神經網絡。您可以將神經網絡視為神經元的集合,有點像我們的大腦。這就是為什么在僵尸末日的情況下,人工智能也會被僵尸吃掉。
當網絡中的所有神經元相互連接時,這稱為全連接或密集。這可以被認為是最基本的神經網絡類型。由于我們希望我們的 AI 能夠從圖像中識別手勢,因此我們使用了一些更先進且更適合圖像的東西,即卷積神經網絡 (CNN)。卷積降低了圖像的維度,提取了重要的模式并保留了像素之間的局部關系。為了設計一個模型,我們使用了TensorFlow 庫,它提供了現成的神經網絡組件,稱為層,這使得創建神經網絡變得容易!
創建模型意味著堆疊層。它們的正確組合對于開發穩健且高精度的模型至關重要。下圖顯示了我們正在使用的不同層。Conv2D表示卷積層。批標準化layer 對上一層的輸出應用一種歸一化形式。然后我們將數據輸入激活層,這會引入非線性并過濾掉不重要的數據點。接下來,最大池化類似于卷積減小圖像的大小。這個層塊重復了幾次;合適的量是由經驗和實驗決定的。之后,我們使用扁平化層將二維圖像縮減為一維數組。最后,該陣列緊密連接到三個神經元,它們分別代表石頭、紙和剪刀等類別。
def make_model_simple_cnn (INPUT_IMG_SHAPE, num_classes= 3 ): 輸入= keras.Input(形狀=INPUT_IMG_SHAPE) x = 輸入 x = layers.Rescaling( 1.0 / 255 )(x) x = layers.Conv2D( 16 , 3 , strides= 3 , padding= "same" )(x) x = layers.BatchNormalization()(x) x = layers.Activation( “relu” )(x) x = 層數.MaxPooling2D()(x) x = layers.Conv2D( 32 , 3 , strides= 2 , padding= "same" , activation= "relu" )(x) x = 層數.MaxPooling2D()(x) x = layers.Conv2D( 64 , 3 , padding= "same" , activation= "relu" )(x) x = 層數.MaxPooling2D()(x) x = 層.Flatten()(x) x = 層數.Dropout( 0.5 )(x) output = layers.Dense(units=num_classes, activation= "softmax" )(x) return keras.Model(inputs, outputs)
訓練模型
一旦我們設計了一個模型,我們就可以訓練它了。最初,人工智能模型會做出隨機預測。預測是與標簽相關的概率,在我們的例子中是石頭、紙或剪刀。我們的 AI 告訴我們它將圖像視為每個標簽的可能性有多大。因為人工智能在一開始就在猜測標簽,所以它經常會弄錯標簽。將預測標簽與真實標簽進行比較后進行訓練。預測錯誤會導致網絡中神經元之間的更新。這種學習形式稱為梯度下降。因為我們在 TensorFlow 中構建了模型,所以訓練就像一、二、三一樣簡單。下面,您會看到訓練期間產生的輸出——準確度(訓練集)和驗證準確度(測試集)越高越好!
時期1 / 6 480 / 480 [===============================] - 17秒34毫秒/步 - 損失:0.4738 - 準確度:0.6579 - val_loss:0.3744 - val_accuracy:0.8718 Epoch 2 / 6 216 / 480 [============>....... ] - ETA:7秒 - 損失:0.2753 - 準確度:0.8436
在訓練期間,可能會出現多個問題。最常見的問題是過擬合。當模型一遍又一遍地暴露在相同的例子中時,它會開始記住訓練數據,而不是學習底層模式。當然,您從學校記得理解比記憶更好!在某些時候,訓練數據的準確率可能會繼續上升,而測試集的準確率則不會。這是過度擬合的明確指標。
轉換模型
經過訓練,我們得到一個 TensorFlow 格式的 AI 模型。由于 ESP-EYE 無法解釋這種格式,我們將模型更改為微處理器可讀格式。我們從轉換為 TfLite 模型開始。TfLite 是一種更緊湊的 TensorFlow 格式,它使用量化導致模型尺寸減小。TfLite 常用于世界各地的邊緣設備,例如智能手機或平板電腦。最后一步是將 TfLite 模型轉換為 C 數組,因為微控制器無法直接解釋 TfLite。
部署模型
現在我們可以將模型部署到微處理器上。我們唯一需要做的就是將新的 C 數組放入預期的文件中。替換 C 數組的內容,不要忘記替換文件末尾的數組長度變量。我們提供了一個腳本來簡化此操作。就是這樣!
嵌入式環境
讓我們回顧一下 MCU 上發生的事情。在設置過程中,解釋器被配置為我們圖像的形狀。
//初始化解釋器 靜態tflite::MicroInterpreter static_interpreter ( 模型、解析器、tensor_arena、kTensorArenaSize、error_reporter); 解釋器 = &static_interpreter; 模型輸入=解釋器->輸入(0); 模型輸出=解釋器->輸出(0); // 斷言真實輸入與期望輸入匹配 if ((model_input->dims->size != 4) || // 形狀 (1, 96, 96, 1) 的張量具有昏暗 4 (model_input->dims->data[ 0] != 1) || // 每批 1 個 img (model_input->dims->data[1] != 96) || // 96 x 像素 (model_input->dims->data[2] != 96 ) || // 96 y 像素 (model_input->dims->data[3] != 1) || // 1 通道(灰度) (model_input->type != kTfLiteFloat32)) { // 單個數據的類型點,這里是一個像素 error_reporter->Report( "Bad input tensor parameters in model\n" ); 返回; }
設置完成后,捕獲的圖像被發送到模型,在模型中進行手勢預測。
// 從攝像頭讀取圖像到一維數組 uint8_t img[dim1*dim2*dim3] if (kTfLiteOk != GetImage(error_reporter, dim1, dim2, dim3, img)) { TF_LITE_REPORT_ERROR(error_reporter, "圖像捕獲失敗。" ); } // 將圖像寫入模型 std :: vector < uint8_t > img_vec(img, img + dim1*dim2*dim3); std ::向量< float_t > img_float(img_vec.begin(), img_vec.end()); 標準::copy(img_float.begin(), img_float.end(), model_input->data.f); // 應用推理 TfLiteStatus invoke_status = 解釋器->Invoke(); }
然后模型返回每個手勢的概率。由于概率數組只是一系列介于 0 和 1 之間的值,因此需要進行一些解釋。我們認為識別出的手勢是概率最高的手勢?,F在我們通過將識別的手勢與 AI 的動作進行比較來處理解釋,并確定誰贏得了回合。你沒有機會了!
// 每個類的概率 浮動紙=模型輸出->數據.f[0]; 浮動巖石 = model_output->data.f[1]; 浮動剪刀 = model_output->data.f[2];
下面的可愛圖表說明了 MCU 上的步驟。出于我們的目的,不需要對微控制器進行預處理。
點擊查看完整大小的圖片
展開示例
來個挑戰怎么樣?人生的新目標?想要給老朋友留下深刻印象或尋找新朋友?通過添加蜥蜴和史波克,將石頭、紙、剪刀提升到一個新的水平。你的 AI 朋友將是一項更接近世界統治的技能。好吧,首先你應該看看我們的石頭、紙、剪刀存儲庫,并能夠復制上述步驟。自述文件將幫助您了解詳細信息。下圖向您展示了游戲的運作方式。您需要添加兩個額外的手勢和一些新的輸贏條件。
點擊查看完整大小的圖片
開始你自己的項目
如果您喜歡這篇文章并想開始自己的項目,我們會為您提供一個模板項目,它使用與我們的石頭、紙、剪刀項目相同的簡單管道。您可以在此處找到模板。不要猶豫,通過社交媒體向我們展示您的項目。我們很想看看你能創造什么!
您可以在這里和那里找到有關 TinyML 的更多信息。Pete Warden 的書是一個很好的資源。
審核編輯 黃昊宇
-
mcu
+關注
關注
146文章
17123瀏覽量
350983 -
AI
+關注
關注
87文章
30728瀏覽量
268886
發布評論請先 登錄
相關推薦
評論