從 0 到 1 走進(jìn) Kaggle

本文結(jié)構(gòu):

  • kaggle 是什么
  • 如何參賽
  • 解決問題一般步驟
  • 進(jìn)一步:
    • 如何探索數(shù)據(jù)
    • 如何構(gòu)造特征
  • 提交結(jié)果

kaggle 是什么?

Kaggle 是一個(gè)數(shù)據(jù)科學(xué)競(jìng)賽的平臺(tái),很多公司會(huì)發(fā)布一些接近真實(shí)業(yè)務(wù)的問題,吸引愛好數(shù)據(jù)科學(xué)的人來一起解決。
https://www.kaggle.com/

點(diǎn)擊導(dǎo)航欄的 competitions 可以看到有很多比賽,其中正式比賽,一般會(huì)有獎(jiǎng)金或者工作機(jī)會(huì),除了正式比賽還有一些為初學(xué)者提供的 playground,在這里可以先了解這個(gè)比賽,練習(xí)能力,再去參加正式比賽。
https://www.kaggle.com/competitions


如何參賽?

以 playground 中的這個(gè) House Prices 預(yù)測(cè)為例,
https://www.kaggle.com/c/house-prices-advanced-regression-techniques

Overview: 首先在 overview 中仔細(xì)閱讀問題的描述,這個(gè)比賽是讓我們預(yù)測(cè)房?jī)r(jià),它會(huì)給我們 79 個(gè)影響房?jī)r(jià)的變量,我們可以通過應(yīng)用 random forest,gradient boosting 等算法,來對(duì)房?jī)r(jià)進(jìn)行預(yù)測(cè)。

Data:在這里給我們提供了 train 數(shù)據(jù)集,用來訓(xùn)練模型;test 數(shù)據(jù)集,用來將訓(xùn)練好的模型應(yīng)用到這上面,進(jìn)行預(yù)測(cè),這個(gè)結(jié)果也是要提交到系統(tǒng)進(jìn)行評(píng)價(jià)的;sample_submission 就是我們最后提交的 csv 文件中,里面的列的格式需要和這里一樣。

Kernels:可以看到一些參賽者分享的代碼。

Discussion:參賽者們可以在這里提問,分享經(jīng)驗(yàn)。

Leaderboard:就是參賽者的排行榜。

參加 kaggle 最簡(jiǎn)單的流程就是:

第一步:在 Data 里面下載三個(gè)數(shù)據(jù)集,最基本的就是上面提到的三個(gè)文件,有些比賽會(huì)有附加的數(shù)據(jù)描述文件等。
第二步:自己在線下分析,建模,調(diào)參,把用 test 數(shù)據(jù)集預(yù)測(cè)好的結(jié)果,按照 sample_submission 的格式輸出到 csv 文件中。
第三步:點(diǎn)擊藍(lán)色按鈕 ’Submit Predictions’ ,把 csv 文件拖拽進(jìn)去,然后系統(tǒng)就會(huì)加載并檢驗(yàn)結(jié)果,稍等片刻后就會(huì)在 Leaderboard 上顯示當(dāng)前結(jié)果所在的排名位置。

上傳過一次結(jié)果之后,就直接加入了這場(chǎng)比賽。正式比賽中每個(gè)團(tuán)隊(duì)每天有 5 次的上傳機(jī)會(huì),然后就要等 24 小時(shí)再次傳結(jié)果,playground 的是 9 次。


解決問題一般步驟?

應(yīng)用算法解決 Kaggle 問題,一般會(huì)有以下幾個(gè)步驟:

  1. 識(shí)別問題
  2. 探索數(shù)據(jù)
  3. 數(shù)據(jù)預(yù)處理
  4. 將 train.csv 分成 train 和 valid 數(shù)據(jù)
  5. 構(gòu)造新的重要特征數(shù)據(jù)
  6. 應(yīng)用算法模型
  7. 優(yōu)化模型
  8. 選擇提取重要特征
  9. 再次選擇模型,進(jìn)行訓(xùn)練
  10. 調(diào)參
  11. 重復(fù)上述過程,進(jìn)一步調(diào)優(yōu)
  12. 預(yù)測(cè)

當(dāng)然上面是相對(duì)細(xì)的分步,如果簡(jiǎn)化的話,是這么幾大步:

  1. 探索數(shù)據(jù)
  2. 特征工程
  3. 建立模型
  4. 調(diào)參
  5. 預(yù)測(cè)提交

之前寫過一篇文章,《一個(gè)框架解決幾乎所有機(jī)器學(xué)習(xí)問題》
http://blog.csdn.net/aliceyangxi1987/article/details/71079448
里面的重點(diǎn)是介紹了常用算法模型一般需要調(diào)節(jié)什么參數(shù),即第四步。

還有這篇,《通過一個(gè)kaggle實(shí)例學(xué)習(xí)解決機(jī)器學(xué)習(xí)問題》
http://blog.csdn.net/aliceyangxi1987/article/details/71079473
主要介紹了第三步建立模型的部分,包括 ensemble 的例子。

今天這篇文章算是一個(gè)補(bǔ)充,在觀察數(shù)據(jù)和特征構(gòu)造上學(xué)習(xí)幾種常用的方式。


如何探索數(shù)據(jù)?

以 House prices 為例,探索數(shù)據(jù)常用方法有以下 6 步。
https://www.kaggle.com/c/house-prices-advanced-regression-techniques

1. 首先,在 data_description.txt 這里有對(duì) 79 個(gè)變量含義非常詳細(xì)的描述

我們可以先通過閱讀變量含義,根據(jù)常識(shí)猜測(cè)一下,哪些變量會(huì)對(duì)預(yù)測(cè)結(jié)果有比較重要的影響。

例如:
OverallQual: Overall material and finish quality 物料和質(zhì)量應(yīng)該是很重要的組成。
GrLivArea: Above grade (ground) living area square feet 面積也是明顯的因素。
YearBuilt: Original construction date 時(shí)間也有影響。

2. 接著,對(duì)要預(yù)測(cè)的目標(biāo)數(shù)據(jù) y 有一個(gè)宏觀的把握,這里是輸出 summary,也可以用 boxplot,histogram 等形式觀察

df_train['SalePrice'].describe()

count      1460.000000
mean     180921.195890
std       79442.502883
min       34900.000000
25%      129975.000000
50%      163000.000000
75%      214000.000000
max      755000.000000
Name: SalePrice, dtype: float64

count 就是有多少行觀察記錄,另外注意一下 min 并未有小于 0 的這樣的不合理的數(shù)值。

3. 通過 Correlation matrix 觀察哪些變量會(huì)和預(yù)測(cè)目標(biāo)關(guān)系比較大,哪些變量之間會(huì)有較強(qiáng)的關(guān)聯(lián)

#correlation matrix
corrmat = df_train.corr()
f, ax = plt.subplots(figsize=(12, 9))
sns.heatmap(corrmat, vmax=.8, square=True);

我們可以看上圖的最右邊一列(也可以是下面最后一行),顏色由深到淺查看,
可以發(fā)現(xiàn) OverallQual 和 GrLivArea 的確是對(duì)目標(biāo)影響較大的因素,
另外觀察中間區(qū)域的幾個(gè)深色塊,例如 'TotalBsmtSF' 和 '1stFlrSF' 二者關(guān)系較強(qiáng),回看它們的定義,它們所包含的信息差不多所以才有顯示出強(qiáng)關(guān)聯(lián):

TotalBsmtSF: Total square feet of basement area
1stFlrSF: First Floor square feet

那這種時(shí)候,我們可以只取其中一個(gè)特征。

或者我們可以把與目標(biāo) 'SalePrice' 最緊密關(guān)聯(lián)的 10 個(gè)變量的關(guān)聯(lián)度打印出來:

#saleprice correlation matrix
k = 10 #number of variables for heatmap
cols = corrmat.nlargest(k, 'SalePrice')['SalePrice'].index
cm = np.corrcoef(df_train[cols].values.T)
sns.set(font_scale=1.25)
hm = sns.heatmap(cm, cbar=True, annot=True, square=True, fmt='.2f', annot_kws={'size': 10}, yticklabels=cols.values, xticklabels=cols.values)
plt.show()

通過這些數(shù)值,我們?cè)僖灰挥^察變量含義,判斷一下是否可以把其中某些變量刪除。

4. 接下來看 missing value

#missing data
total = df_train.isnull().sum().sort_values(ascending=False)
percent = (df_train.isnull().sum()/df_train.isnull().count()).sort_values(ascending=False)
missing_data = pd.concat([total, percent], axis=1, keys=['Total', 'Percent'])
missing_data.head(20)

先把每個(gè)變量的 NaN 記錄個(gè)數(shù)求和算出來,再把所占的比例計(jì)算一下,
對(duì)于占比例太大的變量,例如超過了 15%,就看看它的含義,如果不是很重要,這種數(shù)據(jù)是可以刪掉的,
對(duì)于剩下的,再一個(gè)一個(gè)查看變量的含義,及比例,判斷是否可以刪掉,
最后一個(gè)變量只有一條是 missing 的,那么就可以只刪掉這一個(gè)記錄。
此外,我們還可以通過補(bǔ)充 missing 的值,通過實(shí)際變量的含義進(jìn)行補(bǔ)充,例如類別型變量,就可以補(bǔ)充成 No,數(shù)值型變量可以補(bǔ)充成 0,或者用平均值來填充。

#dealing with missing data
df_train = df_train.drop((missing_data[missing_data['Total'] > 1]).index,1)
df_train = df_train.drop(df_train.loc[df_train['Electrical'].isnull()].index)

5. 下面是看 outliers
我們可以先來看主要的幾個(gè)變量的 outliers

#bivariate analysis saleprice/grlivarea
var = 'GrLivArea'
data = pd.concat([df_train['SalePrice'], df_train[var]], axis=1)
data.plot.scatter(x=var, y='SalePrice', ylim=(0,800000));

例如 'GrLivArea' 這個(gè)變量,它的右下角這幾個(gè)點(diǎn)離主體就比較遠(yuǎn),可以猜測(cè)一下產(chǎn)生這樣數(shù)據(jù)的原因,但因?yàn)椴荒艽碇黧w的,所以此時(shí)先刪掉:

#deleting points
df_train.sort_values(by = 'GrLivArea', ascending = False)[:2]
df_train = df_train.drop(df_train[df_train['Id'] == 1299].index)
df_train = df_train.drop(df_train[df_train['Id'] == 524].index)

6. 很重要的一步是把不符合正態(tài)分布的變量給轉(zhuǎn)化成正態(tài)分布的
因?yàn)橐恍┙y(tǒng)計(jì)檢驗(yàn)方法需要數(shù)據(jù)滿足正態(tài)分布的條件。

#histogram and normal probability plot
sns.distplot(df_train['SalePrice'], fit=norm);
fig = plt.figure()
res = stats.probplot(df_train['SalePrice'], plot=plt)

這個(gè)圖里可以看到 'SalePrice' 的分布是正偏度,在正偏度的情況下,用 log 取對(duì)數(shù)后可以做到轉(zhuǎn)換:

#applying log transformation
df_train['SalePrice'] = np.log(df_train['SalePrice'])

同樣,我們可以把其他不符合正態(tài)分布的變量進(jìn)行轉(zhuǎn)化,
例如 GrLivArea 和 目標(biāo)值 SalePrice 在轉(zhuǎn)化之前的關(guān)系圖是類似錐形的:

#scatter plot
plt.scatter(df_train['GrLivArea'], df_train['SalePrice']);

在對(duì) GrLivArea 轉(zhuǎn)換后,

#data transformation
df_train['GrLivArea'] = np.log(df_train['GrLivArea'])

如何構(gòu)造特征?

通過上面的步驟,我們大概可以篩選出一些重要的特征,除了數(shù)據(jù)集給定的變量之外,我們也可以自己建立一些新的特征。

1. 數(shù)值變類別型
例如,MoSold: Month Sold 這個(gè)變量看起來是數(shù)值型的,但其實(shí)更符合類別型的,所以要做一下轉(zhuǎn)換:

"MoSold" : {1 : "Jan", 2 : "Feb", 3 : "Mar", 4 : "Apr", 5 : "May", 6 : "Jun", 7 : "Jul", 8 : "Aug", 9 : "Sep", 10 : "Oct", 11 : "Nov", 12 : "Dec"}

2. 類別型加順序
例如,F(xiàn)unctional: Home functionality rating 這個(gè)變量,它是個(gè) rating,那么這種數(shù)值應(yīng)該是有序的,并且這種順序是帶有信息的,那我們就給轉(zhuǎn)化成數(shù)字:

"Functional" : {"Sal" : 1, "Sev" : 2, "Maj2" : 3, "Maj1" : 4, "Mod": 5, "Min2" : 6, "Min1" : 7, "Typ" : 8}

3. 簡(jiǎn)化類別
當(dāng)然類別太多了的不好,可以進(jìn)一步簡(jiǎn)化成兩三個(gè)等級(jí):

train["SimplFunctional"] = train.Functional.replace(
{1 : 1, 2 : 1, # bad
3 : 2, 4 : 2, # major
5 : 3, 6 : 3, 7 : 3, # minor
8 : 4 # typical})

4. 構(gòu)造多項(xiàng)式
另外一種常用的方式是構(gòu)造多項(xiàng)式,一般是 2次項(xiàng),3次項(xiàng),開平方:

train["OverallQual-s2"] = train["OverallQual"] ** 2
train["OverallQual-s3"] = train["OverallQual"] ** 3
train["OverallQual-Sq"] = np.sqrt(train["OverallQual"])

5. 加減乘除
還有通過加減乘除的數(shù)學(xué)關(guān)系構(gòu)造:

OverallQual: Overall material and finish quality
OverallCond: Overall condition rating

train["OverallGrade"] = train["OverallQual"] * train["OverallCond"]

6. 變?yōu)?one-h(huán)ot
然后我們來把 categorical 的變量給變成 one-h(huán)ot 的形式:

#convert categorical variable into dummy
df_train = pd.get_dummies(df_train)

提交結(jié)果

接下來用一個(gè)最簡(jiǎn)單的線性規(guī)劃,來展示一下運(yùn)行步驟,

1. 引入常用包

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

2. 導(dǎo)入數(shù)據(jù)

train = pd.read_csv("train.csv")
test = pd.read_csv("test.csv")

print ("Train data shape:", train.shape)
print ("Test data shape:", test.shape)
#('Train data shape:', (1460, 81))
#('Test data shape:', (1459, 80))

3. 取 log 轉(zhuǎn)化為正態(tài),看 correlation,處理 outliers,missing value
此處可以對(duì) train 數(shù)據(jù)集應(yīng)用數(shù)據(jù)探索的幾種方法。

#取 log 轉(zhuǎn)化為正態(tài)
target = np.log(train.SalePrice)

#看 correlation
numeric_features = train.select_dtypes(include=[np.number])
numeric_features.dtypes
corr = numeric_features.corr()
print (corr['SalePrice'].sort_values(ascending=False)[:5], '\n')
print (corr['SalePrice'].sort_values(ascending=False)[-5:])

#處理 outliers
train = train[train['GarageArea'] < 1200]

#處理 missing value
data = train.select_dtypes(include=[np.number]).interpolate().dropna() 

4. 轉(zhuǎn)化為 one-h(huán)ot 向量
這里可以用構(gòu)造特征的幾種方法。

train['enc_street'] = pd.get_dummies(train.Street, drop_first=True)
test['enc_street'] = pd.get_dummies(train.Street, drop_first=True)

5. 模型訓(xùn)練,預(yù)測(cè)
train_test_split 將 train 數(shù)據(jù)集分為 train 和 valid 數(shù)據(jù),
只用一個(gè)簡(jiǎn)單的 linear_model 來擬合,用 mean_squared_error 得到誤差值。

y = np.log(train.SalePrice)
X = data.drop(['SalePrice', 'Id'], axis=1)

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(
                                    X, y, random_state=42, test_size=.33)
                                    
from sklearn import linear_model
lr = linear_model.LinearRegression()

model = lr.fit(X_train, y_train)

predictions = model.predict(X_test)

from sklearn.metrics import mean_squared_error
print ('RMSE is: \n', mean_squared_error(y_test, predictions))

對(duì) test.csv 應(yīng)用剛才的模型進(jìn)行預(yù)測(cè),
因?yàn)榍懊鎸?duì) test 數(shù)據(jù)取了 log,這里要用 exp 變?yōu)樵瓉淼姆秶?/p>

feats = test.select_dtypes(
        include=[np.number]).drop(['Id'], axis=1).interpolate()
predictions = model.predict(feats)
final_predictions = np.exp(predictions)

6. 提交結(jié)果

構(gòu)造一個(gè) submission 格式的 csv,
final_predictions 作為預(yù)測(cè)值列輸入進(jìn)去,
輸出這個(gè) csv 后,就可以在比賽主頁上的 submit 藍(lán)色按鈕上點(diǎn)擊提交。

submission = pd.DataFrame()
submission['Id'] = test.Id
submission['SalePrice'] = final_predictions
submission.to_csv('output.csv', index=False)

#Your submission scored 0.13878

初級(jí)的結(jié)果出來了,大概在50%的排位,之后可以嘗試其他算法:
例如 Random Forest Regressors , Gradient Boosting,ensembling models 等,以及過擬合的分析,配合特征工程等。


這篇文章里面的代碼例子,并不會(huì)帶你進(jìn)入前幾位,只是介紹一個(gè)完整的過程,常用的方法和代碼實(shí)現(xiàn),至于如何讓算法發(fā)揮高效作用,就看玩家怎么挖掘特征,怎么組合算法和特征,怎么調(diào)參了,因?yàn)檫@也是最有趣的環(huán)節(jié),以一個(gè)輕松的方式入門,再以一個(gè)提升的心態(tài)不斷進(jìn)步。

參考:
https://www.kaggle.com/pmarcelino/comprehensive-data-exploration-with-python
https://www.kaggle.com/juliencs/a-study-on-regression-applied-to-the-ames-dataset

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容