房价预测(基于决策树算法)
預(yù)測(cè)波士頓房?jī)r(jià)
第一步. 導(dǎo)入數(shù)據(jù)
在這個(gè)項(xiàng)目中,將使用波士頓房屋信息數(shù)據(jù)來(lái)訓(xùn)練和測(cè)試一個(gè)模型,并對(duì)模型的性能和預(yù)測(cè)能力進(jìn)行評(píng)估。我們希望可以通過(guò)該模型實(shí)現(xiàn)對(duì)房屋的價(jià)值預(yù)估,提高房地產(chǎn)經(jīng)紀(jì)人的工作效率。
此項(xiàng)目的數(shù)據(jù)集來(lái)自kaggle原始數(shù)據(jù),未經(jīng)過(guò)任何處理。該數(shù)據(jù)集統(tǒng)計(jì)了2006年至2010年波士頓個(gè)人住宅銷(xiāo)售情況,包含2900多條觀測(cè)數(shù)據(jù)(其中一半是訓(xùn)練數(shù)據(jù),即我們的housedata.csv文件)。更多文檔信息可以參考作者的文檔,以及項(xiàng)目附件data_description.txt文件(特征描述文件)。
下面區(qū)域的代碼用以載入一些此項(xiàng)目所需的Python庫(kù)。
# 載入此項(xiàng)目需要的庫(kù) import numpy as np import pandas as pd import visuals as vs # Supplementary code 補(bǔ)充的可視化代碼import matplotlib.pyplot as plt import seaborn as sns plt.style.use('seaborn') # use seaborn style 使用seaborn風(fēng)格import warnings warnings.filterwarnings('ignore')%matplotlib inline print('你已經(jīng)成功載入所有庫(kù)!') 你已經(jīng)成功載入所有庫(kù)!
加載數(shù)據(jù)
# 載入波士頓房屋的數(shù)據(jù)集:使用pandas載入csv,并賦值到data_df data_df = pd.read_csv('housedata.csv')# 成功載入的話輸出訓(xùn)練數(shù)據(jù)行列數(shù)目 print("Boston housing dataset has {} data points with {} variables each.".format(*data_df.shape)) Boston housing dataset has 1460 data points with 81 variables each.
第二步. 數(shù)據(jù)分析
這個(gè)部分,將對(duì)已有的波士頓房地產(chǎn)數(shù)據(jù)進(jìn)行初步的觀察與處理。
由于這個(gè)項(xiàng)目的最終目標(biāo)是建立一個(gè)預(yù)測(cè)房屋價(jià)值的模型,需要將數(shù)據(jù)集分為特征(features)和目標(biāo)變量(target variable)。
- 目標(biāo)變量:'SalePrice',是我們希望預(yù)測(cè)的變量。
- 特征:除'SalePrice'外的屬性都是特征,它們反應(yīng)了數(shù)據(jù)點(diǎn)在某些方面的表現(xiàn)或性質(zhì)。
觀察數(shù)據(jù)
對(duì)波士頓房?jī)r(jià)的數(shù)據(jù)進(jìn)行觀察,從而掌握更多數(shù)據(jù)本身的信息。
(1)使用 head方法 打印并觀察前7條data_df數(shù)據(jù)
# 打印出前7條data_df print(data_df.head(7)) Id MSSubClass MSZoning LotFrontage LotArea Street Alley LotShape \ 0 1 60 RL 65.0 8450 Pave NaN Reg 1 2 20 RL 80.0 9600 Pave NaN Reg 2 3 60 RL 68.0 11250 Pave NaN IR1 3 4 70 RL 60.0 9550 Pave NaN IR1 4 5 60 RL 84.0 14260 Pave NaN IR1 5 6 50 RL 85.0 14115 Pave NaN IR1 6 7 20 RL 75.0 10084 Pave NaN Reg LandContour Utilities ... PoolArea PoolQC Fence MiscFeature MiscVal \ 0 Lvl AllPub ... 0 NaN NaN NaN 0 1 Lvl AllPub ... 0 NaN NaN NaN 0 2 Lvl AllPub ... 0 NaN NaN NaN 0 3 Lvl AllPub ... 0 NaN NaN NaN 0 4 Lvl AllPub ... 0 NaN NaN NaN 0 5 Lvl AllPub ... 0 NaN MnPrv Shed 700 6 Lvl AllPub ... 0 NaN NaN NaN 0 MoSold YrSold SaleType SaleCondition SalePrice 0 2 2008 WD Normal 208500 1 5 2007 WD Normal 181500 2 9 2008 WD Normal 223500 3 2 2006 WD Abnorml 140000 4 12 2008 WD Normal 250000 5 10 2009 WD Normal 143000 6 8 2007 WD Normal 307000 [7 rows x 81 columns](2)Id特征對(duì)我們訓(xùn)練數(shù)據(jù)沒(méi)有任何用處,在data_df中使用drop方法刪除'Id'列數(shù)據(jù)
# 刪除data_df中的Id特征(保持?jǐn)?shù)據(jù)仍在data_df中,不更改變量名) data_df.drop('Id',axis=1,inplace=True)(3)使用describe方法觀察data_df各個(gè)特征的統(tǒng)計(jì)信息:
data_df.describe()| 1460.000000 | 1201.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1452.000000 | 1460.000000 | 1460.000000 | ... | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 | 1460.000000 |
| 56.897260 | 70.049958 | 10516.828082 | 6.099315 | 5.575342 | 1971.267808 | 1984.865753 | 103.685262 | 443.639726 | 46.549315 | ... | 94.244521 | 46.660274 | 21.954110 | 3.409589 | 15.060959 | 2.758904 | 43.489041 | 6.321918 | 2007.815753 | 180921.195890 |
| 42.300571 | 24.284752 | 9981.264932 | 1.382997 | 1.112799 | 30.202904 | 20.645407 | 181.066207 | 456.098091 | 161.319273 | ... | 125.338794 | 66.256028 | 61.119149 | 29.317331 | 55.757415 | 40.177307 | 496.123024 | 2.703626 | 1.328095 | 79442.502883 |
| 20.000000 | 21.000000 | 1300.000000 | 1.000000 | 1.000000 | 1872.000000 | 1950.000000 | 0.000000 | 0.000000 | 0.000000 | ... | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 1.000000 | 2006.000000 | 34900.000000 |
| 20.000000 | 59.000000 | 7553.500000 | 5.000000 | 5.000000 | 1954.000000 | 1967.000000 | 0.000000 | 0.000000 | 0.000000 | ... | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 5.000000 | 2007.000000 | 129975.000000 |
| 50.000000 | 69.000000 | 9478.500000 | 6.000000 | 5.000000 | 1973.000000 | 1994.000000 | 0.000000 | 383.500000 | 0.000000 | ... | 0.000000 | 25.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 6.000000 | 2008.000000 | 163000.000000 |
| 70.000000 | 80.000000 | 11601.500000 | 7.000000 | 6.000000 | 2000.000000 | 2004.000000 | 166.000000 | 712.250000 | 0.000000 | ... | 168.000000 | 68.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 8.000000 | 2009.000000 | 214000.000000 |
| 190.000000 | 313.000000 | 215245.000000 | 10.000000 | 9.000000 | 2010.000000 | 2010.000000 | 1600.000000 | 5644.000000 | 1474.000000 | ... | 857.000000 | 547.000000 | 552.000000 | 508.000000 | 480.000000 | 738.000000 | 15500.000000 | 12.000000 | 2010.000000 | 755000.000000 |
8 rows × 37 columns
數(shù)據(jù)預(yù)處理
數(shù)據(jù)不可能是百分百的‘干凈’數(shù)據(jù)(即有用數(shù)據(jù)),總會(huì)在采集整理時(shí)有些”失誤“、“冗余”,造成“臟”數(shù)據(jù),所以要從數(shù)據(jù)的正確性和完整性這兩個(gè)方面來(lái)清理數(shù)據(jù)。
- 正確性:一般是指有沒(méi)有異常值,比如我們這個(gè)數(shù)據(jù)集中作者的文檔所說(shuō):
I would recommend removing any houses with more than 4000 square feet from the data set (which eliminates these five unusual observations) before assigning it to students.
建議我們?nèi)サ魯?shù)據(jù)中'GrLivArea'中超過(guò)4000平方英尺的房屋(具體原因可以參考文檔),當(dāng)然本數(shù)據(jù)集還有其他的異常點(diǎn),這里不再處理。 - 完整性:采集或者整理數(shù)據(jù)時(shí)所產(chǎn)生的空數(shù)據(jù)造成了數(shù)據(jù)的完整性缺失,通常我們會(huì)使用一定的方法處理不完整的數(shù)據(jù)。在本例中,我們使用以下兩種方法,一是丟棄數(shù)據(jù),即選擇丟棄過(guò)多空數(shù)據(jù)的特征(或者直接丟棄數(shù)據(jù)行,前提是NA數(shù)據(jù)占比不多),二是填補(bǔ)數(shù)據(jù),填補(bǔ)的方法也很多,均值中位數(shù)眾數(shù)填充等等都是好方法。
正確性方面
以下代碼將使用matplotlib庫(kù)中的scatter方法 繪制'GrLivArea'和'SalePrice'的散點(diǎn)圖,x軸為'GrLivArea',y軸為'SalePrice',觀察數(shù)據(jù)**
# 繪制散點(diǎn)圖 plt.scatter(data_df['GrLivArea'],data_df['SalePrice']) plt.xlabel('GrLivArea') plt.ylabel('SalePrice') plt.show()**觀察所得:通過(guò)上圖我們可以看到那幾個(gè)異常值,即'GrLivArea'大于4000,但是'SalePrice'又極低的數(shù)據(jù),所以需要從data_df刪除這幾個(gè)異常值。
刪除后重新繪制'GrLivArea'和'SalePrice'的關(guān)系圖,確認(rèn)異常值已刪除。**
# 從data_df中刪除 GrLivArea大于4000 且 SalePrice低于300000 的值 index_del = data_df[(data_df['GrLivArea'] > 4000) & (data_df['SalePrice'] < 300000)].index data_df.drop(index=index_del, inplace=True)# 重新繪制GrLivArea和SalePrice的關(guān)系圖,確認(rèn)異常值已刪除 plt.scatter(data_df['GrLivArea'],data_df['SalePrice']) plt.xlabel('GrLivArea') plt.ylabel('SalePrice') plt.show()
完整性方面
篩選出過(guò)多空數(shù)據(jù)的特征,這個(gè)項(xiàng)目定為篩選出有超過(guò)25%為空數(shù)據(jù)的特征
limit_percent = 0.25 limit_value = len(data_df) * limit_percent # 統(tǒng)計(jì)并打印出超過(guò)25%的空數(shù)據(jù)的特征 list(data_df.columns[data_df.isna().sum() > limit_value]) ['Alley', 'FireplaceQu', 'PoolQC', 'Fence', 'MiscFeature']接著,查看data_description.txt文件,就會(huì)發(fā)現(xiàn),這些并非一定是空缺數(shù)據(jù),而沒(méi)有游泳池,籬笆等也會(huì)用NA來(lái)表示,那么就不需要?jiǎng)h除這些特征了,而是用None來(lái)填充N(xiāo)A數(shù)據(jù)。
以下將使用fillna方法填充空數(shù)據(jù)。
# 確定所有空特征 missing_columns = list(data_df.columns[data_df.isnull().sum() != 0]) # 確定哪些是類(lèi)別特征,哪些是數(shù)值特征 missing_numerical = list(data_df[missing_columns].dtypes[data_df[missing_columns].dtypes != 'object'].index) missing_category = [i for i in missing_columns if i not in missing_numerical] print("missing_numerical:",missing_numerical) print("missing_category:",missing_category) missing_numerical: ['LotFrontage', 'MasVnrArea', 'GarageYrBlt'] missing_category: ['Alley', 'MasVnrType', 'BsmtQual', 'BsmtCond', 'BsmtExposure', 'BsmtFinType1', 'BsmtFinType2', 'Electrical', 'FireplaceQu', 'GarageType', 'GarageFinish', 'GarageQual', 'GarageCond', 'PoolQC', 'Fence', 'MiscFeature'] # 需要填充眾數(shù)的特征 fill_Mode = ['Electrical'] # 需要填充N(xiāo)one的特征 fill_None = ['Alley', 'MasVnrType', 'BsmtQual', 'BsmtCond', 'BsmtExposure', 'BsmtFinType1', 'BsmtFinType2', 'FireplaceQu', 'GarageType', 'GarageFinish', 'GarageQual', 'GarageCond', 'PoolQC', 'Fence', 'MiscFeature'] # 需要填充0的特征 fill_0 = ['GarageYrBlt'] # 需要填充中位數(shù)的特征 fill_median = ['LotFrontage', 'MasVnrArea']# 按需填補(bǔ)上面數(shù)據(jù) data_df[fill_Mode] = data_df[fill_Mode].fillna(data_df[fill_Mode].mode()) data_df[fill_None] = data_df[fill_None].fillna('None') data_df[fill_0] = data_df[fill_0].fillna(0) data_df[fill_median] = data_df[fill_median].fillna(data_df[fill_median].mean())
特征分析
有這么一句話在業(yè)界廣泛流傳:特征數(shù)據(jù)決定了機(jī)器學(xué)習(xí)的上限,而模型和算法只是逼近這個(gè)上限而已。特征工程,是整個(gè)數(shù)據(jù)分析過(guò)程中不可缺少的一個(gè)環(huán)節(jié),其結(jié)果質(zhì)量直接關(guān)系到模型效果和最終結(jié)論。從上面兩步中我們得到了“干凈”的數(shù)據(jù),但是data_df總共有81個(gè)特征,應(yīng)當(dāng)剔除那些無(wú)關(guān)緊要的特征(噪聲),使用真正關(guān)鍵的特征來(lái)進(jìn)行模型訓(xùn)練。現(xiàn)在需要我們對(duì)這些龐大的數(shù)據(jù)進(jìn)行分析,提取出與目標(biāo)最為關(guān)聯(lián)的數(shù)據(jù)。
繪制'SalePrice'的直方圖,觀察該直方圖屬于什么分布
# 繪制直方圖 plt.hist(data_df['SalePrice']) plt.xlabel('SalePrice') plt.show()觀察結(jié)論:'SalePrice'屬于正偏態(tài)分布。
如果特征極其多,很難清晰的看到特征與目標(biāo)變量之間的關(guān)系,就需要利用統(tǒng)計(jì)知識(shí)來(lái)進(jìn)行多變量分析了。常用的方法可使用熱圖heatmap結(jié)合corr方法來(lái)進(jìn)行客觀分析,熱圖Heatmap可以用顏色變化來(lái)反映變量之間的相關(guān)性二維矩陣或說(shuō)相關(guān)性表格中的數(shù)據(jù)信息,它可以直觀地將數(shù)據(jù)值的大小以定義的顏色深淺表示出來(lái)。
這個(gè)項(xiàng)目,為了簡(jiǎn)化訓(xùn)練,將以相關(guān)性絕對(duì)值大于0.5為界來(lái)選取所需要的特征。
corrmat = data_df.corr().abs() top_corr = corrmat[corrmat["SalePrice"]>0.5].sort_values(by = ["SalePrice"], ascending = False).index cm = abs(np.corrcoef(data_df[top_corr].values.T)) f, ax = plt.subplots(figsize=(20, 9)) sns.set(font_scale=1.3) hm = sns.heatmap(cm, cbar=True, annot=True,square=True, fmt='.2f', annot_kws={'size': 13}, yticklabels=top_corr.values, xticklabels=top_corr.values); data_df = data_df[top_corr]
接下來(lái),我們從創(chuàng)造性方面來(lái)對(duì)我們的特征進(jìn)行“改造”。
- 創(chuàng)造性:創(chuàng)造性主要是說(shuō)兩種情況,一種是對(duì)現(xiàn)有數(shù)據(jù)的處理,比如對(duì)類(lèi)別的獨(dú)熱編碼(One-hotEncoder)或者標(biāo)簽編碼(LabelEncoder),數(shù)值的區(qū)間縮放,歸一化,標(biāo)準(zhǔn)化等等。另一種就是根據(jù)某一個(gè)或多個(gè)特征創(chuàng)造一個(gè)新的特征,例如某特征按組分類(lèi)(groupby)后,或者某些特征組合后來(lái)創(chuàng)造新特征等等。
因?yàn)楹Y選出來(lái)的特征都為數(shù)值類(lèi)型特征,所以只做標(biāo)準(zhǔn)化的操作:這個(gè)項(xiàng)目是一個(gè)回歸類(lèi)型的項(xiàng)目,而回歸算法對(duì)標(biāo)準(zhǔn)正態(tài)分步預(yù)測(cè)較為準(zhǔn)確,從目標(biāo)數(shù)據(jù)可以看出數(shù)據(jù)是一個(gè)偏態(tài)分布,那么將使用log將數(shù)據(jù)從偏態(tài)分布轉(zhuǎn)換為標(biāo)準(zhǔn)正態(tài)分布,最后進(jìn)行標(biāo)準(zhǔn)化。
from scipy.special import boxcox1p from sklearn.preprocessing import StandardScalerdata_df['SalePrice'] = np.log1p(data_df['SalePrice']) numeric_features = list(data_df.columns) numeric_features.remove('SalePrice') for feature in numeric_features:#all_data[feat] += 1data_df[feature] = boxcox1p(data_df[feature], 0.15)scaler = StandardScaler() scaler.fit(data_df[numeric_features]) data_df[numeric_features] = scaler.transform(data_df[numeric_features])
第三步. 建立模型
。
定義衡量標(biāo)準(zhǔn)
如果不能對(duì)模型的訓(xùn)練和測(cè)試的表現(xiàn)進(jìn)行量化地評(píng)估,就很難衡量模型的好壞。通常需要定義一些衡量標(biāo)準(zhǔn),這些標(biāo)準(zhǔn)可以通過(guò)對(duì)某些誤差或者擬合程度的計(jì)算來(lái)得到。在這個(gè)項(xiàng)目中,將通過(guò)運(yùn)算決定系數(shù) R2R^2R2 來(lái)量化模型的表現(xiàn)。模型的決定系數(shù)是回歸分析中十分常用的統(tǒng)計(jì)信息,經(jīng)常被當(dāng)作衡量模型預(yù)測(cè)能力好壞的標(biāo)準(zhǔn)。
R2R^2R2 的數(shù)值范圍從0至1,表示目標(biāo)變量的預(yù)測(cè)值和實(shí)際值之間的相關(guān)程度平方的百分比。一個(gè)模型的 R2R^2R2 值為0還不如直接用平均值來(lái)預(yù)測(cè)效果好;而一個(gè) R2R^2R2 值為1的模型則可以對(duì)目標(biāo)變量進(jìn)行完美的預(yù)測(cè)。從0至1之間的數(shù)值,則表示該模型中目標(biāo)變量中有百分之多少能夠用特征來(lái)解釋。模型也可能出現(xiàn)負(fù)值的 R2R^2R2,這種情況下模型所做預(yù)測(cè)有時(shí)會(huì)比直接計(jì)算目標(biāo)變量的平均值差很多。
在下方代碼的 performance_metric 函數(shù)中,將實(shí)現(xiàn):
- 使用 sklearn.metrics 中的 r2_score 來(lái)計(jì)算 y_true 和 y_predict 的 R2R^2R2 值,作為對(duì)其表現(xiàn)的評(píng)判。
- 將他們的表現(xiàn)評(píng)分儲(chǔ)存到 score 變量中。
擬合程度
假設(shè)一個(gè)數(shù)據(jù)集有五個(gè)數(shù)據(jù)且某一模型做出下列目標(biāo)變量的預(yù)測(cè):
| 3.0 | 2.5 |
| -0.5 | 0.0 |
| 2.0 | 2.1 |
| 7.0 | 7.8 |
| 4.2 | 5.3 |
提示:R2R^2R2 分?jǐn)?shù)是指可以從自變量中預(yù)測(cè)的因變量的方差比例。 換一種說(shuō)法:
- R2R^2R2 為0意味著因變量不能從自變量預(yù)測(cè)。
- R2R^2R2 為1意味著可以從自變量預(yù)測(cè)因變量。
- R2R^2R2 在0到1之間表示因變量可預(yù)測(cè)的程度。
- R2R^2R2 為0.40意味著 Y 中40%的方差可以從 X 預(yù)測(cè)。
下方的代碼將使用 performance_metric 函數(shù)來(lái)計(jì)算 y_true 和 y_predict 的決定系數(shù)。
# 計(jì)算這一模型的表現(xiàn) score = performance_metric([3, -0.5, 2, 7, 4.2], [2.5, 0.0, 2.1, 7.8, 5.3]) print("Model has a coefficient of determination, R^2, of {:.3f}.".format(score)) Model has a coefficient of determination, R^2, of 0.923.結(jié)論:這個(gè)模型已經(jīng)成功地描述目標(biāo)變量的變化了。因?yàn)?span id="ozvdkddzhkzd" class="katex--inline">R2R^2R2 分?jǐn)?shù)已高達(dá)0.923,說(shuō)明因變量的可預(yù)測(cè)程度非常高。
數(shù)據(jù)分割與重排
接下來(lái),將分割波士頓房屋數(shù)據(jù)集,包括特征與目標(biāo)變量、訓(xùn)練集和測(cè)試集。通常在這個(gè)過(guò)程中,數(shù)據(jù)也會(huì)被重排,以消除數(shù)據(jù)集中由于順序而產(chǎn)生的偏差。
將data_df分割為特征和目標(biāo)變量
# 分割 labels = data_df['SalePrice'] #TODO:提取SalePrice作為labels features = data_df.drop(['SalePrice'], axis=1) #TODO:提取除了SalePrice以外的特征賦值為features
下方代碼將實(shí)現(xiàn):
- 使用 sklearn.model_selection 中的 train_test_split, 將 features 和 prices 的數(shù)據(jù)都分成用于訓(xùn)練的數(shù)據(jù)子集和用于測(cè)試的數(shù)據(jù)子集。
- 分割比例為:80%的數(shù)據(jù)用于訓(xùn)練,20%用于測(cè)試;
- 選定一個(gè)數(shù)值以設(shè)定 train_test_split 中的 random_state ,這會(huì)確保結(jié)果的一致性;
- 將分割后的訓(xùn)練集與測(cè)試集分配給 X_train, X_test, y_train 和 y_test。
訓(xùn)練及測(cè)試
-
將數(shù)據(jù)集按一定比例分為訓(xùn)練用的數(shù)據(jù)集和測(cè)試用的數(shù)據(jù)集對(duì)學(xué)習(xí)算法能在一定程度上避免過(guò)擬合。
-
如果用模型已經(jīng)見(jiàn)過(guò)的數(shù)據(jù),例如部分訓(xùn)練集數(shù)據(jù)進(jìn)行測(cè)試,會(huì)使得計(jì)算準(zhǔn)確率時(shí),這個(gè)得分會(huì)不可靠。
第四步. 分析模型的表現(xiàn)
在項(xiàng)目的第四步,我們來(lái)觀察不同參數(shù)下,模型在訓(xùn)練集和驗(yàn)證集上的表現(xiàn)。這里,我們專注于一個(gè)特定的算法(帶剪枝的決策樹(shù)DecisionTreeRegressor)和這個(gè)算法的一個(gè)參數(shù) 'max_depth'。
接下來(lái),用全部訓(xùn)練集訓(xùn)練,選擇不同'max_depth' 參數(shù),觀察這一參數(shù)的變化如何影響模型的表現(xiàn)。并畫(huà)出模型的表現(xiàn)來(lái)分析。
學(xué)習(xí)曲線
下方區(qū)域內(nèi)的代碼會(huì)輸出四幅圖像,它們是一個(gè)決策樹(shù)模型在不同最大深度下的表現(xiàn)。每一條曲線都直觀得顯示了隨著訓(xùn)練數(shù)據(jù)量的增加,模型學(xué)習(xí)曲線在訓(xùn)練集評(píng)分和驗(yàn)證集評(píng)分的變化,評(píng)分使用決定系數(shù) R2R^2R2。曲線的陰影區(qū)域代表的是該曲線的不確定性(用標(biāo)準(zhǔn)差衡量)。
# Produce learning curves for varying training set sizes and maximum depths vs.ModelLearning(features, labels)學(xué)習(xí)曲線結(jié)論觀察
- 對(duì)于上述圖像中的最大深度為 3 的那個(gè),隨著訓(xùn)練數(shù)據(jù)量的增加,訓(xùn)練集曲線的評(píng)分減少,驗(yàn)證集曲線的增加。
- 如果有更多的訓(xùn)練數(shù)據(jù),也無(wú)法提升模型的表現(xiàn),因訓(xùn)練集曲線和驗(yàn)證集曲線已相交在一個(gè)數(shù)值。
復(fù)雜度曲線
下列代碼內(nèi)的區(qū)域會(huì)輸出一幅圖像,它展示了一個(gè)已經(jīng)經(jīng)過(guò)訓(xùn)練和驗(yàn)證的決策樹(shù)模型在不同最大深度條件下的表現(xiàn)。這個(gè)圖形將包含兩條曲線,一個(gè)是訓(xùn)練集的變化,一個(gè)是驗(yàn)證集的變化。跟學(xué)習(xí)曲線相似,陰影區(qū)域代表該曲線的不確定性,模型訓(xùn)練和測(cè)試部分的評(píng)分都用的 performance_metric 函數(shù)。
vs.ModelComplexity(X_train, y_train)
偏差(bias)與方差(variance)之間的權(quán)衡取舍
提示: 高偏差表示欠擬合(模型過(guò)于簡(jiǎn)單),而高方差表示過(guò)擬合(模型過(guò)于復(fù)雜,以至于無(wú)法泛化)。
觀察結(jié)論:
- 當(dāng)模型以最大深度 1訓(xùn)練時(shí),模型的預(yù)測(cè)出現(xiàn)了很大的偏差。
- 當(dāng)模型以最大深度10訓(xùn)練時(shí),模型的預(yù)測(cè)出現(xiàn)了很大的方差。
- 當(dāng)模型以最大深度 1訓(xùn)練時(shí),訓(xùn)練集得分和驗(yàn)證集得分都較低,可見(jiàn)是欠擬合的情況。當(dāng)模型以最大深度10訓(xùn)練時(shí),訓(xùn)練集得分極高和驗(yàn)證集得分不太高,而兩個(gè)得分相差甚大,可見(jiàn)是過(guò)擬合的情況。
最優(yōu)模型的猜測(cè)
- 結(jié)合復(fù)雜度曲線,可見(jiàn)最大深度是 4 的模型能夠最好地對(duì)未見(jiàn)過(guò)的數(shù)據(jù)進(jìn)行預(yù)測(cè)。
- 依據(jù):隨著最大深度的增加,訓(xùn)練集得分和驗(yàn)證集得分都在增加,但當(dāng)最大深度超過(guò)4后,驗(yàn)證集得分反而有下降的趨勢(shì),說(shuō)明模型變得越來(lái)越復(fù)雜,逐漸變得過(guò)擬合。
第五步. 評(píng)估模型的表現(xiàn)
在項(xiàng)目的最后一節(jié)中,將構(gòu)建一個(gè)模型,并使用 fit_model 中的優(yōu)化模型去預(yù)測(cè)客戶特征集。
網(wǎng)格搜索(Grid Search)
- 網(wǎng)格搜索法是窮舉所有參數(shù)的組合,找出使模型得分最高的那個(gè)組合。比如在決策樹(shù)模型里,分別用幾個(gè)不同的深度參數(shù)去訓(xùn)練模型并計(jì)算其測(cè)試集得分,測(cè)試集得分最高模型對(duì)應(yīng)的深度參數(shù)便是最優(yōu)參數(shù)。
- 優(yōu)化模型方法:嘗試所有參數(shù)的組合,以發(fā)現(xiàn)能使模型性能最好的參數(shù)組合。
交叉驗(yàn)證
- K折交叉驗(yàn)證法(k-fold cross-validation)是隨機(jī)將訓(xùn)練集劃分成K份,依次將其中的一份作為驗(yàn)證集,其余的作為訓(xùn)練集,訓(xùn)練K個(gè)模型,最后選擇模型表現(xiàn)得最好的那一個(gè)。
- GridSearchCV 是通過(guò)交叉驗(yàn)證得到每個(gè)參數(shù)組合的得分,以確定最優(yōu)的參數(shù)組合。
- GridSearchCV 中的'cv_results_'屬性能生成一個(gè)字典,記錄每組網(wǎng)格參數(shù)每次的訓(xùn)練結(jié)果,包括訓(xùn)練/驗(yàn)證時(shí)間、訓(xùn)練/驗(yàn)證評(píng)估分?jǐn)?shù)以及相關(guān)時(shí)間和評(píng)分的統(tǒng)計(jì)信息。
- K折交叉驗(yàn)證可以盡可能地嘗試所有的數(shù)據(jù)集劃分方式,使網(wǎng)格搜索的結(jié)果可信度更高。K折交叉驗(yàn)證取多次結(jié)果的平均值可以避免樣本劃分不合理的情況。
訓(xùn)練最優(yōu)模型
在這一步中,將使用決策樹(shù)算法訓(xùn)練一個(gè)模型。為了得出的是一個(gè)最優(yōu)模型,需要使用網(wǎng)格搜索法訓(xùn)練模型,以找到最佳的 'max_depth' 參數(shù)。可以把'max_depth' 參數(shù)理解為決策樹(shù)算法在做出預(yù)測(cè)前,允許其對(duì)數(shù)據(jù)提出問(wèn)題的數(shù)量。
在下方 fit_model 函數(shù)中,將實(shí)現(xiàn):
將 ‘performance_metric’ 作為參數(shù)傳至這個(gè)函數(shù)中;
第六步. 做出預(yù)測(cè)
當(dāng)我們用數(shù)據(jù)訓(xùn)練出一個(gè)模型,它就可用于對(duì)新的數(shù)據(jù)進(jìn)行預(yù)測(cè)。在我們的例子–決策樹(shù)回歸函數(shù)中,模型已經(jīng)學(xué)會(huì)對(duì)新輸入的數(shù)據(jù)“提問(wèn)”,并返回對(duì)目標(biāo)變量的預(yù)測(cè)值。現(xiàn)在可以用這些預(yù)測(cè)來(lái)獲取未知目標(biāo)變量的數(shù)據(jù)的信息,但是,輸入的新數(shù)據(jù)必須不能是已有訓(xùn)練數(shù)據(jù)之中的。
最優(yōu)模型
下方代碼將決策樹(shù)回歸函數(shù)代入訓(xùn)練數(shù)據(jù)的集合,以得到最優(yōu)化的模型。
# Fit the training data to the model using grid search reg = fit_model(X_train, y_train)# Produce the value for 'max_depth' print("Parameter 'max_depth' is {} for the optimal model.".format(reg.get_params()['max_depth'])) Parameter 'max_depth' is 6 for the optimal model.最終,使用確認(rèn)好的參數(shù)來(lái)對(duì)測(cè)試數(shù)據(jù)進(jìn)行預(yù)測(cè),并來(lái)看看訓(xùn)練結(jié)果如何。
depth = 6 regressor = DecisionTreeRegressor(max_depth = depth) regressor.fit(X_train, y_train) y_pred = regressor.predict(X_test) score = performance_metric(y_test, y_pred) print("The R2 score is ",score) The R2 score is 0.7520017488593774
訓(xùn)練結(jié)果情況:
-
模型的效果并不理想。
-
改進(jìn):1、需要更多的特征來(lái)訓(xùn)練模型;2、數(shù)據(jù)預(yù)處理時(shí),空值的填充用錯(cuò)數(shù)值;3、試試換成線性回歸模型。
總結(jié)
以上是生活随笔為你收集整理的房价预测(基于决策树算法)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: ActiveX控件缺失解决方法
- 下一篇: 说一下zoom:1的原理,万一被问到呢?