歡迎來到預測波士頓房價項目!在此文件中,咱們已經提供了一些示例代碼,但你還須要完善更多功能才能讓項目成功運行。除非有明確要求,你無需修改任何已給出的代碼。習題的標題爲編程練習。每一部分都會有詳細的指導,須要實現的部分也會在註釋中以TODO標出。請仔細閱讀全部的提示!html
除了實現代碼外,你還必須回答一些問題。請仔細閱讀每一個問題,而且在問題後的'回答'文字框中寫出完整的答案。咱們的項目審閱者將會根據你對問題的回答和撰寫代碼所實現的功能來進行評分。python
提示:代碼 和 Markdown單元格 可經過 Shift + Enter 快捷鍵運行。另外,Markdown單元格 能夠經過雙擊進入編輯模式。
在這個項目中,你將使用咱們提供的波士頓房屋信息數據來訓練和測試一個模型,並對模型的性能和預測能力進行評估。咱們但願能夠經過該模型實現對房屋的價值預估,提升房地產經紀人的工做效率。算法
此項目的數據集來自kaggle原始數據,未通過任何處理。該數據集統計了2006年至2010年波士頓我的住宅銷售狀況,包含2900多條觀測數據(其中一半是訓練數據,即咱們的housedata.csv
文件)。更多文檔信息能夠參考做者的文檔(能夠不看),以及項目附件data_description.txt
文件(特徵描述文件,必定要看)。編程
運行下面區域的代碼以載入一些此項目所需的Python庫。若是成功返回提示語句,則說明載入成功。api
# 載入此項目須要的庫 import numpy as np import pandas as pd import visuals as vs # Supplementary code 補充的可視化代碼 import matplotlib.pyplot as plt import seaborn as sns plt.style.use('seaborn') # use seaborn style 使用seaborn風格 import warnings warnings.filterwarnings('ignore') %matplotlib inline print('你已經成功載入全部庫!')
你已經成功載入全部庫!
你的第一個編程練習是加載波士頓房價數據。咱們已爲你導入了 Pandas
,你須要使用這個庫中的read_csv方法來執行必要的過程。數組
導入數據將會是你整個項目的開始dom
若是成功返回數據集的大小,表示數據集已載入成功。機器學習
# 1 TODO:載入波士頓房屋的數據集:使用pandas載入csv,並賦值到data_df data_df = pd.read_csv('housedata.csv') # 成功載入的話輸出訓練數據行列數目 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.
這個部分,你要對已有的波士頓房地產數據進行初步的觀察與處理。同時,經過對數據的探索可讓你更好地理解數據。ide
因爲這個項目的最終目標是創建一個預測房屋價值的模型,咱們須要將數據集分爲特徵(features)和目標變量(target variable)。函數
'SalePrice'
,是咱們但願預測的變量。 'SalePrice'
外的屬性都是特徵,它們反應了數據點在某些方面的表現或性質。你的第二個編程練習是對波士頓房價的數據進行觀察,這一步會讓你掌握更多數據自己的信息。具體問題以下:
問題2.1:使用head方法打印並觀察前7條data_df
數據
# 2.1 TODO: 打印出前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.2:Id特徵對咱們訓練數據沒有任何用處,在data_df
中使用drop方法刪除'Id'
列數據
# 2.2 TODO: 刪除data_df中的Id特徵(保持數據仍在data_df中,不更改變量名) data_df.drop(columns=['Id'], inplace=True)
問題2.3:使用describe方法觀察data_df
各個特徵的統計信息:
# 2.3 TODO: data_df.describe(include=[np.number])
MSSubClass | LotFrontage | LotArea | OverallQual | OverallCond | YearBuilt | YearRemodAdd | MasVnrArea | BsmtFinSF1 | BsmtFinSF2 | ... | WoodDeckSF | OpenPorchSF | EnclosedPorch | 3SsnPorch | ScreenPorch | PoolArea | MiscVal | MoSold | YrSold | SalePrice | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
count | 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 |
mean | 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 |
std | 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 |
min | 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 |
25% | 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% | 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 |
75% | 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 |
max | 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 |
# data_df.info() #查看dataFrame的信息
咱們的數據不多是百分百的‘乾淨’數據(即有用數據),總會在採集整理時有些」失誤「、「冗餘」,形成「髒」數據,因此咱們要從數據的正確性和完整性這兩個方面來清理數據。
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.
建議咱們去掉數據中'GrLivArea'
中超過4000平方英尺的房屋(具體緣由能夠參考文檔),固然本數據集還有其餘的異常點,這裏再也不處理。
問題3.1:正確性
請按下述步驟刪除一些不合理的數據
問題3.1.1:使用matplotlib
庫中的scatter方法 繪製'GrLivArea'
和'SalePrice'
的散點圖,x軸爲'GrLivArea'
,y軸爲'SalePrice'
,觀察數據
# 3.1.1 TODO:繪製要求的圖形 plt.scatter(data_df['GrLivArea'], data_df['SalePrice'], c='blue', marker='.', s=30) plt.xlabel('GrLivArea') plt.ylabel('SalePrice') plt.show()
問題3.1.2:經過上圖咱們能夠看到那幾個異常值,即'GrLivArea'
大於4000,可是'SalePrice'
又極低的數據,從data_df
刪除這幾個異常值,刪除後從新繪製'GrLivArea'
和'SalePrice'
的關係圖,確認異常值已刪除。
# 3.1.2 # TODO:從data_df中刪除 GrLivArea大於4000 且 SalePrice低於300000 的值 index = data_df[(data_df['GrLivArea'] > 4000) & (data_df['SalePrice'] < 300000)].index data_df.drop(index=index, inplace=True) # TODO:從新繪製GrLivArea和SalePrice的關係圖,確認異常值已刪除 plt.scatter(data_df['GrLivArea'], data_df['SalePrice'], c='blue', marker='.', s=50) plt.xlabel('GrLivArea') plt.ylabel('SalePrice') plt.show()
問題3.2:完整性
請按下述步驟,補足數據的完整性
問題3.2.1:篩選出過多空數據的特徵,咱們這個項目定爲篩選出有超過25%爲空數據的特徵
limit_percent = 0.25 limit_value = len(data_df) * limit_percent # 3.2.1 TODO 統計並打印出超過25%的空數據的特徵,你能夠考慮使用isna() list(data_df.columns[data_df.isna().sum() > limit_value])
['Alley', 'FireplaceQu', 'PoolQC', 'Fence', 'MiscFeature']
若是你整理出的特徵是'Alley', 'FireplaceQu', 'PoolQC', 'Fence', 'MiscFeature'
,那就說明你統計對了,接着咱們查看data_description.txt
文件,就會發現,這些並不是必定是空缺數據,而沒有游泳池,籬笆等也會用NA來表示,那麼就不須要刪除這些特徵了,而是用None
來填充NA
數據。
問題3.2.2:根據data_description.txt
特徵描述,使用fillna方法填充空數據,具體哪種數據須要填充什麼已經整理好了,請按提示要求來進行填充
# 直接運行不用修改 # 肯定全部空特徵 missing_columns = list(data_df.columns[data_df.isnull().sum() != 0]) # 肯定哪些是類別特徵,哪些是數值特徵 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']
data_df.mode() # 取衆數,返回DataFrame
MSSubClass | MSZoning | LotFrontage | LotArea | Street | Alley | LotShape | LandContour | Utilities | LotConfig | ... | PoolArea | PoolQC | Fence | MiscFeature | MiscVal | MoSold | YrSold | SaleType | SaleCondition | SalePrice | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 20.0 | RL | 60.0 | 7200.0 | Pave | Grvl | Reg | Lvl | AllPub | Inside | ... | 0.0 | Ex | MnPrv | Shed | 0.0 | 6.0 | 2009.0 | WD | Normal | 140000.0 |
1 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | Fa | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
2 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | Gd | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
# 須要填充衆數的特徵 fill_Mode = ['Electrical'] # 須要填充None的特徵 fill_None = ['Alley', 'MasVnrType', 'BsmtQual', 'BsmtCond', 'BsmtExposure', 'BsmtFinType1', 'BsmtFinType2', 'FireplaceQu', 'GarageType', 'GarageFinish', 'GarageQual', 'GarageCond', 'PoolQC', 'Fence', 'MiscFeature'] # 須要填充0的特徵 fill_0 = ['GarageYrBlt'] # 須要填充中位數的特徵 fill_median = ['LotFrontage', 'MasVnrArea'] # 3.4.1 TODO:按需填補上面數據 # 個人實現: # # 填充衆數: # mode = data_df[fill_Mode].mode().iloc[0,0] # data_df.fillna(value={fill_Mode[0]: mode}, inplace=True) # # 填充None: # d_None={} # for i in fill_None: # d_None[i] = 'None' # data_df.fillna(value=d_None, inplace=True) # # 填充0: # data_df[fill_0].fillna(value=0, inplace=True) # # 填充中位數: # data_df[fill_median].fillna(data_df[fill_median].median(), inplace=True) # 簡化實現: 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].median()) # 驗證 # data_df.isna().sum()
有這麼一句話在業界普遍流傳:特徵數據決定了機器學習的上限,而模型和算法只是逼近這個上限而已。特徵工程,是整個數據分析過程當中不可缺乏的一個環節,其結果質量直接關係到模型效果和最終結論。從上面兩步中咱們獲得了「乾淨」的數據,可是data_df
總共有81個特徵,咱們應當剔除那些可有可無的特徵(噪聲),使用真正關鍵的特徵來進行模型訓練。如今須要咱們對這些龐大的數據進行分析,提取出與目標最爲關聯的數據。
問題4.1:繪製'SalePrice'
的直方圖,並說明該直方圖屬於什麼分佈
# 4.1 TODO:繪製要求的圖形 # plt.hist(data_df['SalePrice'], bins=50, normed=False, color=None) # plt.xlabel('SalePrice') # plt.show() data_df['SalePrice'].hist(bins=50)
<matplotlib.axes._subplots.AxesSubplot at 0x22186a3e7b8>
回答問題4.1:'SalePrice'
屬於 正偏態 分佈
import scipy scipy.stats.skew(data_df['SalePrice'])
1.8793604459195012
結果>0,表明正偏,從計算上也說明了'SalePrice'屬於正偏態分佈。
若是特徵極其多,很難清晰的看到特徵與目標變量之間的關係,就須要利用統計知識來進行多變量分析了。咱們常使用熱圖heatmap結合corr方法來進行客觀分析,熱圖Heatmap能夠用顏色變化來反映變量之間的相關性二維矩陣或說相關性表格中的數據信息,它能夠直觀地將數據值的大小以定義的顏色深淺表示出來。這個項目,爲了簡化訓練,咱們以相關性絕對值大於0.5爲界來選取咱們須要的特徵。
# 不用修改直接運行 corrmat = data_df.corr().abs() #計算連續型特徵之間的相關係數 #將於SalePrice的相關係數大於5的特徵取出來,並按照SalePrice降序排列,而後取出對應的特徵名,保存在列表中 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]
咱們已經從龐大的特徵羣中篩選出了最相關的特徵,也瞭解了咱們目標數據的分佈,那麼接下來,咱們從創造性方面來對咱們的特徵進行「改造」。
由於咱們篩選出來的特徵都爲數值類型特徵,因此咱們只作標準化的操做:這個項目是一個迴歸類型的項目,而咱們的迴歸算法對標準正態分步預測較爲準確,從咱們的目標數據能夠看出數據是一個偏態分佈,那麼咱們使用log將數據從偏態分佈轉換爲標準正態分佈,最後進行標準化。
# 不要修改,直接運行 from scipy.special import boxcox1p from sklearn.preprocessing import StandardScaler data_df['SalePrice'] = np.log1p(data_df['SalePrice']) # np.log1p()函數將數據從偏態分佈轉換成標準正態分佈 numeric_features = list(data_df.columns) numeric_features.remove('SalePrice') for feature in numeric_features: #all_data[feat] += 1 data_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])
筆記:
在項目的第三步中,你須要瞭解必要的工具和技巧來讓你的模型可以進行預測。用這些工具和技巧對每個模型的表現作精確的衡量能夠極大地加強你預測的可信度。
若是不能對模型的訓練和測試的表現進行量化地評估,咱們就很難衡量模型的好壞。一般咱們會定義一些衡量標準,這些標準能夠經過對某些偏差或者擬合程度的計算來獲得。在這個項目中,你將經過運算決定係數 $R^2$ 來量化模型的表現。模型的決定係數是迴歸分析中十分經常使用的統計信息,常常被看成衡量模型預測能力好壞的標準。
$R^2$ 的數值範圍從0至1,表示目標變量的預測值和實際值之間的相關程度平方的百分比。一個模型的 $R^2$ 值爲0還不如直接用平均值來預測效果好;而一個 $R^2$ 值爲1的模型則能夠對目標變量進行完美的預測。從0至1之間的數值,則表示該模型中目標變量中有百分之多少可以用特徵來解釋。模型也可能出現負值的 $R^2$,這種狀況下模型所作預測有時會比直接計算目標變量的平均值差不少。
問題5.1:
在下方代碼的 performance_metric
函數中,你要實現:
sklearn.metrics
中的 r2_score
來計算 y_true
和 y_predict
的 $R^2$ 值,做爲對其表現的評判。score
變量中。# 5.1 TODO: 引入 'r2_score' from sklearn.metrics import r2_score def performance_metric(y_true, y_predict): """ Calculates and returns the performance score between true and predicted values based on the metric chosen. """ # TODO: 計算 'y_true' 與 'y_predict' 的r2值 score = r2_score(y_true, y_predict) # 返回這一分數 return score
筆記:
R^2是評價模型表現的方法之一,每一個機器學習模型的創建都要有相對應的評價指標,後面咱們會學到更多的評價指標。不過R^2其實也有不少侷限性須要注意 https://en.wikipedia.org/wiki...
skearn對於常見的模型表現衡量方法也有詳細的介紹。
http://scikit-learn.org/stabl...
問題 5.2:擬合程度
假設一個數據集有五個數據且某一模型作出下列目標變量的預測:
真實數值 | 預測數值 |
---|---|
3.0 | 2.5 |
-0.5 | 0.0 |
2.0 | 2.1 |
7.0 | 7.8 |
4.2 | 5.3 |
你以爲這個模型已成功地描述了目標變量的變化嗎?若是成功,請解釋爲何,若是沒有,也請給出緣由。
提示1:運行下方的代碼,使用 performance_metric
函數來計算 y_true
和 y_predict
的決定係數。
提示2:$R^2$ 分數是指能夠從自變量中預測的因變量的方差比例。 換一種說法:
#TODO 5.2:計算這一模型的表現 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.
問題 5.2 - 回答:模型能夠描述目標變量的變化,由於R^2值爲0.923,說明自變量(預測數值)對因變量(真實數值)的解釋越好。
接下來,你須要分割波士頓房屋數據集,包括特徵與目標變量、訓練集和測試集。一般在這個過程當中,數據也會被重排,以消除數據集中因爲順序而產生的誤差。
在下面的代碼中,你須要
問題6.1:將data_df
分割爲特徵和目標變量
# TODO: 6.1 labels = data_df['SalePrice']#TODO:提取SalePrice做爲labels features = data_df.drop(['SalePrice'], axis=1)#TODO:提取除了SalePrice之外的特徵賦值爲features
問題6.2 :
使用 sklearn.model_selection
中的 train_test_split
, 將 features
和 prices
的數據都分紅用於訓練的數據子集和用於測試的數據子集。
train_test_split
中的 random_state
,這會確保結果的一致性;X_train
, X_test
, y_train
和 y_test
。# TODO: 引入 'train_test_split' from sklearn.model_selection import train_test_split # TODO: 打亂並分割訓練集與測試集 X_train, X_test, y_train, y_test = train_test_split(features, labels, test_size=0.2, random_state=1) # 成功~ print("Training and testing split was successful.")
Training and testing split was successful.
問題 6.3 - 訓練及測試
將數據集按必定比例分爲訓練用的數據集和測試用的數據集對學習算法有什麼好處?
若是用模型已經見過的數據,例如部分訓練集數據進行測試,又有什麼壞處?
提示: 若是沒有數據來對模型進行測試,會出現什麼問題?
問題 6.3 - 回答:
在項目的第四步,咱們來觀察不一樣參數下,模型在訓練集和驗證集上的表現。這裏,咱們專一於一個特定的算法(帶剪枝的決策樹DecisionTreeRegressor
,但這並非這個項目的重點)和這個算法的一個參數 'max_depth'
。用所有訓練集訓練,選擇不一樣'max_depth'
參數,觀察這一參數的變化如何影響模型的表現。畫出模型的表現來對於分析過程十分有益。
下方區域內的代碼會輸出四幅圖像,它們是一個決策樹模型在不一樣最大深度下的表現。每一條曲線都直觀得顯示了隨着訓練數據量的增長,模型學習曲線在訓練集評分和驗證集評分的變化,評分使用決定係數 $R^2$。曲線的陰影區域表明的是該曲線的不肯定性(用標準差衡量)。
運行下方區域中的代碼,並利用輸出的圖形回答下面的問題。
# Produce learning curves for varying training set sizes and maximum depths vs.ModelLearning(features, labels)
提示:學習曲線的評分是否最終會收斂到特定的值?通常來講,你擁有的數據越多,模型表現力越好。可是,若是你的訓練和測試曲線以高於基準閾值的分數收斂,這是否有必要?基於訓練和測試曲線已經收斂的前提下,思考添加更多訓練點的優缺點。
問題 7 - 回答:當max_depth爲3時,隨着訓練數據的增長,訓練集曲線的評分下降,驗證集曲線的評分提升,可是二者會收斂到一特定數值,隨着訓練數據的增長,模型表現再也不提升,此時沒有必要再繼續增長訓練數據,由於會增長模型的訓練時間。可是,若是在過擬合的狀況下,比方說當max_depth爲6或者10時,隨着訓練數據的增長,模型表現也不斷提升,此時反而有必要增長訓練數據。
筆記:
對訓練曲線和測試曲線趨勢和意義解釋的很好。這裏隨着數據的增多,max_depth不變的狀況下,模型提高的幅度也愈來愈小。
傳統的機器學習算法(又被稱爲基於統計的機器學習)在數據量達到必定程度後,更多的數據沒法提高模型的表現。深度學習的一個優點就是它能夠把大量的數據利用起來,提高學習表現。
這裏還有更多關於學習曲線的介紹:
https://www.coursera.org/lear...
http://scikit-learn.org/stabl...
傳統的機器學習算法(又被稱爲基於統計的機器學習)在數據量達到必定程度後,更多的數據沒法提高模型的表現。深度學習的一個優點就是它能夠把大量的數據利用起來,提高學習表現。
這裏還有更多關於學習曲線的介紹:
https://www.coursera.org/lear...
http://scikit-learn.org/stabl...
下列代碼內的區域會輸出一幅圖像,它展現了一個已經通過訓練和驗證的決策樹模型在不一樣最大深度條件下的表現。這個圖形將包含兩條曲線,一個是訓練集的變化,一個是驗證集的變化。跟學習曲線類似,陰影區域表明該曲線的不肯定性,模型訓練和測試部分的評分都用的 performance_metric
函數。
運行下方區域中的代碼,根據問題5與問題6對輸出的圖形進行分析並給出你思考的結果。
vs.ModelComplexity(X_train, y_train)
提示: 高誤差表示欠擬合(模型過於簡單),而高方差表示過擬合(模型過於複雜,以致於沒法泛化)。考慮哪一種模型(深度1或10)對應着上述的狀況,並權衡誤差與方差。
問題 8 - 回答:當max_depth爲1時,模型表現出高誤差,由於訓練集和測試集的R2分數都比較低;當max_depth爲10時,模型表現出高方差,由於訓練集的R2分數較高,而驗證集的R2分數較低。
筆記:
誤差-方差分解是解釋學習算法泛化性能的重要工具。這裏你須要理解三個方面:
什麼是泛化偏差(Generalization error):
Bias-Variance分解:
Bias-Variance trade-off:
通常狀況下,誤差和方差是有衝突的,以下圖所示。爲了取得好的泛化性能,則須要誤差較小,即可以充分擬合數據,而且方差較小,即便得數據擾動產生的影響小。
更多內容請閱讀參考資料。
參考資料:
[1] «機器學習», 周志華, 2.5 節誤差與方差.
[2] Understanding the Bias-Variance Tradeoff
提示:查看問題8上方的圖表,並查看模型在不一樣 depth
下的驗證分數。隨着深度的增長模型的表現力會變得更好嗎?咱們在什麼狀況下得到最佳驗證分數而不會使咱們的模型過分複雜?請記住,奧卡姆剃刀:「在競爭性假設中,應該選擇假設最少的那一個。」
問題 9 - 回答:
在項目的最後一節中,你將構建一個模型,並使用 fit_model
中的優化模型去預測客戶特徵集。
提示:在解釋網格搜索算法時,首先要理解咱們爲何使用網格搜索算法,以及咱們使用它的最終目的是什麼。爲了使你的回答更具備說服力,你還能夠給出一個模型中可使用此方法進行優化參數的示例。
問題 10 - 回答: 網格搜索法是給定參數值,窮舉搜索尋找最優參數的算法。網格搜索法經過構建一個參數的字典,創造出不一樣的參數組合,輸入給分類器進行訓練,採用交叉驗證,尋找驗證分數最高的那一組參數,這一組參數就是模型的最優參數。
'cv_results_'
屬性能告訴咱們什麼?提示:在解釋k-fold交叉驗證時,必定要理解'k'是什麼,和數據集是如何分紅不一樣的部分來進行訓練和測試的,以及基於'k'值運行的次數。
在考慮k-fold交叉驗證如何幫助網格搜索時,你可使用特定的數據子集來進行訓練與測試有什麼缺點,以及K折交叉驗證是如何幫助緩解這個問題。
問題 11 - 回答:
在這個練習中,你將須要將所學到的內容整合,使用決策樹算法訓練一個模型。爲了得出的是一個最優模型,你須要使用網格搜索法訓練模型,以找到最佳的 'max_depth'
參數。你能夠把'max_depth'
參數理解爲決策樹算法在作出預測前,容許其對數據提出問題的數量。決策樹是監督學習算法中的一種。
在下方 fit_model
函數中,你須要作的是:
'cross_validator'
變量: 使用 sklearn.model_selection
中的 KFold
建立一個交叉驗證生成器對象;'regressor'
變量: 使用 sklearn.tree
中的 DecisionTreeRegressor
建立一個決策樹的迴歸函數;'params'
變量: 爲 'max_depth'
參數創造一個字典,它的值是從1至10的數組;'scoring_fnc'
變量: 使用 sklearn.metrics
中的 make_scorer
建立一個評分函數;‘performance_metric’
做爲參數傳至這個函數中;'grid'
變量: 使用 sklearn.model_selection
中的 GridSearchCV
建立一個網格搜索對象;將變量'regressor'
, 'params'
, 'scoring_fnc'
和 'cross_validator'
做爲參數傳至這個對象構造函數中;若是你對python函數的默認參數定義和傳遞不熟悉,能夠參考這個MIT課程的視頻。
# TODO: Import 'make_scorer', 'DecisionTreeRegressor', and 'GridSearchCV' from sklearn.model_selection import KFold from sklearn.tree import DecisionTreeRegressor from sklearn.metrics import make_scorer from sklearn.model_selection import GridSearchCV def fit_model(X, y): """ Performs grid search over the 'max_depth' parameter for a decision tree regressor trained on the input data [X, y]. """ cross_validator = KFold(n_splits=10) # TODO: Create a decision tree regressor object regressor = DecisionTreeRegressor(random_state=1) # TODO: Create a dictionary for the parameter 'max_depth' with a range from 1 to 10 params = {'max_depth':[i for i in range(1, 11)]} # TODO: Transform 'performance_metric' into a scoring function using 'make_scorer' scoring_fnc = make_scorer(performance_metric) # TODO: Create the grid search cv object --> GridSearchCV() # Make sure to include the right parameters in the object: # (estimator, param_grid, scoring, cv) which have values 'regressor', 'params', 'scoring_fnc', and 'cross_validator' respectively. grid = GridSearchCV(regressor, params, scoring_fnc, cv = cross_validator) # Fit the grid search object to the data to compute the optimal model grid = grid.fit(X, y) # Return the optimal model after fitting the data return grid.best_estimator_
當咱們用數據訓練出一個模型,它就可用於對新的數據進行預測。在咱們的例子--決策樹迴歸函數中,模型已經學會對新輸入的數據「提問」,並返回對目標變量的預測值。你能夠用這些預測來獲取未知目標變量的數據的信息,可是,輸入的新數據必須不能是已有訓練數據之中的。
最優模型的最大深度(maximum depth)是多少?此答案與你在問題 9所作的猜想是否相同?
運行下方區域內的代碼,將決策樹迴歸函數代入訓練數據的集合,以獲得最優化的模型。
# 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 5 for the optimal model.
最終,使用咱們確認好的參數來對測試數據進行預測,完成下面的問題,來看看咱們的訓練結果如何吧
問題12.1:填入上題所確認的最優參數,查看測試結果
depth = 5 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.7520883029841192
問題12.2:你剛剛計算了最優模型在測試集上的決定係數,你會如何評價這個結果?還有什麼地方能夠改進,以提高這一分數呢?
回答問題12.2:這個結果並非理想的,應該還須要利用決策樹的其餘參數進行網格搜索,以及使用更多的特徵;