sklearn之线性回归实现—阿里云天池二手车交易价格预测赛
最近整理了線性回歸的原理及代碼實現(xiàn),想要用實際數(shù)據(jù)來測試模型,正好看到阿里云天池數(shù)據(jù)賽正在進(jìn)行二手車交易價格預(yù)測算法賽,正好能用線性回歸模型進(jìn)行預(yù)測,就在這里分享一下代碼。
一、賽題介紹
賽題以預(yù)測二手車的交易價格為任務(wù),該數(shù)據(jù)來自某交易平臺的二手車交易記錄,總數(shù)據(jù)量超過40w,包含31列變量信息,其中15列為匿名變量。其中抽取15萬條作為訓(xùn)練集,5萬條作為測試集A,5萬條作為測試集B。
特征如下:
二、數(shù)據(jù)預(yù)處理
數(shù)據(jù)預(yù)處理是跑模型之前最重要的一步,做好預(yù)處理,模型也就成功了一半。
import pandas as pd import numpy as np data=pd.read_csv('./train.csv',encoding='big5') #讀取訓(xùn)練集 data=data.iloc[:,2:] #只取有用字段為了方便讀取數(shù)據(jù),我將原始數(shù)據(jù)中price(價格)字段移到最后一列。
x_data=data.iloc[:,:28] #取特征字段 y_data=data.iloc[:,28] #取目標(biāo)值price字段 x=np.array(x_data.values.tolist()) #將數(shù)據(jù)展開成二維數(shù)據(jù) y=np.array(y_data.values.tolist()) #將數(shù)據(jù)展開成二維數(shù)據(jù)在進(jìn)行預(yù)處理之前,先做特征分析,看看各個特征的分布。
查看數(shù)據(jù)的特征字段名稱:
查看該特征數(shù)據(jù)分布:
作特征數(shù)據(jù)分布圖:
與Y值做散點圖:
對所有特征數(shù)據(jù)做歸一化,保持特征量綱統(tǒng)一。
將訓(xùn)練集按8:2比例分為組內(nèi)訓(xùn)練集與測試集,測試模型訓(xùn)練效果。
import math x_train_set = x[: math.floor(len(x) * 0.9), :] y_train_set = y[: math.floor(len(y) * 0.9)] x_validation = x[math.floor(len(x) * 0.9): , :] y_validation = y[math.floor(len(y) * 0.9):]三、線性回歸模型代碼實現(xiàn)
我嘗試直接利用手寫線性回歸算法代碼實現(xiàn)模型訓(xùn)練。
dim = 28+1 #之所以+1是留出誤差項b的位置 w = np.ones([dim, 1]) #w就是待學(xué)習(xí)參數(shù) x_1 = np.concatenate((np.ones([len(x_train_set), 1]), x_train_set), axis = 1).astype(float) learning_rate = 100 #初始化學(xué)習(xí)率設(shè)置為100 iter_time = 1000 #訓(xùn)練次數(shù)為1000次 adagrad = np.zeros([dim, 1]) #adagrad自適應(yīng)學(xué)習(xí)率方法 eps = 0.0000000001 #adagrad中防止分母為0的極小值 for t in range(iter_time):loss = np.sqrt(np.sum(np.power(np.dot(x_1, w) - y,2)) / len(x_train_set)) #損失函數(shù)if(t%100==0): #每隔100次輸出一次誤差值print(str(t) + ":" + str(loss))gradient = 2 * np.dot(x_1.transpose(), np.dot(x_1, w) - y) ##計算的梯度adagrad=adagrad+gradient ** 2 w = w - learning_rate * gradient / np.sqrt(adagrad + eps) #更新w的值結(jié)果遇到報錯"MemoryError: Unable to allocate 151. GiB for an array with shape (135000, 150000) and data type float64" ,意思就是待訓(xùn)練矩陣過大導(dǎo)致內(nèi)存不足無法計算。
在嘗試盡量縮小訓(xùn)練數(shù)據(jù)量后,發(fā)現(xiàn)計算機最多只能計算數(shù)千條數(shù)據(jù),我轉(zhuǎn)而求助sklearn包來實現(xiàn)線性回歸。
四、sklearn代碼實現(xiàn)
sklearn是目前python中十分流行的用來實現(xiàn)機器學(xué)習(xí)的第三方包,其中包含了多種常見算法如:決策樹,邏輯回歸、集成算法(如隨機森林)等等。
用sklearn實現(xiàn)多元線性回歸:
參數(shù) fit_intercept,選擇是否需要計算截距,默認(rèn)為True;
參數(shù) normalize,選擇是否需要標(biāo)準(zhǔn)化(中心化),默認(rèn)為false;
預(yù)測組內(nèi)測試集,查看均方誤差大小。
作圖查看預(yù)測效果,數(shù)據(jù)集數(shù)據(jù)量太大,只取前100個預(yù)測結(jié)果查看擬合效果:
y_pred_p=y_pred[:100] #取預(yù)測結(jié)果 y_train_set_p=y_validation[:100] #取組內(nèi)測試集結(jié)果 plt.figure(dpi=100) plt.plot(range(len(y_pred_p)),y_pred_p,'b',label="predict") plt.plot(range(len(y_train_set_p)),y_train_set_p,'r',label="test")可以看到預(yù)測結(jié)果大體上還是和測試集相符的:
五、比賽得分
將訓(xùn)練的模型用于待預(yù)測數(shù)據(jù)集,輸出結(jié)果提交到比賽中。
testdata = pd.read_csv('./test.csv', encoding='big5') test_data = testdata.iloc[:, 2:] test_x = np.array(test_data.values.tolist()) # 將其轉(zhuǎn)換為數(shù)組 # 下面是Normalize,且必須跟training data是同一種方法進(jìn)行Normalize for i in range(len(test_x)): #12 * 471for j in range(len(test_x[0])): #18 * 9 if std_x[j] != 0:test_x[i][j] = (test_x[i][j] - mean_x[j]) / std_x[j]預(yù)測結(jié)果:
y_pred_test=reg.predict(test_x)將結(jié)果輸出到csv文件中:
import csv with open('./result.csv', mode='w', newline='') as submit_file:csv_writer = csv.writer(submit_file)header = ['SaleID', 'price']print(header)csv_writer.writerow(header)for i in range(50000):if y_pred_test[i]<0 :y_pred_test[i]=0 #如果預(yù)測結(jié)果小于0,就為0,因為價格不可能小于0row = [str(i+150000), y_pred_test[i]]csv_writer.writerow(row)print(row)以下為提交結(jié)果后獲得的誤差分?jǐn)?shù)與排名,可以看到和其他人提交的結(jié)果還是有很大差距的。
六、模型優(yōu)化
面對不佳的預(yù)測效果,我回頭檢查數(shù)據(jù)發(fā)現(xiàn)了一些數(shù)據(jù)缺失和數(shù)據(jù)移位的問題,進(jìn)行數(shù)據(jù)補齊后重新訓(xùn)練模型,但預(yù)測分?jǐn)?shù)沒有得到顯著提升。
于是我思考基于sklearn優(yōu)化現(xiàn)有線性回歸模型。
(1) 嶺回歸
嶺回歸在損失函數(shù)中增加了正則項,也叫L2范數(shù),以限制模型參數(shù)對異常樣本的匹配程度,進(jìn)而提高模型面對多數(shù)正常樣本的擬合精度。
from sklearn.linear_model import Ridge,RidgeCV Lambdas=np.logspace(-0.5,1,5) #構(gòu)造不同的lambda值#設(shè)置交叉驗證的參數(shù),使用均方誤差評估 ridge_cv=RidgeCV(alphas=Lambdas,normalize=True,scoring='neg_mean_squared_error',cv=10) ridge_cv.fit(x_train_set,y_train_set)#基于最佳lambda值建模 ridge=Ridge(alpha=ridge_cv.alpha_,normalize=True) ridge.fit(x_train_set,y_train_set)#輸出預(yù)測結(jié)果 ridge_pred=ridge.predict(x_validation)#評估模型效果 MSE=metrics.mean_squared_error(y_validation,ridge_pred) print(MSE)提交比賽結(jié)果后,模型預(yù)測表現(xiàn)沒有得到顯著提升。
(2)LASSO回歸
嶺回歸無法剔除變量,而LASSO回歸模型,將懲罰項由L2范數(shù)變?yōu)長1范數(shù),可以將一些不重要的回歸系數(shù)縮減為0,達(dá)到剔除變量的目的。
from sklearn.linear_model import Lasso,LassoCV Lambdas=np.logspace(-0.5,1,2)#設(shè)置交叉驗證的參數(shù),使用均方誤差評估 lasso_cv=LassoCV(alphas=Lambdas,normalize=True,cv=10,max_iter=10000) lasso_cv.fit(x_train_set,y_train_set)#基于最佳lambda值建模 lasso=Lasso(alpha=lasso_cv.alpha_,normalize=True,max_iter=10000) lasso.fit(x_train_set,y_train_set)#輸出預(yù)測結(jié)果 lasso_pred=lasso.predict(x_validation)#評估模型效果 MSE=metrics.mean_squared_error(y_validation,lasso_pred) print(MSE)提交比賽結(jié)果后,模型預(yù)測表現(xiàn)沒有得到顯著提升。
至此,線性回歸模型在二手車交易價格預(yù)測賽中的代碼如上。
小記:
1、線性回歸在sklearn上實現(xiàn)即方便又快速。
2、我看到二手車交易價格預(yù)測賽論壇中,排名靠前的模型都是神經(jīng)網(wǎng)絡(luò)實現(xiàn)的,下一步我將用神經(jīng)網(wǎng)絡(luò)框架實現(xiàn)價格預(yù)測模型,對比現(xiàn)有模型效果。
總結(jié)
以上是生活随笔為你收集整理的sklearn之线性回归实现—阿里云天池二手车交易价格预测赛的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2013/06 事情发生之后都会显得云淡
- 下一篇: 算法——最短路径应用