『我的App開發之路』自動商品分類器(下) -佈署與整合
接續深度學習與爬蟲這篇,在順利取得數據並訓練好模型之後,接下來便是要把這這個商品自動分類器導入到 App 裡了,雖然可以透過 PyTorch Mobile 讓模型可以執行在 Android Device 上,但過於巨大的參數資料加上沒有那麼即時的需求,評估之後認為佈署到 backend server 上透過 REST API 來存取是比較好的方式,接下來會介紹佈署的方法以及整合上遇到的問題與解法。
佈署服務
nodejs 其實是蠻適合用來架設這樣的微服務,初步是打算利用 child_process 的方式來呼叫 python 執行分類器,再把使用者傳過來的商品名稱當作參數傳入,但這樣的缺點是每次都要重新載入模型很耗費時間,另外也要針對 stdout 進行字串處理,不是很有效率,最後還是改用 python 的 http server Flask,以下是一個 server 的簡單架構。
Flask 使用上很直覺,透過 decorator 宣告好路徑然後,接著寫 API 的邏輯,回傳結果也可以直接使用 dictonary ,非常方便。
知道 Flask 的用法後,開始來定義 API 介面的參數與回傳結果。首先定義 end point 為 /product_class 使用 POST 方法,將要分類的產品名稱放在一個叫 prodcuts 的 JSON array,array 中的每個 JSON object 都必須要有一個 name 的參數,這個參數就是產品的名稱。
Server 收到 request 後,將每個名稱送到 Model 中取得分類代碼陣列(class array )以及分數陣列(score array),把此一結果添加到一開始傳遞過來的 JSON 結構中,送回到呼叫端。之所以會把送過來的資料原封不動送回去的原因是,因為 app 端 API 呼叫通常是非同步的,我們可以在每筆資料裡放內部 id 或是其他資料,讓 app 在收到資料後就可以直接參考,執行相對應的動作,這樣程式設計上會比較簡便。
API 實做,classify()函數封裝了訓練完成的 model,輸入產品名稱後輸出class, score 兩個陣列。完整的程式可以參考這裡。
程式設計完成,佈署到網路上就可以開始服務了。
App整合
完成上述的服務佈署,現在離完成整個設計只差最後一步了,就是讓 App 透過 server 取得商品的分類後,能夠順利轉換成記帳的分類。
問題
App 透過 HTTP API 呼叫 server 取得商品分類這部份蠻容易的,不過取得分類碼後,如何對應到使用者定義的分類這就有點麻煩了,因為 App 允許使用者可以自行定義記帳時分類,可想而知,有人只想知道食衣住行幾個消費類型,也會有人光外食就分成早餐,中餐,晚餐及宵夜,要如何把自動分類器中定義的分類,適當的對應到使用者使用的所有分類去呢?
解決方法
方案一:手動建立商品分類與記帳分類的映射關係。
雖然這樣很直覺但是不可行,使用者定義的分類會有上百種,還會隨著時間增加,加上映射可能是一對多或是多對一,就算勉強花了很多時間手動建立,準確率也不會太高。
方案二:根據使用者以往的手動選擇紀錄,建立評分機制,統計使用者自訂的消費類型在每個商品分類。
App 會在紀錄電子發票消費支出時,同時紀錄商品被設定成何種類型的消費,可以利用查詢這些已經有消費類型的商品,取得分類器的分類以及評分並加總,這樣就可以得到使用者自訂消費類型的一個分類清單以及評分。
建立評分資料後,當有新的商品出現的時候,先查詢這個商品最相關的分類,然後根據資料庫中比對出分數最高的消費類型,這樣就可以自動選擇最相關的消費類型了。
這個解決方案不受限於消費類型的命名與定義,能夠根據使用者的歷史選擇紀錄,來推測可能適合的分類。不過這樣會有個缺點,就是在沒有初始資料的時是沒有辦法發揮作用的。
資料結構
在原本的設計中,已經有兩個表格來儲存消費類型(Category)以及產品(Product),現在只需要再新增一個紀錄產品的分類與分數的表格(Product_Class)。
然後只要透過 Sql 的查詢,就可以很容易得到消費類型的相關分類及其加總分數,接下來就只是單純的比對計算工作,找出累計分數最高的消費類型。
select (select category_id from Product where Product.id = product_id) category_id ,class_id, sum(score) scores from Product_Class by category_id, class_id order by category_id asc, scores desc
結語
這個自動商品分類功能算是一個很有趣的挑戰,在沒有深度學習的基礎下,能從無到有設計出初步可行的架構,證明現在 AI 的發展越來越成熟了,即使不懂背後的複雜數學理論,也能輕鬆的得到還可以的成果,當然,目前這個功能離完美還很遙遠,還需要不少的調整,也許到時候會有一些新的心得可以再拿出來分享。