尋夢新聞LINE@每日推播熱門推薦文章,趣聞不漏接❤️
機器之心編輯
參與:思源
你是否常訓練炫酷的機器學習模型,用來分析數據或執行某些新奇的任務?你是否發現你的模型只能在一定開發環境上才能跑起來,很難部署也很難加入其它程序?今天我們將介紹一個炫酷的工具,它可以把構建在 scikit-learn 或 XGBoost 等庫上的 ML 模型直接轉化為不需要任何依賴項的 Java/Python/C 源代碼。
-
項目地址:https://github.com/BayesWitnesses/m2cgen/
那麼轉化為 Java/Python/C 源代碼有什麼用呢?想像一下如果我們使用 ML 框架(scikit-learn\XGBoost\LightGBM)訓練了一個模型,現在我們希望把這個模型做成應用或嵌入到已有的模型中,那麼我們肯定需要考慮這些問題:
-
如果產品環境並沒有 Python 運行時怎麼辦?
-
如果產品不能通過雲服務器進行計算,只能在本地進行怎麼辦?
-
ML 模型的推斷速度太慢又怎麼辦?
這些問題都很難解決,也是開發者在做自己項目時常遇到的問題。如果我們能將用 Python 和 ML 庫構建的模型轉換一下,變成純 Java 或 C 寫的代碼,且這些代碼不會依賴各種庫,那麼部署或嵌入不就簡單了麼。在 m2cgen 這個項目中,它就可以將 ML 模型轉化為不帶有依賴項的純代碼。
m2cgen(Model 2 Code Generator)是一個輕量級的 Python 庫,它能快速便捷地將已訓練統計模型轉化為 Python、C 和 Java 代碼。目前 m2cgen 已經支持各種分類模型與回歸模型,包括支持向量機、決策樹、隨機森林和梯度提升樹等,注意這些都是統計機器學習模型,深度神經網路還是老老實實使用 DL 框架吧。
模型轉換效果
我們可以通過幾個簡單案例了解 m2cgen 是如何轉換為純代碼的,簡單而言即把模型架構和權重顯化了。如下所示如果我們簡單地訓練一個線性回歸模型,當然代碼看著簡單是因為我們直接調用了 scikit-learn 庫中的模型。
fromsklearn.datasetsimportload_bostonfromsklearnimportlinear_modelimportm2cgenasm2cboston=load_boston()X,y=boston.data,boston.targetestimator=linear_model.LinearRegression()estimator.fit(X,y)code=m2c.export_to_java(estimator)
上面最後一行將 scikit-learn 中的線性回歸模型轉化為 Java 代碼,注意這個模型已經擬合了訓練數據,或者說已經完成了訓練。轉化後的代碼如下所示:
publicclassModel{publicstaticdoublescore(double[]input){return(((((((((((((36.45948838508965)+((input[0])*(-0.10801135783679647)))+((input[1])*(0.04642045836688297)))+((input[2])*(0.020558626367073608)))+((input[3])*(2.6867338193449406)))+((input[4])*(-17.76661122830004)))+((input[5])*(3.8098652068092163)))+((input[6])*(0.0006922246403454562)))+((input[7])*(-1.475566845600257)))+((input[8])*(0.30604947898516943)))+((input[9])*(-0.012334593916574394)))+((input[10])*(-0.9527472317072884)))+((input[11])*(0.009311683273794044)))+((input[12])*(-0.5247583778554867));}}
如上 return 後面的語句,它就是一個線性回歸的表達式,每一個 input[ * ] 都是一種特徵,它後面的數值就是訓練後的權重。所以整個線性模型有 13 個特徵及對應權重,以及另外一個偏置項。
我們還可以找到更多的案例,如果我們用 XGBoost 訓練一個簡單的分類模型,我們可以看到轉化的代碼會大量使用 if-else 大法,不過我們本身也不用維護生成的代碼,所以這種結構也沒什麼關係了。
importnumpyasnpdefscore(input):if(input[2])>=(2.5999999):var0=-0.0731707439else:var0=0.142857149if(input[2])>=(2.5999999):var1=-0.0705206916else:var1=0.12477719var2=np.exp(((0.5)+(var0))+(var1))if(input[2])>=(2.5999999):if(input[2])>=(4.85000038):var3=-0.0578680299else:var3=0.132596686else:var3=-0.0714285821if(input[2])>=(2.5999999):if(input[2])>=(4.85000038):var4=-0.0552999191else:var4=0.116139404else:var4=-0.0687687024var5=np.exp(((0.5)+(var3))+(var4))if(input[2])>=(4.85000038):if(input[3])>=(1.75):var6=0.142011836else:var6=0.0405405387else:if(input[3])>=(1.6500001):var6=0.0428571403else:var6=-0.0730659068if(input[2])>=(4.85000038):if(input[3])>=(1.75):var7=0.124653712else:var7=0.035562478else:if(input[3])>=(1.6500001):var7=0.0425687581else:var7=-0.0704230517var8=np.exp(((0.5)+(var6))+(var7))var9=((var2)+(var5))+(var8)returnnp.asarray([(var2)/(var9),(var5)/(var9),(var8)/(var9)])
不過上面這種代碼也非常合理,本身決策樹就可以視為一種 if-else 的規則集合,不同輸入特徵 input[ * ] 滿足不同的條件就能得到不同的值,這些值最後能聯合計算分類結果。
項目細節
工具的安裝很簡單,直接用 pip 就行了:
pipinstallm2cgen
除了前面那樣在代碼中調用轉換工具,我們還能通過命令行使用序列化的模型目標(pickle protocol)生成代碼:
$m2cgen<pickle_file>--language<language>[--indent<indent>][--class_name<class_name>][--package_name<package_name>][--recursion-limit<recursion_limit>]
目前項目支持以下分類和回歸模型的轉換:
分類模型輸出結果:
本文為機器之心編輯,轉載請聯繫本公眾號獲得授權。
✄————————————————
加入機器之心(全職記者 / 實習生):[email protected]
投稿或尋求報導:content@jiqizhixin.com
廣告 & 商務合作:[email protected]