【机器学习】完整的机器学习项目演练:第一部分
把機(jī)器學(xué)習(xí)拼接起來
通過閱讀數(shù)據(jù)科學(xué)書籍或參加課程,可以感覺到你有各自的作品,但不太知道如何將它們組合在一起。采取下一步并解決完整的機(jī)器學(xué)習(xí)問題可能令人生畏,但保留和完成第一個項(xiàng)目將使您有信心解決任何數(shù)據(jù)科學(xué)問題。本系列文章將介紹一個包含真實(shí)數(shù)據(jù)集的完整機(jī)器學(xué)習(xí)解決方案,讓您了解所有部分是如何組合在一起的。
我們將按照一般的機(jī)器學(xué)習(xí)工作流程逐步進(jìn)行:
在此過程中,我們將看到每個步驟如何流入下一步以及如何在Python中專門實(shí)現(xiàn)每個部分。該完整的項(xiàng)目可在GitHub上,與這里的部分的jupyter notebook。第一篇文章將介紹步驟1-3,其余內(nèi)容將在后續(xù)文章中介紹。
(作為一個說明,這個問題最初是作為啟動時作業(yè)屏幕的“任務(wù)”給我的。完成工作后,我得到了工作,但公司的首席技術(shù)官辭職了,他們不是'能夠引進(jìn)任何新員工。我想這就是啟動現(xiàn)場的情況!)
?
問題定義
我們編寫代碼之前的第一步是了解我們要解決的問題和可用數(shù)據(jù)。在這個項(xiàng)目中,我們將使用紐約市公開提供的建筑能源數(shù)據(jù)。
目標(biāo)是使用能源數(shù)據(jù)建立一個模型,該模型可以預(yù)測建筑物的能源之星得分并解釋結(jié)果以找出影響得分的因素。
這些數(shù)據(jù)包括能源之星得分,這使其成為受監(jiān)督的回歸機(jī)器學(xué)習(xí)任務(wù):
- 監(jiān)督:我們可以訪問功能和目標(biāo),我們的目標(biāo)是培訓(xùn)可以學(xué)習(xí)兩者之間映射的模型
- 回歸:能源之星得分是一個連續(xù)變量
我們希望開發(fā)一個既準(zhǔn)確?的模型- 它可以預(yù)測接近真實(shí)值的能源之星分?jǐn)?shù) - 并且可以解釋??- 我們可以理解模型預(yù)測。一旦我們了解了目標(biāo),我們就可以在我們深入研究數(shù)據(jù)和構(gòu)建模型時使用它來指導(dǎo)我們的決策。
?
數(shù)據(jù)清理
與您認(rèn)為的大多數(shù)數(shù)據(jù)科學(xué)課程相反,并非每個數(shù)據(jù)集都是完美策劃的觀察組,沒有缺失值或異常(查看您的mtcars和虹膜數(shù)據(jù)集)。現(xiàn)實(shí)世界的數(shù)據(jù)很混亂,這意味著我們需要在可以開始分析之前將其清理并加工成可接受的格式。數(shù)據(jù)清理是大多數(shù)實(shí)際數(shù)據(jù)科學(xué)問題的一個非常迷人但必不可少的部分。
首先,我們可以將數(shù)據(jù)加載為Pandas?DataFrame并查看:
import pandas as pd import numpy as np # Read in data into a dataframe data = pd.read_csv('data/Energy_and_Water_Data_Disclosure_for_Local_Law_84_2017__Data_for_Calendar_Year_2016_.csv') # Display top of dataframe data.head()?
這是包含60列的完整數(shù)據(jù)的子集。我們已經(jīng)看到了幾個問題:首先,我們知道我們想要預(yù)測,ENERGY STAR Score但我們不知道任何列的含義。雖然這不一定是一個問題 - 我們通??梢栽诓涣私庾兞康那闆r下制作精確的模型 - 我們希望專注于可解釋性,并且至少理解一些列可能很重要。
當(dāng)我最初從初創(chuàng)公司獲得任務(wù)時,我不想問所有列名稱的含義,所以我查看了文件的名稱,
并決定尋找“地方法84”。這導(dǎo)致我進(jìn)入這個頁面,解釋這是紐約市法律要求所有規(guī)模的建筑物報(bào)告他們的能源使用情況。更多的搜索讓我了解了列的所有定義。也許看一個文件名是一個顯而易見的起點(diǎn),但對我來說,這是一個緩慢的提示,所以你不要錯過任何重要的東西!
我們不需要研究所有列,但我們至少應(yīng)該了解能源之星得分,其描述如下:
基于報(bào)告年度自我報(bào)告的能源使用情況的1到100百分位排名。在能源之星的分?jǐn)?shù)是用于比較建筑物的能源效率的相對度量。
這清除了第一個問題,但第二個問題是缺失值被編碼為“不可用”。這是Python中的一個字符串,這意味著即使帶有數(shù)字的列也將存儲為object數(shù)據(jù)類型,因?yàn)镻andas會將包含任何字符串的列轉(zhuǎn)換為所有字符串的列。我們可以使用以下dataframe.info()方法查看列的數(shù)據(jù)類型:
# 查看列數(shù)據(jù)類型和非缺失值 data.info()果然,一些明顯包含數(shù)字(例如ft2)的列存儲為對象。我們不能對字符串進(jìn)行數(shù)值分析,因此必須將它們轉(zhuǎn)換為數(shù)字(特定float)數(shù)據(jù)類型!
這里有一個Python代碼,用于替換所有“Not Available”條目而不是number(np.nan),可以將其解釋為數(shù)字,然后將相關(guān)列轉(zhuǎn)換為float數(shù)據(jù)類型:
# 將所有不可用的numpy替換為numpy而不是數(shù)字 data = data.replace({'Not Available': np.nan})# 遍歷列 for col in list(data.columns):# 選擇應(yīng)為數(shù)字的列if ('ft2' in col or 'kBtu' in col or 'Metric Tons CO2e' in col or 'kWh' in col or 'therms' in col or 'gal' in col or 'Score' in col):# 將數(shù)據(jù)類型轉(zhuǎn)換為floatdata[col] = data[col].astype(float)一旦正確的列是數(shù)字,我們就可以開始調(diào)查數(shù)據(jù)了。
?
缺少數(shù)據(jù)和異常值
除了不正確的數(shù)據(jù)類型之外,處理實(shí)際數(shù)據(jù)時的另一個常見問題是缺少值。這些可能由于許多原因而產(chǎn)生,并且必須在我們訓(xùn)練機(jī)器學(xué)習(xí)模型之前填寫或移除。首先,讓我們了解每列中有多少缺失值(請參閱筆記本中的代碼)。
(為了創(chuàng)建這個表,我使用了這個Stack Overflow論壇中的一個函數(shù))。
雖然我們總是要小心刪除信息,但如果列的缺失值百分比很高,那么它對我們的模型可能沒用。刪除列的閾值應(yīng)該取決于問題(這是一個討論),對于這個項(xiàng)目,我們將刪除任何缺失值超過50%的列。
此時,我們可能還想刪除異常值。這可能是由于數(shù)據(jù)輸入中的拼寫錯誤,單位錯誤,或者它們可能是合法的但是極端值。對于這個項(xiàng)目,我們將根據(jù)極端異常值的定義刪除異常:
- 低于第一個四分位數(shù)--3 *四分位數(shù)范圍
- 高于第三個四分位數(shù)+3 *四分位數(shù)范圍
(有關(guān)刪除列和異常的代碼,請參閱筆記本)。在數(shù)據(jù)清理和異常刪除過程結(jié)束時,我們留下了超過11,000個建筑物和49個功能。
?
探索性數(shù)據(jù)分析
既然數(shù)據(jù)清理的繁瑣但必要的步驟已經(jīng)完成,我們可以繼續(xù)探索我們的數(shù)據(jù)!探索性數(shù)據(jù)分析(EDA)是一個開放式過程,我們計(jì)算統(tǒng)計(jì)數(shù)據(jù)并制作數(shù)據(jù)以查找數(shù)據(jù)中的趨勢,異常,模式或關(guān)系。
簡而言之,EDA的目標(biāo)是了解我們的數(shù)據(jù)可以告訴我們什么。它通常以高級概述開始,然后在我們找到有趣的數(shù)據(jù)部分時縮小到特定區(qū)域。這些發(fā)現(xiàn)本身可能很有趣,或者它們可以用來告知我們的建模選擇,例如幫助我們決定使用哪些功能。
單變量圖
目標(biāo)是預(yù)測能源之星得分(score在我們的數(shù)據(jù)中重命名),因此合理的起點(diǎn)是檢查此變量的分布。直方圖是一種簡單而有效的方法,可視化單個變量的分布,并且易于使用matplotlib。
import matplotlib.pyplot as plt # Histogram of the Energy Star Score plt.style.use('fivethirtyeight') plt.hist(data['score'].dropna(), bins = 100, edgecolor = 'k'); plt.xlabel('Score'); plt.ylabel('Number of Buildings'); plt.title('Energy Star Score Distribution');這看起來很可疑!能源之星得分是百分位數(shù),這意味著我們期望看到均勻分布,每個得分分配給相同數(shù)量的建筑物。然而,不成比例的建筑物具有最高,100或最低1的分?jǐn)?shù)(能量之星得分越高越好)。
如果我們回到分?jǐn)?shù)的定義,我們會發(fā)現(xiàn)它基于“自我報(bào)告的能量使用”,這可能解釋了非常高的分?jǐn)?shù)。要求建筑物業(yè)主報(bào)告他們自己的能源使用情況就像要求學(xué)生在測試中報(bào)告他們自己的分?jǐn)?shù)一樣!因此,這可能不是建筑物能效的最客觀衡量標(biāo)準(zhǔn)。
如果我們有無限的時間,我們可能想調(diào)查為什么這么多建筑物的分?jǐn)?shù)非常高而且非常低,我們可以通過選擇這些建筑物并看到它們的共同點(diǎn)。但是,我們的目標(biāo)只是預(yù)測得分,而不是設(shè)計(jì)更好的建筑物評分方法!我們可以在報(bào)告中記下分?jǐn)?shù)有可疑分布,但我們主要關(guān)注的是預(yù)測分?jǐn)?shù)。
?
尋找關(guān)系
EDA的一個主要部分是搜索特征和目標(biāo)之間的關(guān)系。與目標(biāo)相關(guān)的變量對模型很有用,因?yàn)樗鼈兛捎糜陬A(yù)測目標(biāo)。檢查目標(biāo)上的分類變量(僅接受有限的一組值)的影響的一種方法是使用seaborn庫的密度圖。
甲密度圖可以被看作是一個平滑的直方圖,因?yàn)樗境隽藛蝹€變量的分布。我們可以按類別對密度圖進(jìn)行著色,以查看分類變量如何改變分布。以下代碼根據(jù)建筑物的類型繪制能源之星得分的密度圖(僅限于具有超過100個數(shù)據(jù)點(diǎn)的建筑類型):
# 創(chuàng)建超過100個測量值的建筑物列表 types = data.dropna(subset=['score']) types = types['Largest Property Use Type'].value_counts() types = list(types[types.values > 100].index)# 建筑類別分?jǐn)?shù)分布圖 figsize(12, 10)# 繪制每個建筑物 for b_type in types:# 選擇建筑類型subset = data[data['Largest Property Use Type'] == b_type]# 密度能源之星成績的plotsns.kdeplot(subset['score'].dropna(),label = b_type, shade = False, alpha = 0.8);# label the plot plt.xlabel('Energy Star Score', size = 20); plt.ylabel('Density', size = 20); plt.title('Density Plot of Energy Star Scores by Building Type', size = 28);我們可以看到建筑類型對能源之星得分有重大影響。辦公樓往往得分較高,而酒店得分較低。這告訴我們,我們應(yīng)該在建模中包含建筑類型,因?yàn)樗_實(shí)會對目標(biāo)產(chǎn)生影響。作為一個分類變量,我們將不得不對建筑類型進(jìn)行單熱編碼。
類似的情節(jié)可以用來顯示自治市鎮(zhèn)的能源之星得分:
?
自治市鎮(zhèn)的建筑類型似乎沒有那么大的影響。盡管如此,我們可能希望將其包含在我們的模型中,因?yàn)樽灾问墟?zhèn)之間存在細(xì)微差別。
為了量化變量之間的關(guān)系,我們可以使用Pearson Correlation Coefficient。這是兩個變量之間線性關(guān)系的強(qiáng)度和方向的度量。得分+1是完全線性正關(guān)系,得分-1是完全負(fù)線性關(guān)系。相關(guān)系數(shù)的幾個值如下所示:
?
雖然相關(guān)系數(shù)無法捕獲非線性關(guān)系,但它是一種開始計(jì)算變量如何相關(guān)的好方法。在Pandas中,我們可以輕松計(jì)算數(shù)據(jù)幀中任何列之間的相關(guān)性:
#查找與分?jǐn)?shù)的所有相關(guān)性并排序 correlations_data = data.corr()['score'].sort_values()與目標(biāo)的最負(fù)(左)和正(右)相關(guān):
特征與目標(biāo)之間存在若干強(qiáng)烈的負(fù)相關(guān),而不同類別的EUI最為負(fù)(這些指標(biāo)在計(jì)算方式上略有不同)。該EUI -能源使用強(qiáng)度??-是能量通過一座由建筑物的面積有多大劃分的使用量。它旨在衡量建筑物的效率,評分越低越好。直覺上,這些相關(guān)性是有意義的:隨著EUI的增加,能源之星得分趨于下降。
?
雙變量圖
為了可視化兩個連續(xù)變量之間的關(guān)系,我們使用散點(diǎn)圖。我們可以在點(diǎn)的顏色中包含其他信息,例如分類變量。例如,下圖顯示了建筑類型所著色的能源之星得分與場地EUI:
該圖使我們可以看到-0.7的相關(guān)系數(shù)是什么樣的。隨著場地EUI減少,能源之星得分增加,這種關(guān)系在建筑類型中保持穩(wěn)定。
我們將要做的最終探索性情節(jié)被稱為Pairs Plot。這是一個很好的探索工具,因?yàn)樗梢宰屛覀兛吹蕉鄬ψ兞恐g的關(guān)系以及單個變量的分布。在這里,我們使用seaborn可視化庫和PairGrid函數(shù)來創(chuàng)建一個對上圖,上面的三角形上有散點(diǎn)圖,對角線上的直方圖和下三角形上的2D核密度圖和相關(guān)系數(shù)。
# 提取要繪制的列 plot_data = features[['score', 'Site EUI (kBtu/ft2)', 'Weather Normalized Source EUI (kBtu/ft2)', 'log_Total GHG Emissions (Metric Tons CO2e)']]# 用nan替換inf plot_data = plot_data.replace({np.inf: np.nan, -np.inf: np.nan})# 重命名列 plot_data = plot_data.rename(columns = {'Site EUI (kBtu/ft2)': 'Site EUI', 'Weather Normalized Source EUI (kBtu/ft2)': 'Weather Norm EUI','log_Total GHG Emissions (Metric Tons CO2e)': 'log GHG Emissions'})# 刪除na值 plot_data = plot_data.dropna()# 功能計(jì)算兩列之間的相關(guān)系數(shù) def corr_func(x, y, **kwargs):r = np.corrcoef(x, y)[0][1]ax = plt.gca()ax.annotate("r = {:.2f}".format(r),xy=(.2, .8), xycoords=ax.transAxes,size = 20)# 創(chuàng)建pairgrid對象 grid = sns.PairGrid(data = plot_data, size = 3)# 上是一個散點(diǎn)圖 grid.map_upper(plt.scatter, color = 'red', alpha = 0.6)# 對角線是直方圖 grid.map_diag(plt.hist, color = 'red', edgecolor = 'black')# 下方是相關(guān)性和密度圖 grid.map_lower(corr_func); grid.map_lower(sns.kdeplot, cmap = plt.cm.Reds)# Title for entire plot plt.suptitle('Pairs Plot of Energy Data', size = 36, y = 1.02);?
要查看變量之間的交互,我們會查找行與列相交的位置。例如,要查看Weather Norm EUIwith?的相關(guān)性score,我們查看Weather Norm EUI行和score列,并查看相關(guān)系數(shù)-0.67。除了看起來很酷,這些圖可以幫助我們決定在建模中包含哪些變量。
?
特征工程與選擇
特征工程和選擇通常可以為機(jī)器學(xué)習(xí)問題提供最大的時間回報(bào)。首先,讓我們來定義這兩個任務(wù)是什么:
- 特征工程:獲取原始數(shù)據(jù)并提取或創(chuàng)建新特征的過程。這可能意味著轉(zhuǎn)換變量,例如自然日志和平方根,或者單熱編碼分類變量,以便可以在模型中使用它們。通常,我認(rèn)為特征工程是從原始數(shù)據(jù)創(chuàng)建其他功能。
- 特征選擇:選擇數(shù)據(jù)中最相關(guān)特征的過程。在特征選擇中,我們刪除了一些功能,以幫助模型更好地概括新數(shù)據(jù)并創(chuàng)建更具可解釋性的模型。一般來說,我認(rèn)為特征選擇是減去特征,所以我們只留下最重要的特征。
機(jī)器學(xué)習(xí)模型只能從我們提供的數(shù)據(jù)中學(xué)習(xí),因此確保數(shù)據(jù)包含我們?nèi)蝿?wù)的所有相關(guān)信息至關(guān)重要。如果我們不為模型提供正確的數(shù)據(jù),那么我們將其設(shè)置為失敗,我們不應(yīng)期望它能夠?qū)W習(xí)!
對于此項(xiàng)目,我們將采取以下功能工程步驟:
- 單熱編碼分類變量(自治市鎮(zhèn)和財(cái)產(chǎn)使用類型)
- 添加數(shù)值變量的自然對數(shù)變換
在模型中包含分類變量需要單熱編碼。機(jī)器學(xué)習(xí)算法無法理解建筑類型的“辦公室”,因此如果建筑物是辦公室,我們必須將其記錄為1,否則記錄為0。
添加變換特征可以幫助我們的模型學(xué)習(xí)數(shù)據(jù)中的非線性關(guān)系。采用平方根,自然對數(shù)或各種特征的權(quán)力是數(shù)據(jù)科學(xué)中的常見做法,可以基于領(lǐng)域知識或在實(shí)踐中最有效的方法。這里我們將包括所有數(shù)字特征的自然對數(shù)。
以下代碼選擇數(shù)字要素,對這些要素進(jìn)行日志轉(zhuǎn)換,選擇兩個分類要素,對這些要素進(jìn)行一次熱編碼,并將這兩個要素連接在一起。這似乎很多工作,但它在熊貓中相對簡單!
# 復(fù)制原始數(shù)據(jù) features = data.copy()# 選擇數(shù)字列 numeric_subset = data.select_dtypes('number')# 創(chuàng)建包含數(shù)字列日志的列 for col in numeric_subset.columns:# 跳過能源之星得分列if col == 'score':nextelse:numeric_subset['log_' + col] = np.log(numeric_subset[col])# 選擇分類列 categorical_subset = data[['Borough', 'Largest Property Use Type']]# 一個熱編碼 categorical_subset = pd.get_dummies(categorical_subset)# 使用concat加入兩個數(shù)據(jù)幀 # 確保使用axis = 1來執(zhí)行列綁定 features = pd.concat([numeric_subset, categorical_subset], axis = 1)在此過程之后,我們擁有超過11,000個具有110列(特征)的觀測(建筑物)。并非所有這些功能都可能對預(yù)測能源之星得分有用,所以現(xiàn)在我們將轉(zhuǎn)向功能選擇以刪除一些變量。
?
特征選擇
我們數(shù)據(jù)中的110個功能中的許多功能都是多余的,因?yàn)樗鼈儽舜烁叨认嚓P(guān)。例如,這里是Site EUI與Weather Normalized Site EUI的關(guān)系系數(shù)為0.997的圖。
彼此強(qiáng)相關(guān)的特征被稱為共線特征,并且移除這些特征對中的一個變量通常可以幫助機(jī)器學(xué)習(xí)模型概括并且更易于解釋。(我應(yīng)該指出,我們正在討論功能與其他功能的相關(guān)性,而不是與目標(biāo)的相關(guān)性,這有助于我們的模型!)
有許多方法可以計(jì)算特征之間的共線性,其中最常見的是方差膨脹因子。在這個項(xiàng)目中,我們將使用相關(guān)系數(shù)來識別和刪除共線特征。如果它們之間的相關(guān)系數(shù)大于0.6,我們將丟棄一對特征中的一個。對于實(shí)現(xiàn),請看一下筆記本(以及此Stack Overflow答案)
雖然這個值似乎是任意的,但我嘗試了幾個不同的閾值,這個選擇產(chǎn)生了最好的模型。機(jī)器學(xué)習(xí)是一個經(jīng)驗(yàn)領(lǐng)域,通常是試驗(yàn)和發(fā)現(xiàn)最佳表現(xiàn)!選擇特征后,我們剩下64個總功能和1個目標(biāo)。
# Remove any columns with all na values features = features.dropna(axis=1, how = 'all') print(features.shape) (11319, 65)?
建立基線
我們現(xiàn)在已經(jīng)完成了數(shù)據(jù)清理,探索性數(shù)據(jù)分析和特征工程。在開始建模之前采取的最后一步是建立一個naive基線。這基本上是我們可以比較我們的結(jié)果的猜測。如果機(jī)器學(xué)習(xí)模型沒有超過這個猜測,那么我們可能必須得出結(jié)論,機(jī)器學(xué)習(xí)對于任務(wù)是不可接受的,或者我們可能需要嘗試不同的方法。
對于回歸問題,合理的naive基線是猜測測試集中所有示例的訓(xùn)練集上目標(biāo)的中值。這為任何模型設(shè)定了相對較低的標(biāo)準(zhǔn)。
我們將使用的度量是平均絕對誤差(mae),它測量預(yù)測的平均絕對誤差?;貧w有很多指標(biāo),但我喜歡Andrew Ng建議選擇一個指標(biāo),然后在評估模型時堅(jiān)持使用它。平均絕對誤差易于計(jì)算且可解釋。
在計(jì)算基線之前,我們需要將數(shù)據(jù)分成訓(xùn)練和測試集:
我們將使用70%的數(shù)據(jù)進(jìn)行培訓(xùn),30%的數(shù)據(jù)用于測試:
# Split into 70% training and 30% testing set X, X_test, y, y_test = train_test_split(features, targets, test_size = 0.3, random_state = 42)?
現(xiàn)在我們可以計(jì)算出naive?基線表現(xiàn):
# Function to calculate mean absolute error def mae(y_true, y_pred):return np.mean(abs(y_true - y_pred))baseline_guess = np.median(y)print('The baseline guess is a score of %0.2f' % baseline_guess) print("Baseline Performance on the test set: MAE = %0.4f" % mae(y_test, baseline_guess))naive?估計(jì)在測試集上減少了約25個點(diǎn)。得分范圍從1-100,所以這代表25%的錯誤,超過相當(dāng)?shù)偷臉?biāo)準(zhǔn)!
?
結(jié)論
在本文中,我們介紹了機(jī)器學(xué)習(xí)問題的前三個步驟。在定義問題后,我們:
最后,我們還完成了建立基線的關(guān)鍵步驟,我們可以據(jù)此判斷機(jī)器學(xué)習(xí)算法。
第二篇文章(此處提供)將展示如何使用Scikit-Learn評估機(jī)器學(xué)習(xí)模型,選擇最佳模型,以及執(zhí)行超參數(shù)調(diào)整以優(yōu)化模型。處理模型解釋和報(bào)告結(jié)果的第三篇文章就在這里。
一如既往,我歡迎反饋和建設(shè)性的批評,可以在Twitter?@koehrsen_will上聯(lián)系。
?
原文:https://towardsdatascience.com/a-complete-machine-learning-walk-through-in-python-part-one-c62152f39420
?
?
?
?
?
總結(jié)
以上是生活随笔為你收集整理的【机器学习】完整的机器学习项目演练:第一部分的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [生存志] 第55节 吴公子札巡访中原
- 下一篇: ESP32-cam使用-智能家居云端视频