機器學(xué)習(xí)的開發(fā)實戰(zhàn)推進
目錄
1?????? 機器學(xué)習(xí)理論知識... 1
1.1??????? 機器學(xué)習(xí)基本概念... 1
1.2??????? 機器學(xué)習(xí)方法... 1
1.2.1???????? 機器學(xué)習(xí)方法-監(jiān)督學(xué)習(xí)... 1
1.2.2???????? 機器學(xué)習(xí)方法-無監(jiān)督學(xué)習(xí)... 2
1.2.3???????? 半監(jiān)督式學(xué)習(xí):... 3
1.2.4???????? 強化學(xué)習(xí):... 3
1.3??????? 機器學(xué)習(xí)算法分類... 4
1.3.3???????? 決策樹學(xué)習(xí)... 4
1.3.8???????? 關(guān)聯(lián)規(guī)則學(xué)習(xí)... 5
1.3.10?????? 人工神經(jīng)網(wǎng)絡(luò)... 6
1.5??????? 機器學(xué)習(xí)的數(shù)據(jù)統(tǒng)計的兩種拆分方式... 6
2?????? 機器學(xué)習(xí)實戰(zhàn)... 6
2.1??????? 使用數(shù)據(jù)二八拆分方式:... 7
2.3??????? 為機器學(xué)習(xí)算法準備數(shù)據(jù)... 10
2.4??????? 數(shù)據(jù)清洗... 10
2.6??????? 實戰(zhàn)總結(jié)... 13
機器學(xué)習(xí)是英文名稱Machine
Learning(簡稱ML)的直譯。機器學(xué)習(xí)涉及概率論、統(tǒng)計學(xué)、逼近論、凸分析、算法復(fù)雜度理論等多門學(xué)科。專門研究計算機怎樣模擬或?qū)崿F(xiàn)人類的學(xué)習(xí)行為,以獲取新的知識或技能,重新組織已有的知識結(jié)構(gòu)使之不斷改善自身的性能。它是人工智能的核心,是使計算機具有智能的根本途徑,其應(yīng)用遍及人工智能的各個領(lǐng)域,它主要使用歸納、綜合而不是演繹。
相對于傳統(tǒng)的計算機工作,我們給它一串指令,然后它遵照這個指令一步步執(zhí)行下去即可。機器學(xué)習(xí)根本不接受你輸入的指令,相反,它只接受你輸入的數(shù)據(jù)!也就是說它某種意義上具有了我們?nèi)颂幚硎虑榈哪芰Α?/p>
機器學(xué)習(xí)分為:監(jiān)督學(xué)習(xí),無監(jiān)督學(xué)習(xí),半監(jiān)督學(xué)習(xí),強化學(xué)習(xí)
1.2.1? 機器學(xué)習(xí)方法-監(jiān)督學(xué)習(xí)
監(jiān)督學(xué)習(xí):從給定的訓(xùn)練數(shù)據(jù)集中學(xué)習(xí)出一個函數(shù)(模型參數(shù)),當新的數(shù)據(jù)到來時,可以根據(jù)這個函數(shù)預(yù)測結(jié)果。監(jiān)督學(xué)習(xí)的訓(xùn)練集要求包括輸入輸出,也可以說是特征和目標。訓(xùn)練集中的目標是由人標注的。監(jiān)督學(xué)習(xí)就是最常見的分類(注意和聚類區(qū)分)問題,通過已有的訓(xùn)練樣本(即已知數(shù)據(jù)及其對應(yīng)的輸出)去訓(xùn)練得到一個最優(yōu)模型(這個模型屬于某個函數(shù)的集合,最優(yōu)表示某個評價準則下是最佳的),再利用這個模型將所有的輸入映射為相應(yīng)的輸出,對輸出進行簡單的判斷從而實現(xiàn)分類的目的。也就具有了對未知數(shù)據(jù)分類的能力。監(jiān)督學(xué)習(xí)的目標往往是讓計算機去學(xué)習(xí)我們已經(jīng)創(chuàng)建好的分類系統(tǒng)(模型)。
監(jiān)督學(xué)習(xí)是訓(xùn)練神經(jīng)網(wǎng)絡(luò)和決策樹的常見技術(shù)。這兩種技術(shù)高度依賴事先確定的分類系統(tǒng)給出的信息,對于神經(jīng)網(wǎng)絡(luò),分類系統(tǒng)利用信息判斷網(wǎng)絡(luò)的錯誤,然后不斷調(diào)整網(wǎng)絡(luò)參數(shù)。對于決策樹,分類系統(tǒng)用它來判斷哪些屬性提供了最多的信息。
在監(jiān)督式學(xué)習(xí)下,輸入數(shù)據(jù)被稱為“訓(xùn)練數(shù)據(jù)”,每組訓(xùn)練數(shù)據(jù)有一個明確的標識或結(jié)果,如對防垃圾郵件系統(tǒng)中“垃圾郵件”“非垃圾郵件”,對手寫數(shù)字識別中的“1“,”2“,”3“,”4“等。在建立預(yù)測模型的時候,監(jiān)督式學(xué)習(xí)建立一個學(xué)習(xí)過程,將預(yù)測結(jié)果與“訓(xùn)練數(shù)據(jù)”的實際結(jié)果進行比較,不斷的調(diào)整預(yù)測模型,直到模型的預(yù)測結(jié)果達到一個預(yù)期的準確率。
監(jiān)督式學(xué)習(xí)的常見應(yīng)用場景如分類問題和回歸問題。常見算法有邏輯回歸(Logistic Regression)和反向傳遞神經(jīng)網(wǎng)絡(luò)(Back Propagation Neural Network)
(1) regression:Y是實數(shù)vector。回歸問題,就是擬合(X,Y)的一條曲線,使得下式cost function L最小。
(2) classification:Y是一個finite number,可以看做類標號。分類問題需要首先給定有l(wèi)abel的數(shù)據(jù)訓(xùn)練分類器,故屬于有監(jiān)督學(xué)習(xí)過程。分類問題中,cost function L(X,Y)是X屬于類Y的概率的負對數(shù),其中fi(X)=P(Y=i | X);
屬于監(jiān)督式學(xué)習(xí)的算法有:回歸模型,決策樹,隨機森林,K鄰近算法,邏輯回歸等。
1.2.2? ? ?機器學(xué)習(xí)方法-無監(jiān)督學(xué)習(xí)
無監(jiān)督學(xué)習(xí):在非監(jiān)督式學(xué)習(xí)中,數(shù)據(jù)并不被特別標識,學(xué)習(xí)模型是為了推斷出數(shù)據(jù)的一些內(nèi)在結(jié)構(gòu)。常見的應(yīng)用場景包括關(guān)聯(lián)規(guī)則的學(xué)習(xí)以及聚類等。常見算法包括Apriori算法以及k-Means算法。
無監(jiān)督學(xué)習(xí)的目的是學(xué)習(xí)一個function
f,使它可以描述給定數(shù)據(jù)的位置分布P(Z)。包括兩種:density estimation & clustering.
density estimation就是密度估計,估計該數(shù)據(jù)在任意位置的分布密度
clustering就是聚類,將Z聚集幾類(如K-Means),或者給出一個樣本屬于每一類的概率。由于不需要事先根據(jù)訓(xùn)練數(shù)據(jù)去train聚類器,故屬于無監(jiān)督學(xué)習(xí)。
屬于無監(jiān)督式學(xué)習(xí)的算法有:關(guān)聯(lián)規(guī)則,K-means聚類算法等。
解釋1:輸入數(shù)據(jù)沒有被標記,也沒有確定的結(jié)果。樣本數(shù)據(jù)類別未知,需要根據(jù)樣本間的相似性對樣本集進行分類(聚類,clustering)試圖使類內(nèi)差距最小化,類間差距最大化。通俗點將就是實際應(yīng)用中,不少情況下無法預(yù)先知道樣本的標簽,也就是說沒有訓(xùn)練樣本對應(yīng)的類別,因而只能從原先沒有樣本標簽的樣本集開始學(xué)習(xí)分類器設(shè)計。
解釋2:非監(jiān)督學(xué)習(xí)目標不是告訴計算機怎么做,而是讓它(計算機)自己去學(xué)習(xí)怎樣做事情。非監(jiān)督學(xué)習(xí)有兩種思路。第一種思路是在指導(dǎo)Agent時不為其指定明確分類,而是在成功時,采用某種形式的激勵制度。需要注意的是,這類訓(xùn)練通常會置于決策問題的框架里,因為它的目標不是為了產(chǎn)生一個分類系統(tǒng),而是做出最大回報的決定,這種思路很好的概括了現(xiàn)實世界,agent可以對正確的行為做出激勵,而對錯誤行為做出懲罰。
無監(jiān)督學(xué)習(xí)的方法分為兩大類:
(1) 一類為基于概率密度函數(shù)估計的直接方法:指設(shè)法找到各類別在特征空間的分布參數(shù),再進行分類。
(2) 另一類是稱為基于樣本間相似性度量的簡潔聚類方法:其原理是設(shè)法定出不同類別的核心或初始內(nèi)核,然后依據(jù)樣本與核心之間的相似性度量將樣本聚集成不同的類別。
利用聚類結(jié)果,可以提取數(shù)據(jù)集中隱藏信息,對未來數(shù)據(jù)進行分類和預(yù)測。應(yīng)用于數(shù)據(jù)挖掘,模式識別,圖像處理等。
屬于無監(jiān)督式學(xué)習(xí)的算法有:關(guān)聯(lián)規(guī)則,K-means聚類算法等。
PCA和很多deep learning算法都屬于無監(jiān)督學(xué)習(xí)。
1.2.3? ? 半監(jiān)督式學(xué)習(xí):
半監(jiān)督學(xué)習(xí):在此學(xué)習(xí)方式下,輸入數(shù)據(jù)部分被標識,部分沒有被標識,這種學(xué)習(xí)模型可以用來進行預(yù)測,但是模型首先需要學(xué)習(xí)數(shù)據(jù)的內(nèi)在結(jié)構(gòu)以便合理的組織數(shù)據(jù)來進行預(yù)測。
應(yīng)用場景包括分類和回歸,算法包括一些對常用監(jiān)督式學(xué)習(xí)算法的延伸,這些算法首先試圖對未標識數(shù)據(jù)進行建模,在此基礎(chǔ)上再對標識的數(shù)據(jù)進行預(yù)測。如圖論推理算法(Graph Inference)或者拉普拉斯支持向量機(Laplacian SVM.)等。
強化學(xué)習(xí):在這種學(xué)習(xí)模式下,輸入數(shù)據(jù)作為對模型的反饋,不像監(jiān)督模型那樣,輸入數(shù)據(jù)僅僅是作為一個檢查模型對錯的方式,在強化學(xué)習(xí)下,輸入數(shù)據(jù)直接反饋到模型,模型必須對此立刻作出調(diào)整。常見的應(yīng)用場景包括動態(tài)系統(tǒng)以及機器人控制等。常見算法包括Q-Learning以及時間差學(xué)習(xí)(Temporal difference learning)
回歸算法是試圖采用對誤差的衡量來探索變量之間的關(guān)系的一類算法?;貧w算法是統(tǒng)計機器學(xué)習(xí)的利器。
常見的回歸算法包括:最小二乘法(Ordinary Least Square),邏輯回歸(Logistic Regression),逐步式回歸(Stepwise Regression),多元自適應(yīng)回歸樣條(Multivariate Adaptive Regression Splines)以及本地散點平滑估計(LocallyEstimated Scatterplot Smoothing)
基于實例的算法常常用來對決策問題建立模型,這樣的模型常常先選取一批樣本數(shù)據(jù),然后根據(jù)某些近似性把新數(shù)據(jù)與樣本數(shù)據(jù)進行比較。通過這種方式來尋找最佳的匹配。因此,基于實例的算法常常也被稱為“贏家通吃”學(xué)習(xí)或者“基于記憶的學(xué)習(xí)”。常見的算法包括 k-Nearest Neighbor(KNN), 學(xué)習(xí)矢量量化(LearningVector Quantization, LVQ),以及自組織映射算法(Self-Organizing Map , SOM)深度學(xué)習(xí)的概念源于人工神經(jīng)網(wǎng)絡(luò)的研究。含多隱層的多層感知器就是一種深度學(xué)習(xí)結(jié)構(gòu)。深度學(xué)習(xí)通過組合低層特征形成更加抽象的高層表示屬性類別或特征,以發(fā)現(xiàn)數(shù)據(jù)的分布式特征表示
決策樹算法根據(jù)數(shù)據(jù)的屬性采用樹狀結(jié)構(gòu)建立決策模型,決策樹模型常常用來解決分類和回歸問題。常見的算法包括:分類及回歸樹(Classification And Regression Tree, CART), ID3(Iterative Dichotomiser 3), C4.5, Chi-squared Automatic Interaction Detection(CHAID), Decision Stump,隨機森林(Random Forest),多元自適應(yīng)回歸樣條(MARS)以及梯度推進機(Gradient Boosting Machine, GBM)
貝葉斯方法算法是基于貝葉斯定理的一類算法,主要用來解決分類和回歸問題。常見算法包括:樸素貝葉斯算法,平均單依賴估計(Averaged One-Dependence Estimators, AODE),以及BayesianBelief Network(BBN)。
基于核的算法中最著名的莫過于支持向量機(SVM)了。基于核的算法把輸入數(shù)據(jù)映射到一個高階的向量空間,在這些高階向量空間里,有些分類或者回歸問題能夠更容易的解決。常見的基于核的算法包括:支持向量機(Support Vector Machine, SVM),徑向基函數(shù)(Radial Basis Function ,RBF),以及線性判別分析(Linear Discriminate Analysis ,LDA)等。
聚類,就像回歸一樣,有時候人們描述的是一類問題,有時候描述的是一類算法。聚類算法通常按照中心點或者分層的方式對輸入數(shù)據(jù)進行歸并。所以的聚類算法都試圖找到數(shù)據(jù)的內(nèi)在結(jié)構(gòu),以便按照最大的共同點將數(shù)據(jù)進行歸類。常見的聚類算法包括 k-Means算法以及期望最大化算法(Expectation Maximization, EM)。EM算法,指的是最大期望算法(ExpectationMaximization Algorithm,又譯期望最大化算法),是一種迭代算法,在統(tǒng)計學(xué)中被用于尋找,依賴于不可觀察的隱性變量的概率模型中,參數(shù)的最大似然估計。
EM算法的思想是:
1,給θ自主規(guī)定個初值(既然我不知道想實現(xiàn)“兩個碟子平均分配鍋里的菜”的話每個碟子需要有多少菜,那我就先估計個值);
2,根據(jù)給定觀測數(shù)據(jù)和當前的參數(shù)θ,求未觀測數(shù)據(jù)z的條件概率分布的期望(在上一步中,已經(jīng)根據(jù)手感將菜倒進了兩個碟子,然后這一步根據(jù)“兩個碟子里都有菜”和“當前兩個碟子都有多少菜”來判斷自己倒菜的手感);
3,上一步中z已經(jīng)求出來了,于是根據(jù)極大似然估計求最優(yōu)的θ’(手感已經(jīng)有了,那就根據(jù)手感判斷下盤子里應(yīng)該有多少菜,然后把菜勻勻);
4,因為第二步和第三步的結(jié)果可能不是最優(yōu)的,所以重復(fù)第二步和第三步,直到收斂(重復(fù)多次勻勻的過程,直到兩個碟子中菜的量大致一樣)。
而上面的第二步被稱作E步(求期望),第三步被稱作M步(求極大化),于是EM算法就在不停的EM、EM、EM….,所以被叫做EM算法,你看,多形象(攤手)。
像聚類算法一樣,降低維度算法試圖分析數(shù)據(jù)的內(nèi)在結(jié)構(gòu),不過降低維度算法是以非監(jiān)督學(xué)習(xí)的方式試圖利用較少的信息來歸納或者解釋數(shù)據(jù)。這類算法可以用于高維數(shù)據(jù)的可視化或者用來簡化數(shù)據(jù)以便監(jiān)督式學(xué)習(xí)使用。常見的算法包括:主成份分析(Principle Component Analysis, PCA),偏最小二乘回歸(PartialLeast Square Regression,PLS), Sammon映射,多維尺度(Multi-Dimensional Scaling, MDS), 投影追蹤(ProjectionPursuit)等。
1.3.8? ? ? ? 關(guān)聯(lián)規(guī)則學(xué)習(xí)
關(guān)聯(lián)規(guī)則學(xué)習(xí)通過尋找最能夠解釋數(shù)據(jù)變量之間關(guān)系的規(guī)則,來找出大量多元數(shù)據(jù)集中有用的關(guān)聯(lián)規(guī)則。常見算法包括 Apriori算法和Eclat算法等。
集成算法用一些相對較弱的學(xué)習(xí)模型獨立地就同樣的樣本進行訓(xùn)練,然后把結(jié)果整合起來進行整體預(yù)測。集成算法的主要難點在于究竟集成哪些獨立的較弱的學(xué)習(xí)模型以及如何把學(xué)習(xí)結(jié)果整合起來。這是一類非常強大的算法,同時也非常流行。常見的算法包括:Boosting, Bootstrapped Aggregation(Bagging), AdaBoost,堆疊泛化(StackedGeneralization, Blending),梯度推進機(Gradient Boosting Machine, GBM),隨機森林(Random Forest)。
1.3.10? ? ?人工神經(jīng)網(wǎng)絡(luò)
人工神經(jīng)網(wǎng)絡(luò)算法模擬生物神經(jīng)網(wǎng)絡(luò),是一類模式匹配算法。通常用于解決分類和回歸問題。人工神經(jīng)網(wǎng)絡(luò)是機器學(xué)習(xí)的一個龐大的分支,有幾百種不同的算法。(其中深度學(xué)習(xí)就是其中的一類算法,我們會單獨討論),重要的人工神經(jīng)網(wǎng)絡(luò)算法包括:感知器神經(jīng)網(wǎng)絡(luò)(Perceptron Neural Network), 反向傳遞(BackPropagation), Hopfield網(wǎng)絡(luò),自組織映射(Self-Organizing Map, SOM)。學(xué)習(xí)矢量量化(LearningVector Quantization, LVQ)
均方根誤差RSEM
平均絕對誤差MAE

MSE 和 MAE 都是測量預(yù)測值和目標值兩個向量距離的方法。有多種測量距離的方法,或范數(shù),更一般的K 階閔氏范數(shù)寫成。p=0時,?0(漢明范數(shù))只顯示了這個向量的基數(shù)(即,非零元素的個數(shù)),p趨于無窮時,?∞(切比雪夫范數(shù))是向量中最大的絕對值。
1.5? ? 機器學(xué)習(xí)的數(shù)據(jù)統(tǒng)計的兩種拆分方式
兩種拆分方式:二八拆分和分層采樣。
2? ? ? ? ? 機器學(xué)習(xí)實戰(zhàn)
上述已經(jīng)對機器學(xué)習(xí)基本知識進行了陳述,下面從實戰(zhàn)角度對機器學(xué)習(xí)進行論述,我們以以下數(shù)據(jù)為例,通過使用兩種拆分方式的實例來更深入的了解機器學(xué)習(xí):

上圖為使用housing.csv 訓(xùn)練數(shù)據(jù)。
實例代碼:
import numpy as np
def split_train_test(data, test_ratio):
??? shuffled_indices =np.random.permutation(len(data))???
??? test_set_size =int(len(data) * test_ratio)??? #拆分比例
??? test_indices =shuffled_indices[:test_set_size]
??? train_indices =shuffled_indices[test_set_size:]
??? returndata.iloc[train_indices], data.iloc[test_indices]
train_set, test_set = split_train_test(housing, 0.2)??? # housing數(shù)據(jù)二八拆分
經(jīng)驗證這個方法可行,但是并不完美:如果再次運行程序,就會產(chǎn)生一個不同的測試集。多次運行之后,你(或你的機器學(xué)習(xí)算法)就會得到整個數(shù)據(jù)集,這是需要避免的。
一個通常的解決辦法是使用每個實例的識別碼,以判定是否這個實例是否應(yīng)該放入測試集(假設(shè)實例有單一且不變的識別碼)。例如,你可以計算出每個實例識別碼的哈希值,只保留其最后一個字節(jié),如果值小于等于 51(約為 256 的 20%),就將其放入測試集。這樣可以保證在多次運行中,測試集保持不變,即使更新了數(shù)據(jù)集。新的測試集會包含新實例中的 20%,但不會有之前位于訓(xùn)練集的實例。
下面是一種可用的方法:
import hashlib
# 參數(shù)identifier為單一且不變的識別碼,可以為索引id
# hash(np.int64(identifier)).digest()[-1]返回識別碼的哈希摘要值的最后一個字節(jié)
def test_set_check(identifier, test_ratio, hash):
??? returnhash(np.int64(identifier)).digest()[-1] < 256 * test_ratio??? #記錄滿足條件的索引
def split_train_test_by_id(data, test_ratio, id_column,hash=hashlib.md5):
??? ids = data[id_column]
??? in_test_set =ids.apply(lambda id_: test_set_check(id_, test_ratio, hash))
??? returndata.loc[~in_test_set], data.loc[in_test_set]
但房產(chǎn)數(shù)據(jù)集沒有識別碼這一列。最簡單的方法是使用行索引作為 ID:
housing_with_id = housing.reset_index()?? #增加一個索引列,放在數(shù)據(jù)的第一列
train_set, test_set = split_train_test_by_id(housing_with_id, 0.2,"index")
如果使用行索引作為唯一識別碼,你需要保證新數(shù)據(jù)放到現(xiàn)有數(shù)據(jù)的尾部,且沒有行被深處。如果做不到,則可以用最穩(wěn)定的特征來創(chuàng)建唯一識別碼。例如,一個區(qū)的維度和經(jīng)度在幾百萬年之內(nèi)是不變的,所以可以將兩者結(jié)合成一個 ID。
將人群分成均勻的子分組,稱為分層,從每個分層去除合適數(shù)量的實例,以保證測試集對總?cè)藬?shù)有代表性。例如,美國人口的 51.3% 是女性,48.7% 是男性。所以在美國,嚴謹?shù)恼{(diào)查需要保證樣本也是這個比例:513 名女性,487 名男性作為數(shù)據(jù)樣本。
數(shù)據(jù)集中的每個分層都要有足夠的實例位于你的數(shù)據(jù)中,這點很重要。否則,對分層重要性的評估就會有偏差。這意味著,你不能有過多的分層,且每個分層都要足夠大。后面的代碼通過將收入中位數(shù)除以 1.5(以限制收入分類的數(shù)量),創(chuàng)建了一個收入類別屬性,用ceil對值舍入(以產(chǎn)生離散的分類),然后將所有大于 5的分類歸入到分類5 :
# 預(yù)處理,創(chuàng)建"income_cat"屬性
# 凡是會對原數(shù)組作出修改并返回一個新數(shù)組的,往往都有一個 inplace可選參數(shù)
# inplace=True,原數(shù)組名對應(yīng)的內(nèi)存值直接改變;inplace=False,原數(shù)組名對應(yīng)的內(nèi)存值并不改變,新的結(jié)果賦給一個新的數(shù)組.
housing["income_cat"]= np.ceil(housing["median_income"] / 1.5)
housing["income_cat"].where(housing["income_cat"]< 5, 5.0, inplace=True)
# 現(xiàn)在,就可以根據(jù)收入分類,進行分層采樣。你可以使用 Scikit-Learn 的StratifiedShuffleSplit類
fromsklearn.model_selection import StratifiedShuffleSplit
# random_state為隨機種子生成器,可以得到相同的隨機結(jié)果
# n_splits是將訓(xùn)練數(shù)據(jù)分成train/test對的組數(shù),這里匯總成一組數(shù)據(jù)
split =StratifiedShuffleSplit(n_splits=1, test_size=0.2, random_state=42)???
for train_index,test_index in split.split(housing, housing["income_cat"]):
??? strat_train_set = housing.loc[train_index]
??? strat_test_set = housing.loc[test_index]
# 現(xiàn)在,你需要刪除income_cat屬性,使數(shù)據(jù)回到初始狀態(tài):???
for set in(strat_train_set, strat_test_set):
??? set.drop(["income_cat"], axis=1,inplace=True)
可視化數(shù)據(jù)尋找規(guī)律:
housing.plot(kind="scatter",x="longitude", y="latitude", alpha=0.4,
??? s=housing["population"]/100,label="population",
??? c="median_house_value",cmap=plt.get_cmap("jet"), colorbar=True,
)
plt.legend()
每個圈的半徑表示街區(qū)的人口(選項s),顏色代表價格(選項c)。我們用預(yù)先定義的名為jet的顏色圖(選項cmap),它的范圍是從藍色(低價)到紅色(高價):

這張圖說明房價和位置(比如,靠海)和人口密度聯(lián)系密切。你還可以很容易地使用corr()方法計算出每對屬性間的標準相關(guān)系數(shù)(也稱作皮爾遜相關(guān)系數(shù)):
corr_matrix =housing.corr()
現(xiàn)在來看下每個屬性和房價中位數(shù)的關(guān)聯(lián)度:
>>>corr_matrix["median_house_value"].sort_values(ascending=False)
median_house_value??? 1.000000
median_income???????? 0.687170
total_rooms?????????? 0.135231
housing_median_age??? 0.114220
households??????????? 0.064702
total_bedrooms??????? 0.047865
population??????????-0.026699
longitude??????????? -0.047279
latitude???????????? -0.142826
Name:median_house_value, dtype: float64
相關(guān)系數(shù)的范圍是 -1 到 1。當接近 1 時,意味強正相關(guān);例如,當收入中位數(shù)增加時,房價中位數(shù)也會增加。當相關(guān)系數(shù)接近 -1 時,意味強負相關(guān);你可以看到,緯度和房價中位數(shù)有輕微的負相關(guān)性(即,越往北,房價越可能降低)。最后,相關(guān)系數(shù)接近 0,意味沒有線性相關(guān)性。(沒有直接的線性關(guān)系,不是沒有關(guān)系)
另一種檢測屬性間相關(guān)系數(shù)的方法是使用Pandas 的scatter_matrix函數(shù),它能畫出每個數(shù)值屬性對每個其它數(shù)值屬性的圖。因為現(xiàn)在共有 11 個數(shù)值屬性,你可以得到11 ** 2 = 121張圖。
frompandas.tools.plotting import scatter_matrix
attributes =["median_house_value", "median_income","total_rooms",
????????????? "housing_median_age"]
scatter_matrix(housing[attributes],figsize=(12, 8))
得到兩個屬性的散點圖:

2.3? ? 為機器學(xué)習(xí)算法準備數(shù)據(jù)
函數(shù)可以讓你在任何數(shù)據(jù)集上(比如,你下一次獲取的是一個新的數(shù)據(jù)集)方便地進行重復(fù)數(shù)據(jù)轉(zhuǎn)換。
你能慢慢建立一個轉(zhuǎn)換函數(shù)庫,可以在未來的項目中復(fù)用。
在將數(shù)據(jù)傳給算法之前,你可以在實時系統(tǒng)中使用這些函數(shù)。
這可以讓你方便地嘗試多種數(shù)據(jù)轉(zhuǎn)換,查看那些轉(zhuǎn)換方法結(jié)合起來效果最好。
大多機器學(xué)習(xí)算法不能處理特征丟失,因此先創(chuàng)建一些函數(shù)來處理特征丟失的問題。前面,你應(yīng)該注意到了屬性total_bedrooms有一些缺失值。有三個解決選項:
去掉對應(yīng)的街區(qū);
去掉整個屬性;
進行賦值(0、平均值、中位數(shù)等等)。
用DataFrame的dropna(),drop(),和fillna()方法,可以方便地實現(xiàn):
housing.dropna(subset=["total_bedrooms"])??? #選項1
housing.drop("total_bedrooms",axis=1)? ?????#選項2??? axis=0對行操作,axis=1對列操作
median =housing["total_bedrooms"].median()
housing["total_bedrooms"].fillna(median)???? #選項3
如果選擇選項 3,你需要計算訓(xùn)練集的中位數(shù),用中位數(shù)填充訓(xùn)練集的缺失值,不要忘記保存該中位數(shù)。后面用測試集評估系統(tǒng)時,需要替換測試集中的缺失值,也可以用來實時替換新數(shù)據(jù)中的缺失值。
Scikit-Learn 提供了一個方便的類來處理缺失值:Imputer。下面是其使用方法:首先,需要創(chuàng)建一個Imputer實例,指定用該屬性的中位數(shù)替換它的每個缺失值:
from sklearn.preprocessingimport Imputer
imputer =Imputer(strategy="median")??? #進行中位數(shù)賦值
因為只有數(shù)值屬性才能算出中位數(shù),我們需要創(chuàng)建一份不包括文本屬性ocean_proximity的數(shù)據(jù)副本:
housing_num =
housing.drop("ocean_proximity", axis=1) # 去除ocean_proximity不為數(shù)值屬性的特征
現(xiàn)在,就可以用fit()方法將imputer實例擬合到訓(xùn)練數(shù)據(jù):
imputer.fit(housing_num)
imputer計算出了每個屬性的中位數(shù),并將結(jié)果保存在了實例變量statistics_中。只有屬性total_bedrooms有缺失值,但是我們確保一旦系統(tǒng)運行起來,新的數(shù)據(jù)中沒有缺失值,所以安全的做法是將imputer應(yīng)用到每個數(shù)值:
>>> imputer.statistics_??? #實例變量statistics_和housing_num數(shù)值數(shù)據(jù)得到的中位數(shù)是一樣的
array([ -118.51, 34.26 , 29. , 2119. , 433. , 1164. , 408. , 3.5414])
>>>housing_num.median().values
array([ -118.51
, 34.26 , 29. , 2119. , 433. , 1164. , 408. , 3.5414])
現(xiàn)在,你就可以使用這個“訓(xùn)練過的”imputer來對訓(xùn)練集進行轉(zhuǎn)換,通過將缺失值替換為中位數(shù):
X = imputer.transform(housing_num)
結(jié)果是一個普通的 Numpy 數(shù)組,包含有轉(zhuǎn)換后的特征。如果你想將其放回到 PandasDataFrame中,也很簡單:
housing_tr =
pd.DataFrame(X, columns=housing_num.columns) # 得到處理缺失值后的DF數(shù)據(jù)
前面,我們丟棄了類別屬性ocean_proximity,因為它是一個文本屬性,不能計算出中位數(shù)。大多數(shù)機器學(xué)習(xí)算法跟喜歡和數(shù)字打交道,所以讓我們把這些文本標簽轉(zhuǎn)換為數(shù)字。Scikit-Learn 為這個任務(wù)提供了一個轉(zhuǎn)換器LabelEncoder:
# 簡單來說 LabelEncoder 是對不連續(xù)的數(shù)字或者文本進行編號
# le.fit([1,5,67,100])
#le.transform([1,1,100,67,5])
# 輸出:array([0,0,3,2,1])
>>> fromsklearn.preprocessing import LabelEncoder
>>> encoder =LabelEncoder()
>>> housing_cat =housing["ocean_proximity"]
>>>housing_cat_encoded = encoder.fit_transform(housing_cat)
>>>housing_cat_encoded
array([1, 1, 4, ..., 1, 0,3])
處理離散特征這還不夠,Scikit-Learn提供了一個編碼器OneHotEncoder,用于將整書分類值轉(zhuǎn)變?yōu)楠殶嵯蛄?。注意fit_transform()用于 2D 數(shù)組,而housing_cat_encoded是一個 1D 數(shù)組,所以需要將其變形:
>>> fromsklearn.preprocessing import OneHotEncoder
>>> encoder =OneHotEncoder()
>>>housing_cat_1hot = encoder.fit_transform(housing_cat_encoded.reshape(-1,1))
>>>housing_cat_1hot
<16513x5 sparse matrixof type ''
??? with 16513 stored elements in CompressedSparse Row format>
注意輸出結(jié)果是一個 SciPy 稀疏矩陣,而不是NumPy 數(shù)組。當類別屬性有數(shù)千個分類時,這樣非常有用。經(jīng)過獨熱編碼,我們得到了一個有數(shù)千列的矩陣,這個矩陣每行只有一個 1,其余都是 0。使用大量內(nèi)存來存儲這些 0 非常浪費,所以稀疏矩陣只存儲非零元素的位置。你可以像一個 2D 數(shù)據(jù)那樣進行使用,但是如果你真的想將其轉(zhuǎn)變成一個(密集的)NumPy 數(shù)組,只需調(diào)用toarray()方法:
>>>housing_cat_1hot.toarray()
array([[ 0.,? 1.,?0.,? 0.,? 0.],
?????? [ 0.,?1.,? 0.,? 0.,?0.],
?????? [ 0.,?0.,? 0.,? 0.,?1.],
?????? ...,
?????? [ 0.,?1.,? 0.,? 0.,?0.],
?????? [ 1.,?0.,? 0.,? 0.,?0.],
?????? [ 0.,?0.,? 0.,? 1.,?0.]])
使用類LabelBinarizer,我們可以用一步執(zhí)行這兩個轉(zhuǎn)換(從文本分類到整數(shù)分類,再從整數(shù)分類到獨熱向量):
>>> fromsklearn.preprocessing import LabelBinarizer
>>> encoder =LabelBinarizer()
>>>housing_cat_1hot = encoder.fit_transform(housing_cat)
>>>housing_cat_1hot
array([[0, 1, 0, 0, 0],
?????? [0, 1, 0, 0, 0],
?????? [0, 0, 0, 0, 1],
?????? ...,
?????? [0, 1, 0, 0, 0],
?????? [1, 0, 0, 0, 0],
?????? [0, 0, 0, 1, 0]])
注意默認返回的結(jié)果是一個密集 NumPy 數(shù)組。向構(gòu)造器LabelBinarizer傳遞sparse_output=True,就可以得到一個稀疏矩陣。
經(jīng)過以上自己對機器學(xué)習(xí)實戰(zhàn)開發(fā)演練,使初學(xué)者對機器學(xué)習(xí)的概念會有更深入的認識,對機器學(xué)習(xí)設(shè)計模式及開發(fā)邏輯更加了解,希望對機器學(xué)習(xí)的愛好者在實戰(zhàn)開發(fā)中有一定的助力。