日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

kaggle(02)-房价预测案例(基础版)

發布時間:2023/12/13 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 kaggle(02)-房价预测案例(基础版) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

房價預測案例

Step 1: 檢視源數據集

import numpy as np import pandas as pd

讀入數據

  • 一般來說源數據的index那一欄沒什么用,我們可以用來作為我們pandas dataframe的index。這樣之后要是檢索起來也省事兒。

  • 有人的地方就有鄙視鏈。跟知乎一樣。Kaggle的也是個處處呵呵的危險地帶。Kaggle上默認把數據放在input文件夾下。所以我們沒事兒寫個教程什么的,也可以依據這個convention來,顯得自己很有逼格。。

train_df = pd.read_csv('train.csv', index_col=0) test_df = pd.read_csv('test.csv', index_col=0)

檢視源數據

train_df.head() # print(train_df.info) # print(train_df.shape) MSSubClassMSZoningLotFrontageLotAreaStreetAlleyLotShapeLandContourUtilitiesLotConfig...PoolAreaPoolQCFenceMiscFeatureMiscValMoSoldYrSoldSaleTypeSaleConditionSalePriceId12345
60RL65.08450PaveNaNRegLvlAllPubInside...0NaNNaNNaN022008WDNormal208500
20RL80.09600PaveNaNRegLvlAllPubFR2...0NaNNaNNaN052007WDNormal181500
60RL68.011250PaveNaNIR1LvlAllPubInside...0NaNNaNNaN092008WDNormal223500
70RL60.09550PaveNaNIR1LvlAllPubCorner...0NaNNaNNaN022006WDAbnorml140000
60RL84.014260PaveNaNIR1LvlAllPubFR2...0NaNNaNNaN0122008WDNormal250000

5 rows × 80 columns

這時候大概心里可以有數,哪些地方需要人為的處理一下,以做到源數據更加好被process。

Step 2: 合并數據:將測試集和訓練集的數據進行合并,因為要對數據做預處理

這么做主要是為了用DF進行數據預處理的時候更加方便。等所有的需要的預處理進行完之后,我們再把他們分隔開。

首先,SalePrice作為我們的訓練目標,只會出現在訓練集中,不會在測試集中(要不然你測試什么?)。所以,我們先把SalePrice這一列給拿出來,不讓它礙事兒。

我們先看一下SalePrice長什么樣紙:

%matplotlib inline prices = pd.DataFrame({"price":train_df["SalePrice"], "log(price + 1)":np.log1p(train_df["SalePrice"])}) prices.hist() array([[<matplotlib.axes._subplots.AxesSubplot object at 0x7fbf9f8703c8>,<matplotlib.axes._subplots.AxesSubplot object at 0x7fbf97340400>]],dtype=object)

可見,label本身并不平滑。為了我們分類器的學習更加準確,我們會首先把label給“平滑化”(正態化)

這一步大部分同學會miss掉,導致自己的結果總是達不到一定標準。

這里我們使用最有逼格的log1p, 也就是 log(x+1),避免了復值的問題。

記住喲,如果我們這里把數據都給平滑化了,那么最后算結果的時候,要記得把預測到的平滑數據給變回去。

按照“怎么來的怎么去”原則,log1p()就需要expm1(); 同理,log()就需要exp(), … etc.

對于分類問題,不需要對標簽進行平滑處理,因為其結果本來就是需要離散化的;但是對于回歸問題,由于需要預測的是一個連續的值,所以需要訓練模型的數據的標簽也是平滑的,而對于訓練集,我們得到的標簽往往又是離散的,所以要先做平滑處理!

注:在比賽中,由于訓練集和測試集已經知道,所以常常為了更大的得到好的結果,常常將測試集和訓練集先混合在一起,然后在整體做數據的預處理;但是在實際的過程中,由于測試集是未知的,所以先對訓練集做處理,再用相同的方法去處理測試集。

y_train = np.log1p(train_df.pop('SalePrice'))

然后我們把剩下的部分合并起來

all_df = pd.concat((train_df, test_df), axis=0)

此刻,我們可以看到all_df就是我們合在一起的DF

all_df.shape (2919, 79)

而y_train則是SalePrice那一列

y_train.head() Id 1 12.247699 2 12.109016 3 12.317171 4 11.849405 5 12.429220 Name: SalePrice, dtype: float64

Step 3: 變量轉化

類似『特征工程』。就是把不方便處理或者不unify的數據給統一了。

正確化變量屬性

首先,我們注意到,MSSubClass 的值其實應該是一個category,

但是Pandas是不會懂這些事兒的。使用DF的時候,這類數字符號會被默認記成數字。

這種東西就很有誤導性,我們需要把它變回成string

all_df['MSSubClass'].dtypes dtype('int64') all_df['MSSubClass'] = all_df['MSSubClass'].astype(str) #這個根據給出的數據集的描述可知,該屬性應該是表示的為級別,但是PD在讀取數據的時候會自動將其認為是數字,所以需要轉換為字符串

變成str以后,做個統計,就很清楚了

all_df['MSSubClass'].value_counts() 20 1079 60 575 50 287 120 182 30 139 160 128 70 128 80 118 90 109 190 61 85 48 75 23 45 18 180 17 40 6 150 1 Name: MSSubClass, dtype: int64

把category的變量轉變成numerical表達形式

當我們用numerical來表達categorical的時候,要注意,數字本身有大小的含義,所以亂用數字會給之后的模型學習帶來麻煩。于是我們可以用One-Hot的方法來表達category。

pandas自帶的get_dummies方法,可以幫你一鍵做到One-Hot。

pd.get_dummies(all_df['MSSubClass'], prefix='MSSubClass').head()#將分類數據轉換為數值型數據 MSSubClass_120MSSubClass_150MSSubClass_160MSSubClass_180MSSubClass_190MSSubClass_20MSSubClass_30MSSubClass_40MSSubClass_45MSSubClass_50MSSubClass_60MSSubClass_70MSSubClass_75MSSubClass_80MSSubClass_85MSSubClass_90Id12345
0000000000100000
0000010000000000
0000000000100000
0000000000010000
0000000000100000

此刻MSSubClass被我們分成了12個column,每一個代表一個category。是就是1,不是就是0。

同理,我們把所有的category數據,都給One-Hot了

all_dummy_df = pd.get_dummies(all_df) all_dummy_df.head() LotFrontageLotAreaOverallQualOverallCondYearBuiltYearRemodAddMasVnrAreaBsmtFinSF1BsmtFinSF2BsmtUnfSF...SaleType_ConLwSaleType_NewSaleType_OthSaleType_WDSaleCondition_AbnormlSaleCondition_AdjLandSaleCondition_AllocaSaleCondition_FamilySaleCondition_NormalSaleCondition_PartialId12345
65.084507520032003196.0706.00.0150.0...0001000010
80.0960068197619760.0978.00.0284.0...0001000010
68.0112507520012002162.0486.00.0434.0...0001000010
60.0955075191519700.0216.00.0540.0...0001100000
84.0142608520002000350.0655.00.0490.0...0001000010

5 rows × 303 columns

處理好numerical變量

就算是numerical的變量,也還會有一些小問題。

比如,有一些數據是缺失 的:

all_dummy_df.isnull().sum().sort_values(ascending=False).head(10) #將數據中有缺失項的屬性統計出來并從大到小排序 LotFrontage 486 GarageYrBlt 159 MasVnrArea 23 BsmtHalfBath 2 BsmtFullBath 2 BsmtFinSF2 1 GarageCars 1 TotalBsmtSF 1 BsmtUnfSF 1 GarageArea 1 dtype: int64

可以看到,缺失最多的column是LotFrontage

處理這些缺失的信息,得靠好好審題。一般來說,數據集的描述里會寫的很清楚,這些缺失都代表著什么。當然,如果實在沒有的話,也只能靠自己的『想當然』。。

在這里,我們用平均值來填滿這些空缺。

mean_cols = all_dummy_df.mean()#得到所有列的平均值 mean_cols.head(10) #打印出前10列數據的平均值 LotFrontage 69.305795 LotArea 10168.114080 OverallQual 6.089072 OverallCond 5.564577 YearBuilt 1971.312778 YearRemodAdd 1984.264474 MasVnrArea 102.201312 BsmtFinSF1 441.423235 BsmtFinSF2 49.582248 BsmtUnfSF 560.772104 dtype: float64 all_dummy_df = all_dummy_df.fillna(mean_cols) #用每一列的平均值填充每一列中的NAN項

看看是不是沒有空缺了?

all_dummy_df.isnull().sum().sum() 0

標準化numerical數據

這一步并不是必要,但是得看你想要用的分類器是什么。一般來說,regression的分類器都比較傲嬌,最好是把源數據給放在一個標準分布內。不要讓數據間的差距太大。

這里,我們當然不需要把One-Hot的那些0/1數據給標準化。我們的目標應該是那些本來就是numerical的數據:

先來看看 哪些是numerical的:

numeric_cols = all_df.columns[all_df.dtypes != 'object'] numeric_cols Index(['LotFrontage', 'LotArea', 'OverallQual', 'OverallCond', 'YearBuilt','YearRemodAdd', 'MasVnrArea', 'BsmtFinSF1', 'BsmtFinSF2', 'BsmtUnfSF','TotalBsmtSF', '1stFlrSF', '2ndFlrSF', 'LowQualFinSF', 'GrLivArea','BsmtFullBath', 'BsmtHalfBath', 'FullBath', 'HalfBath', 'BedroomAbvGr','KitchenAbvGr', 'TotRmsAbvGrd', 'Fireplaces', 'GarageYrBlt','GarageCars', 'GarageArea', 'WoodDeckSF', 'OpenPorchSF','EnclosedPorch', '3SsnPorch', 'ScreenPorch', 'PoolArea', 'MiscVal','MoSold', 'YrSold'],dtype='object')

計算標準分布:(X-X’)/s

讓我們的數據點更平滑,更便于計算。

注意:我們這里也是可以繼續使用Log的,我只是給大家展示一下多種“使數據平滑”的辦法。

numeric_col_means = all_dummy_df.loc[:, numeric_cols].mean()#算出每一個數值型的屬性下數據的平均值 numeric_col_std = all_dummy_df.loc[:, numeric_cols].std()#算出每一個數值型的屬性下數據的方差 all_dummy_df.loc[:, numeric_cols] = (all_dummy_df.loc[:, numeric_cols] - numeric_col_means) / numeric_col_std #計算標準分布

Step 4: 建立模型

把數據集分回 訓練/測試集

dummy_train_df = all_dummy_df.loc[train_df.index] dummy_test_df = all_dummy_df.loc[test_df.index] dummy_train_df.shape, dummy_test_df.shape ((1460, 303), (1459, 303))

Ridge Regression

用Ridge Regression模型來跑一遍看看。(對于多因子的數據集,這種模型可以方便的把所有的var都無腦的放進去)

from sklearn.linear_model import Ridge from sklearn.model_selection import cross_val_score

這一步不是很必要,只是把DF轉化成Numpy Array,這跟Sklearn更加配

X_train = dummy_train_df.values X_test = dummy_test_df.values

用Sklearn自帶的cross validation方法來測試模型

alphas = np.logspace(-3, 2, 50) test_scores = [] for alpha in alphas:clf = Ridge(alpha)test_score = np.sqrt(-cross_val_score(clf, X_train, y_train, cv=10, scoring='neg_mean_squared_error'))test_scores.append(np.mean(test_score))

存下所有的CV值,看看哪個alpha值更好(也就是『調參數』)

import matplotlib.pyplot as plt %matplotlib inline plt.plot(alphas, test_scores) plt.title("Alpha vs CV Error");

可見,大概alpha=10~20的時候,可以把score達到0.135左右。

Random Forest

from sklearn.ensemble import RandomForestRegressor max_features = [.1, .3, .5, .7, .9, .99] test_scores = [] for max_feat in max_features:clf = RandomForestRegressor(n_estimators=200, max_features=max_feat)test_score = np.sqrt(-cross_val_score(clf, X_train, y_train, cv=5, scoring='neg_mean_squared_error'))test_scores.append(np.mean(test_score)) plt.plot(max_features, test_scores) plt.title("Max Features vs CV Error");

用RF的最優值達到了0.137

Step 5: Ensemble

這里我們用一個Stacking的思維來汲取兩種或者多種模型的優點

首先,我們把最好的parameter拿出來,做成我們最終的model

ridge = Ridge(alpha=15) rf = RandomForestRegressor(n_estimators=500, max_features=.3) ridge.fit(X_train, y_train) rf.fit(X_train, y_train) RandomForestRegressor(bootstrap=True, criterion='mse', max_depth=None,max_features=0.3, max_leaf_nodes=None,min_impurity_decrease=0.0, min_impurity_split=None,min_samples_leaf=1, min_samples_split=2,min_weight_fraction_leaf=0.0, n_estimators=500, n_jobs=1,oob_score=False, random_state=None, verbose=0, warm_start=False)

上面提到了,因為最前面我們給label做了個log(1+x), 于是這里我們需要把predit的值給exp回去,并且減掉那個"1"

所以就是我們的expm1()函數。

y_ridge = np.expm1(ridge.predict(X_test)) y_rf = np.expm1(rf.predict(X_test))

一個正經的Ensemble是把這群model的預測結果作為新的input,再做一次預測。這里我們簡單的方法,就是直接『平均化』。

y_final = (y_ridge + y_rf) / 2 #對模型進行融合

Step 6: 提交結果

submission_df = pd.DataFrame(data= {'Id' : test_df.index, 'SalePrice': y_final})

我們的submission大概長這樣:

submission_df.head(10) IdSalePrice0123456789
1461120284.850938
1462151366.179663
1463174792.133120
1464190099.605945
1465195500.170436
1466175876.563502
1467177675.128914
1468169318.651321
1469184796.699921
1470122328.836416

走你~

總結

以上是生活随笔為你收集整理的kaggle(02)-房价预测案例(基础版)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。