機器學習經典模型簡單使用及歸一化(標準化)影響
阿新 • • 發佈:2018-11-15
俗話說的好,不動手就永遠不知道該怎麼做,上次一聽說要做這個的時候人都懵了,聽了幾次似乎都摸不到門道,這次花了幾天時間去寫了寫,總算是摸到了點門道。
實驗
資料集
這次用到的資料集是跟火電廠有關的,都是匿名特徵,資料量為20160*170,做到最後發現只根據時間順序就能做的比較好。
歸一化
先來講講歸一化。歸一化也稱標準化,是資料探勘的一項基礎工作,使用歸一化的原因大體如下
- 資料存在不同的評價指標,其量綱或量綱單位不同,處於不同的數量級。解決特徵指標之間的可比性,經過歸一化處理後,各指標處於同一數量級,便於綜合對比。
- 求最優解的過程會變得平緩,更容易正確收斂。即能提高梯度下降求最優解時的速度。
- 提高計算精度。
MinMaxScaler
線性歸一化,也稱為離差標準化,是對原始資料的線性變換,min-max標準化方法的缺陷在當有新資料加入時,可能會導致X.max和X.min的值發生變化,需要重新計算。其轉換函式如下:
StandardScaler
標準差歸一化,也叫Z-score標準化,這種方法給予原始資料的均值(mean,μ)和標準差(standard deviation,σ)進行資料的標準化。經過處理後的資料符合標準正態分佈,即均值為0,標準差為1,轉化函式為:
MaxAbsScaler
原理與MinMaxScaler很像,只是資料會被規模化到[-1,1]之間。也就是特徵中,所有資料都會除以最大值。這個方法對那些已經中心化均值維0或者稀疏的資料有意義。
模型
本次實驗使用了5個模型,分別為Lasso、Redige、SVR、RandomForest、XGBoost。
實驗方式
- 以不同方式劃分資料集和測試集
- 使用不同的歸一化(標準化)方式
- 使用不同的模型
- 通過比較MSE(均方誤差,mean-square error)的大小來得出結論
部分程式碼及結果
資料預處理
#按時間排序 sort_data = data.sort_values(by = 'time',ascending = True) sort_data.reset_index(inplace = True,drop = True) target= data['T1AOMW_AV'] sort_target = sort_data['T1AOMW_AV'] del data['T1AOMW_AV'] del sort_data['T1AOMW_AV'] from sklearn.model_selection import train_test_split test_sort_data = sort_data[16160:] test_sort_target = sort_target[16160:] _sort_data = sort_data[:16160] _sort_target = sort_target[:16160] sort_data1 = _sort_data[:(int)(len(_sort_data)*0.75)] sort_data2 = _sort_data[(int)(len(_sort_data)*0.75):] sort_target1 = _sort_target[:(int)(len(_sort_target)*0.75)] sort_target2 = _sort_target[(int)(len(_sort_target)*0.75):] import scipy.stats as stats dict_corr = { 'spearman' : [], 'pearson' : [], 'kendall' : [], 'columns' : [] } for i in data.columns: corr_pear,pval = stats.pearsonr(sort_data[i],sort_target) corr_spear,pval = stats.spearmanr(sort_data[i],sort_target) corr_kendall,pval = stats.kendalltau(sort_data[i],sort_target) dict_corr['pearson'].append(abs(corr_pear)) dict_corr['spearman'].append(abs(corr_spear)) dict_corr['kendall'].append(abs(corr_kendall)) dict_corr['columns'].append(i) # 篩選新屬性 dict_corr =pd.DataFrame(dict_corr) new_fea = list(dict_corr[(dict_corr['pearson']>0.41) & (dict_corr['spearman']>0.45) & (dict_corr['kendall']>0.29)]['columns'].values) # 選取原則,選取25%分位數 以上的相關性係數
模型測試
from sklearn.linear_model import LinearRegression,Lasso,Ridge from sklearn.preprocessing import MinMaxScaler,StandardScaler,MaxAbsScaler from sklearn.metrics import mean_squared_error as mse from sklearn.svm import SVR from sklearn.ensemble import RandomForestRegressor import xgboost as xgb #最大最小歸一化 mm = MinMaxScaler() lr = Lasso(alpha=0.5) lr.fit(mm.fit_transform(sort_data1[new_fea]), sort_target1) lr_ans = lr.predict(mm.transform(sort_data2[new_fea])) print('lr:',mse(lr_ans,sort_target2)) ridge = Ridge(alpha=0.5) ridge.fit(mm.fit_transform(sort_data1[new_fea]),sort_target1) ridge_ans = ridge.predict(mm.transform(sort_data2[new_fea])) print('ridge:',mse(ridge_ans,sort_target2)) svr = SVR(kernel='rbf',C=100,epsilon=0.1).fit(mm.fit_transform(sort_data1[new_fea]),sort_target1) svr_ans = svr.predict(mm.transform(sort_data2[new_fea])) print('svr:',mse(svr_ans,sort_target2)) estimator_RF = RandomForestRegressor().fit(mm.fit_transform(sort_data1[new_fea]),sort_target1) predict_RF = estimator_RF.predict(mm.transform(sort_data2[new_fea])) print('RF:',mse(predict_RF,sort_target2)) bst = xgb.XGBRegressor(learning_rate=0.1, n_estimators=550, max_depth=4, min_child_weight=5, seed=0,subsample=0.7, colsample_bytree=0.7, gamma=0.1, reg_alpha=1, reg_lambda=1) bst.fit(mm.fit_transform(sort_data1[new_fea]),sort_target1) bst_ans = bst.predict(mm.transform(sort_data2[new_fea])) print('bst:',mse(bst_ans,sort_target2))
結果
lr: 7.736200563088036 ridge: 3.264150764935616 svr: 3.505799850945091 RF: 0.24087179220636037 bst: 0.9945862722591914
上面的這段程式碼測試的是最大最小歸一化情況下的結果,測試其他標準化時只需要改動mm = MinMaxScaler(),這段程式碼即可。
實驗結果及原因分析
經過多次測試,統計結果如下
通過對比,可以發現,
- 對於Lasso模型,使用MaxAbsScaler方式時,MSE增大十分明顯,且歸一化後結果高於不進行歸一化時(可能是資料的問題),
- 對於Redige模型,歸一化結果也明顯高於不歸一化時的結果。
- 對於SVR模型,不進行歸一化時,其MSE會非常大,是因為svm實質上選擇的是分割兩類資料最遠的超平面,由於錯分類造成了影響,不進行歸一化會造成對平面的影響,導致得到的劃分平面不準確測試整合功率低。
- 對於RandomForest和XGBoost來說,是否進行歸一化對結果影響不大。這也是樹模型的一大特徵。