- 原文地址:Can Machine Learning model simple Math functions?
- 原文作者:Harsh Sahu
- 譯文出自:掘金翻譯計劃
- 本文永久鏈接:github.com/xitu/gold-m…
- 譯者:Minghao23
- 校對者:lsvih,zoomdong
機器學習可以建模簡單的數學函數嗎?
使用機器學習建模一些基礎數學函數
近來,在各種任務上應用機器學習已經成為了一個慣例。似乎在每一個 Gartner's 技術循環曲線 上的新興技術都對機器學習有所涉及,這是一種趨勢。這些算法被當做 figure-out-it-yourself 的模型:將任何類型的數據都分解為一串特征,應用一些黑盒的機器學習模型,對每個模型求解并選擇結果最好的那個。
但是機器學習真的能解決所有的問題嗎?還是它只適用于一小部分的任務?在這篇文章中,我們試圖回答一個更基本的問題,即機器學習能否推導出那些在日常生活中經常出現的數學關系。在這里,我會嘗試使用一些流行的機器學習技術來擬合幾個基礎的函數,并觀察這些算法能否識別并建模這些基礎的數學關系。
我們將要嘗試的函數:
- 線性函數
- 指數函數
- 對數函數
- 冪函數
- 模函數
- 三角函數
將會用到的機器學習算法:
- XGBoost
- 線性回歸
- 支持向量回歸(SVR)
- 決策樹
- 隨機森林
- 多層感知機(前饋神經網絡)
數據準備
我會保持因變量(譯者注:原文錯誤,應該為自變量)的維度為 4(選擇這個特殊的數字并沒有什么原因)。所以,X(自變量)和 Y(因變量)的關系為:
f :- 我們將要擬合的函數
Epsilon:- 隨機噪聲(使 Y 更加真實一點,因為現實生活中的數據中總是存在一些噪聲)
每個函數類型都會用到一系列的參數。這些參數通過生成隨機數得到,方法如下:
numpy.random.normal()
numpy.random.randint()
復制代碼
randint() 用于獲取冪函數的參數,以免 Y 的值特別小。normal() 用于所有其他情況。
生成自變量(即 X):
function_type = 'Linear'if function_type=='Logarithmic':X_train = abs(np.random.normal(loc=5, size=(1000, 4)))X_test = abs(np.random.normal(loc=5, size=(500, 4)))
else:X_train = np.random.normal(size=(1000, 4))X_test = np.random.normal(size=(500, 4))
復制代碼
對于對數函數,使用均值為 5(均值遠大于方差)的正態分布來避免得到負值。
獲取因變量(即 Y):
def get_Y(X, function_type, paras):X1 = X[:,0]X2 = X[:,1]X3 = X[:,2]X4 = X[:,3]if function_type=='Linear':[a0, a1, a2, a3, a4] = parasnoise = np.random.normal(scale=(a1*X1).var(), size=X.shape[0])Y = a0+a1*X1+a2*X2+a3*X3+a4*X4+noiseelif function_type=='Exponential':[a0, a1, a2, a3, a4] = parasnoise = np.random.normal(scale=(a1*np.exp(X1)).var(), size=X.shape[0])Y = a0+a1*np.exp(X1)+a2*np.exp(X2)+a3*np.exp(X3)+a4*np.exp(X4)+noiseelif function_type=='Logarithmic':[a0, a1, a2, a3, a4] = parasnoise = np.random.normal(scale=(a1*np.log(X1)).var(), size=X.shape[0])Y = a0+a1*np.log(X1)+a2*np.log(X2)+a3*np.log(X3)+a4*np.log(X4)+noiseelif function_type=='Power':[a0, a1, a2, a3, a4] = parasnoise = np.random.normal(scale=np.power(X1,a1).var(), size=X.shape[0])Y = a0+np.power(X1,a1)+np.power(X2,a2)+np.power(X2,a2)+np.power(X3,a3)+np.power(X4,a4)+noiseelif function_type=='Modulus':[a0, a1, a2, a3, a4] = parasnoise = np.random.normal(scale=(a1*np.abs(X1)).var(), size=X.shape[0])Y = a0+a1*np.abs(X1)+a2*np.abs(X2)+a3*np.abs(X3)+a4*np.abs(X4)+noiseelif function_type=='Sine':[a0, a1, b1, a2, b2, a3, b3, a4, b4] = parasnoise = np.random.normal(scale=(a1*np.sin(X1)).var(), size=X.shape[0])Y = a0+a1*np.sin(X1)+b1*np.cos(X1)+a2*np.sin(X2)+b2*np.cos(X2)+a3*np.sin(X3)+b3*np.cos(X3)+a4*np.sin(X4)+b4*np.cos(X4)+noiseelse:print('Unknown function type')return Yif function_type=='Linear':paras = [0.35526578, -0.85543226, -0.67566499, -1.97178384, -1.07461643]Y_train = get_Y(X_train, function_type, paras)Y_test = get_Y(X_test, function_type, paras)
elif function_type=='Exponential':paras = [ 0.15644562, -0.13978794, -1.8136447 , 0.72604755, -0.65264939]Y_train = get_Y(X_train, function_type, paras)Y_test = get_Y(X_test, function_type, paras)
elif function_type=='Logarithmic':paras = [ 0.63278503, -0.7216328 , -0.02688884, 0.63856392, 0.5494543]Y_train = get_Y(X_train, function_type, paras)Y_test = get_Y(X_test, function_type, paras)
elif function_type=='Power':paras = [2, 2, 8, 9, 2]Y_train = get_Y(X_train, function_type, paras)Y_test = get_Y(X_test, function_type, paras)
elif function_type=='Modulus':paras = [ 0.15829356, 1.01611121, -0.3914764 , -0.21559318, -0.39467206]Y_train = get_Y(X_train, function_type, paras)Y_test = get_Y(X_test, function_type, paras)
elif function_type=='Sine':paras = [-2.44751615, 1.89845893, 1.78794848, -2.24497666, -1.34696884, 0.82485303, 0.95871345, -1.4847142 , 0.67080158]Y_train = get_Y(X_train, function_type, paras)Y_test = get_Y(X_test, function_type, paras)
復制代碼
噪聲是在 0 均值的正態分布中隨機抽樣得到的。我設置了噪聲的方差等于 f(X) 的方差,借此保證我們數據中的“信號和噪聲”具有可比性,且噪聲不會在信號中有損失,反之亦然。
訓練
注意:在任何模型中都沒有做超參數的調參。 我們的基本想法是只在這些模型對所提及的函數上的表現做一個粗略的估計,因此沒有對這些模型做太多的優化。
model_type = 'MLP'if model_type=='XGBoost':model = xgb.XGBRegressor()
elif model_type=='Linear Regression':model = LinearRegression()
elif model_type=='SVR':model = SVR()
elif model_type=='Decision Tree':model = DecisionTreeRegressor()
elif model_type=='Random Forest':model = RandomForestRegressor()
elif model_type=='MLP':model = MLPRegressor(hidden_layer_sizes=(10, 10))model.fit(X_train, Y_train)
復制代碼
結果
大多數的表現結果比平均基線要好很多。計算出的平均R方是 70.83%,我們可以說,機器學習技術對這些簡單的數學函數確實可以有效地建模。
但是通過這個實驗,我們不僅知道了機器學習能否建模這些函數,同時也了解了不同的機器學習技術在各種基礎函數上的表現是怎樣的。
有些結果是令人驚訝的(至少對我來說),有些則是合理的。總之,這些結果重新認定了我們的一些先前的想法,也給出了新的想法。
最后,我們可以得到下列結論:
- 盡管線性回歸是一個簡單的模型,但是在線性相關的數據上,它的表現是優于其他模型的
- 大多數情況下,決策樹 < 隨機森林 < XGBoost,這是根據實驗的表現得到的(在以上 6 個結果中有 5 個是顯而易見的)
- 不像最近實踐中的流行趨勢那樣,XGBoost(6 個結果中只有 2 個表現最好)不應該成為所有類型的列表數據的一站式解決方案,我們仍然需要對每個模型進行公平地比較。
- 和我們的猜測相反的是,線性函數不一定是最容易預測的函數。我們在對數函數上得到了最好的聚合R方結果,達到了 92.98%
- 各種技術在不同的基礎函數上的效果(相對地)差異十分大,因此,對一個任務選擇何種技術必須經過完善的思考和實驗
完整代碼見我的 github。
來點贊,評論和分享吧。建設性的批評和反饋總是受歡迎的!
如果發現譯文存在錯誤或其他需要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改并 PR,也可獲得相應獎勵積分。文章開頭的 本文永久鏈接 即為本文在 GitHub 上的 MarkDown 鏈接。
掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源為 掘金 上的英文分享文章。內容覆蓋 Android、iOS、前端、后端、區塊鏈、產品、設計、人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄。