天天看點

機器學習算法一覽(附python和R代碼)◆ ◆ ◆◆ ◆ ◆結束語

機器學習算法一覽(附python和R代碼)◆ ◆ ◆◆ ◆ ◆結束語

“谷歌的無人車和機器人得到了很多關注,但我們真正的未來卻在于能夠使電腦變得更聰明,更人性化的技術,機器學習。 ”

—— 埃裡克 施密特(谷歌首席執行官)

當計算從大型計算機轉移至個人電腦再轉移到雲的今天,我們可能正處于人類曆史上最關鍵的時期。之是以關鍵,并不是因為已經取得的成就,而是未來幾年裡我們即将要獲得的進步和成就。

對我來說,如今最令我激動的就是計算技術和工具的普及,進而帶來了計算的春天。作為一名資料科學家,我可以建造一個資料處理系統來進行複雜的算法運算,這樣每小時能賺幾美金。可是學習這些算法卻花了我無數個日日夜夜。

這篇文章有可能是我寫的所有文章裡最有價值的一篇。

寫這篇文章的目的,就是希望它可以讓有志于從事資料科學和機器學習的諸位在學習算法的路上少走些路。我會在文章中舉例一些機器學習的問題,你們也可以在思考解決這些問題的過程中得到啟發。我也會寫下對于各種機器學習算法的一些個人了解,并且提供r和python的執行代碼。讀完這篇文章,讀者們至少可以行動起來親手試試寫一個機器學習的程式。

不過,這篇文章并沒有闡述這些算法背後的統計學原理,有時候從實踐入手也是很好的學習路徑。如果你希望了解的是這些統計學原理,那麼這篇文章的内容可能并不适合你。

監督式學習算法包括一個目标變量(因變量)和用來預測目标變量的預測變量(自變量)。通過這些變量我們可以搭建一個模型,進而對于一個已知的預測變量值,我們可以得到對應的目标變量值。重複訓練這個模型,直到它能在訓練資料集上達到預定的準确度。 

與監督式學習不同的是,無監督學習中我們沒有需要預測或估計的目标變量。無監督式學習是用來對總體對象進行分類的。它在根據某一名額将客戶分類上有廣泛應用。 

屬于無監督式學習的算法有:關聯規則,k-means聚類算法等。

這個算法可以訓練程式做出某一決定。程式在某一情況下嘗試所有的可能行動,記錄不同行動的結果并試着找出最好的一次嘗試來做決定。 

屬于這一類算法的有馬爾可夫決策過程。

以下是最常用的機器學習算法,大部分資料問題都可以通過它們解決:

<code>1.線性回歸 (linear regression) 2.邏輯回歸 (logistic regression) 3.決策樹 (decision tree) 4.支援向量機(svm) 5.樸素貝葉斯 (naive bayes) 6.k鄰近算法(knn) 7.k-均值算法(k-means) 8.随機森林 (random forest) 9.降低次元算法(dimensionality reduction algorithms) 10.gradient boost和adaboost算法</code>

線性回歸是利用連續性變量來估計實際數值(例如房價,呼叫次數和總銷售額等)。我們通過線性回歸算法找出自變量和因變量間的最佳線性關系,圖形上可以确定一條最佳直線。這條最佳直線就是回歸線。這個回歸關系可以用y=ax+b 表示。

我們可以假想一個場景來了解線性回歸。比如你讓一個五年級的孩子在不問同學具體體重多少的情況下,把班上的同學按照體重從輕到重排隊。這個孩子會怎麼做呢?他有可能會通過觀察大家的身高和體格來排隊。這就是線性回歸!這個孩子其實是認為身高和體格與人的體重有某種相關。而這個關系就像是前一段的y和x的關系。

在y=ax+b這個公式裡:

y- 因變量

a- 斜率

x- 自變量

b- 截距

a和b可以通過最小化因變量誤差的平方和得到(最小二乘法)。

下圖中我們得到的線性回歸方程是 y=0.2811x+13.9。通過這個方程,我們可以根據一個人的身高得到他的體重資訊。

機器學習算法一覽(附python和R代碼)◆ ◆ ◆◆ ◆ ◆結束語

線性回歸主要有兩種:一進制線性回歸和多元線性回歸。一進制線性回歸隻有一個自變量,而多元線性回歸有多個自變量。拟合多元線性回歸的時候,可以利用多項式回歸(polynomial regression)或曲線回歸 (curvilinear regression)。

python 代碼

<code>#import library</code>

<code>#import other necessary libraries like pandas, numpy...</code>

<code>from sklearn import linear_model</code>

<code>#load train and test datasets</code>

<code>#identify feature and response variable(s) and values must be numeric and numpy arrays</code>

<code>x_train=input_variables_values_training_datasets</code>

<code>y_train=target_variables_values_training_datasets</code>

<code>x_test=input_variables_values_test_datasets</code>

<code># create linear regression object</code>

<code>linear = linear_model.linearregression()</code>

<code># train the model using the training sets and check score</code>

<code>linear.fit(x_train, y_train)</code>

<code>linear.score(x_train, y_train)</code>

<code>#equation coefficient and intercept</code>

<code>print('coefficient: \n', linear.coef_)</code>

<code>print('intercept: \n', linear.intercept_)</code>

<code>#predict output</code>

<code>predicted= linear.predict(x_test)</code>

r 代碼

<code>x_train &lt;- input_variables_values_training_datasets</code>

<code>y_train &lt;- target_variables_values_training_datasets</code>

<code>x_test &lt;- input_variables_values_test_datasets</code>

<code>x &lt;- cbind(x_train,y_train)</code>

<code>linear &lt;- lm(y_train ~ ., data = x)</code>

<code>summary(linear)</code>

<code>predicted= predict(linear,x_test)</code>

同樣,我們可以用一個例子來了解這個算法。

假設你的一個朋友讓你回答一道題。可能的結果隻有兩種:你答對了或沒有答對。為了研究你最擅長的題目領域,你做了各種領域的題目。那麼這個研究的結果可能是這樣的:如果是一道十年級的三角函數題,你有70%的可能性能解出它。但如果是一道五年級的曆史題,你會的機率可能隻有30%。邏輯回歸就是給你這樣的機率結果。

回到數學上,事件結果的勝算對數(log odds)可以用預測變量的線性組合來描述:

<code>odds= p/ (1-p) = probability of event occurrence / probability of not event occurrence ln(odds) = ln(p/(1-p)) logit(p) = ln(p/(1-p)) = b0+b1x1+b2x2+b3x3....+bkxk</code>

在這裡,p 是我們感興趣的事件出現的機率。它通過篩選出特定參數值使得觀察到的樣本值出現的機率最大化,來估計參數,而不是像普通回歸那樣最小化誤差的平方和。

你可能會問為什麼需要做對數呢?簡單來說這是重複階梯函數的最佳方法。因本篇文章旨不在此,這方面就不做詳細介紹了。

機器學習算法一覽(附python和R代碼)◆ ◆ ◆◆ ◆ ◆結束語

<code>from sklearn.linear_model import logisticregression</code>

<code>#assumed you have, x (predictor) and y (target) for training data set and x_test(predictor) of test_dataset</code>

<code># create logistic regression object</code>

<code>model = logisticregression()</code>

<code>model.fit(x, y)</code>

<code>model.score(x, y)</code>

<code>print('coefficient: \n', model.coef_)</code>

<code>print('intercept: \n', model.intercept_)</code>

<code>predicted= model.predict(x_test)</code>

<code>logistic &lt;- glm(y_train ~ ., data = x,family='binomial')</code>

<code>summary(logistic)</code>

<code>predicted= predict(logistic,x_test)</code>

延伸: 

以下是一些可以嘗試的優化模型的方法:

加入互動項(interaction)

減少特征變量

使用非線性模型

機器學習算法一覽(附python和R代碼)◆ ◆ ◆◆ ◆ ◆結束語

從上圖中我們可以看出,總體人群最終在玩與否的事件上被分成了四個群組。而分組是依據一些特征變量實作的。用來分組的具體名額有很多,比如gini,information gain, chi-square,entropy。

了解決策樹原理的最好的辦法就是玩jezzball遊戲。這是微軟的一款經典遊戲(見下圖)。這個遊戲的最終任務是在一個有移動牆壁的房間裡,通過建造牆壁來盡可能地将房間分成盡量大的,沒有小球的空間。

機器學習算法一覽(附python和R代碼)◆ ◆ ◆◆ ◆ ◆結束語

每一次你用建牆來分割房間,其實就是在将一個總體分成兩部分。決策樹也是用類似方法将總體分成盡量多的不同組别。

延伸閱讀:simplified version of decision tree algorithms

<code>from sklearn import tree</code>

<code># create tree object</code>

<code>model = tree.decisiontreeclassifier(criterion='gini') # for classification, here you can change the algorithm as gini or entropy (information gain) by default it is gini  </code>

<code># model = tree.decisiontreeregressor() for regression</code>

<code>library(rpart)</code>

<code># grow tree</code>

<code>fit &lt;- rpart(y_train ~ ., data = x,method="class")</code>

<code>summary(fit)</code>

<code>predicted= predict(fit,x_test)</code>

這是一個分類算法。在這個算法中我們将每一個資料作為一個點在一個n維空間上作圖(n是特征數),每一個特征值就代表對應坐标值的大小。比如說我們有兩個特征:一個人的身高和發長。我們可以将這兩個變量在一個二維空間上作圖,圖上的每個點都有兩個坐标值(這些坐标軸也叫做支援向量)。

機器學習算法一覽(附python和R代碼)◆ ◆ ◆◆ ◆ ◆結束語

現在我們要在圖中找到一條直線能最大程度将不同組的點分開。兩組資料中距離這條線最近的點到這條線的距離都應該是最遠的。

機器學習算法一覽(附python和R代碼)◆ ◆ ◆◆ ◆ ◆結束語

在上圖中,黑色的線就是最佳分割線。因為這條線到兩組中距它最近的點,點a和b的距離都是最遠的。任何其他線必然會使得到其中一個點的距離比這個距離近。這樣根據資料點分布在這條線的哪一邊,我們就可以将資料歸類。

更多閱讀:simplified version of support vector machine

你可以以任何角度畫分割線/分割面(經典遊戲中隻有垂直和水準方向)。

現在這個遊戲的目的是把不同顔色的小球分到不同空間裡。

小球是不動的。

<code>from sklearn import svm</code>

<code># create svm classification object</code>

<code>model = svm.svc() # there is various option associated with it, this is simple for classification. you can refer link, for mo# re detail.</code>

<code>library(e1071)</code>

<code># fitting model</code>

<code>fit &lt;-svm(y_train ~ ., data = x)</code>

樸素貝葉斯的模型易于建造,并且在分析大量資料問題時效率很高。雖然模型簡單,但很多情況下工作得比非常複雜的分類方法還要好。

貝葉斯理論告訴我們如何從先驗機率p(c),p(x)和條件機率p(x|c)中計算後驗機率p(c|x)。算法如下: 

機器學習算法一覽(附python和R代碼)◆ ◆ ◆◆ ◆ ◆結束語

p(c|x)是已知特征x而分類為c的後驗機率。

p(c)是種類c的先驗機率。

p(x|c)是種類c具有特征x的可能性。

p(x)是特征x的先驗機率。

例子: 以下這組訓練集包括了天氣變量和目标變量“是否出去玩”。我們現在需要根據天氣情況将人們分為兩組:玩或不玩。整個過程按照如下步驟進行:

步驟1:根據已知資料做頻率表

步驟2:計算各個情況的機率制作機率表。比如陰天(overcast)的機率為0.29,此時玩的機率為0.64.

機器學習算法一覽(附python和R代碼)◆ ◆ ◆◆ ◆ ◆結束語

步驟3:用樸素貝葉斯計算每種天氣情況下玩和不玩的後驗機率。機率大的結果為預測值。

提問: 天氣晴朗的情況下(sunny),人們會玩。這句陳述是否正确?

我們可以用上述方法回答這個問題。p(yes | sunny)=p(sunny | yes) * p(yes) / p(sunny)。 

這裡,p(sunny |yes) = 3/9 = 0.33, p(sunny) = 5/14 = 0.36, p(yes)= 9/14 = 0.64。

那麼,p (yes | sunny) = 0.33 * 0.64 / 0.36 = 0.60&gt;0.5,說明這個機率值更大。

當有多種類别和多種特征時,預測的方法相似。樸素貝葉斯通常用于文本分類和多類别分類問題。

<code>from sklearn.naive_bayes import gaussiannb</code>

<code># create svm classification object model = gaussiannb() # there is other distribution for multinomial classes like bernoulli naive bayes, refer link</code>

<code>fit &lt;-naivebayes(y_train ~ ., data = x)</code>

這個算法既可以解決分類問題,也可以用于回歸問題,但工業上用于分類的情況更多。 knn先記錄所有已知資料,再利用一個距離函數,找出已知資料中距離未知事件最近的k組資料,最後按照這k組資料裡最常見的類别預測該事件。

距離函數可以是歐式距離,曼哈頓距離,闵氏距離 (minkowski distance), 和漢明距離(hamming distance)。前三種用于連續變量,漢明距離用于分類變量。如果k=1,那問題就簡化為根據最近的資料分類。k值的選取時常是knn模組化裡的關鍵。

機器學習算法一覽(附python和R代碼)◆ ◆ ◆◆ ◆ ◆結束語

knn在生活中的運用很多。比如,如果你想了解一個不認識的人,你可能就會從這個人的好朋友和圈子中了解他的資訊。

在用knn前你需要考慮到:

knn的計算成本很高

所有特征應該标準化數量級,否則數量級大的特征在計算距離上會有偏移。

在進行knn前預處理資料,例如去除異常值,噪音等。

<code>from sklearn.neighbors import kneighborsclassifier</code>

<code># create kneighbors classifier object model</code>

<code>kneighborsclassifier(n_neighbors=6) # default value for n_neighbors is 5</code>

<code>library(knn)</code>

<code>fit &lt;-knn(y_train ~ ., data = x,k=5)</code>

這是一種解決聚類問題的非監督式學習算法。這個方法簡單地利用了一定數量的叢集(假設k個叢集)對給定資料進行分類。同一叢集内的資料點是同類的,不同叢集的資料點不同類。

還記得你是怎樣從墨水漬中辨認形狀的麼?k均值算法的過程類似,你也要通過觀察叢集形狀和分布來判斷叢集數量!

機器學習算法一覽(附python和R代碼)◆ ◆ ◆◆ ◆ ◆結束語

k均值算法如何劃分叢集:

從每個叢集中選取k個資料點作為質心(centroids)。

将每一個資料點與距離自己最近的質心劃分在同一叢集,即生成k個新叢集。

找出新叢集的質心,這樣就有了新的質心。

重複2和3,直到結果收斂,即不再有新的質心出現。

怎樣确定k的值:

如果我們在每個叢集中計算叢集中所有點到質心的距離平方和,再将不同叢集的距離平方和相加,我們就得到了這個叢集方案的總平方和。

我們知道,随着叢集數量的增加,總平方和會減少。但是如果用總平方和對k作圖,你會發現在某個k值之前總平方和急速減少,但在這個k值之後減少的幅度大大降低,這個值就是最佳的叢集數。

機器學習算法一覽(附python和R代碼)◆ ◆ ◆◆ ◆ ◆結束語

<code>from sklearn.cluster import kmeans</code>

<code>#assumed you have, x (attributes) for training data set and x_test(attributes) of test_dataset</code>

<code>k_means = kmeans(n_clusters=3, random_state=0)</code>

<code>model.fit(x)</code>

<code>library(cluster)</code>

<code>fit &lt;- kmeans(x, 3) # 5 cluster solution</code>

随機森林是對決策樹集合的特有名稱。随機森林裡我們有多個決策樹(是以叫“森林”)。為了給一個新的觀察值分類,根據它的特征,每一個決策樹都會給出一個分類。随機森林算法選出投票最多的分類作為分類結果。

怎樣生成決策樹:

如果訓練集中有n種類别,則有重複地随機選取n個樣本。這些樣本将組成培養決策樹的訓練集。

如果有m個特征變量,那麼選取數m &lt;&lt; m,進而在每個節點上随機選取m個特征變量來分割該節點。m在整個森林養成中保持不變。

每個決策樹都最大程度上進行分割,沒有剪枝。

比較決策樹和調節模型參數可以擷取更多該算法細節。我建議讀者閱讀這些文章:

introduction to random forest – simplified

comparing a cart model to random forest (part 1)

comparing a random forest to a cart model (part 2)

tuning the parameters of your random forest model

<code>from sklearn.ensemble import randomforestclassifier</code>

<code># create random forest object</code>

<code>model= randomforestclassifier()</code>

<code>library(randomforest)</code>

<code>fit &lt;- randomforest(species ~ ., x,ntree=500)</code>

在過去的4-5年裡,可擷取的資料幾乎以指數形式增長。公司/政府機構/研究組織不僅有了更多的資料來源,也獲得了更多元度的資料資訊。

例如:電子商務公司有了顧客更多的細節資訊,像個人資訊,網絡浏覽曆史,個人喜惡,購買記錄,回報資訊等,他們關注你的私人特征,比你天天去的超市裡的店員更了解你。

作為一名資料科學家,我們手上的資料有非常多的特征。雖然這聽起來有利于建立更強大精準的模型,但它們有時候反倒也是模組化中的一大難題。怎樣才能從1000或2000個變量裡找到最重要的變量呢?這種情況下降維算法及其他算法,如決策樹,随機森林,pca,因子分析,相關矩陣,和預設值比例等,就能幫我們解決難題。

進一步的了解可以閱讀beginners guide to learn dimension reduction techniques。

<code>from sklearn import decomposition</code>

<code>#assumed you have training and test data set as train and test</code>

<code># create pca obeject pca= decomposition.pca(n_components=k) #default value of k =min(n_sample, n_features)</code>

<code># for factor analysis</code>

<code>#fa= decomposition.factoranalysis()</code>

<code># reduced the dimension of training dataset using pca</code>

<code>train_reduced = pca.fit_transform(train)</code>

<code>#reduced the dimension of test dataset</code>

<code>test_reduced = pca.transform(test)</code>

<code>library(stats)</code>

<code>pca &lt;- princomp(train, cor = true)</code>

<code>train_reduced  &lt;- predict(pca,train)</code>

<code>test_reduced  &lt;- predict(pca,test)</code>

gbm和adaboost都是在有大量資料時提高預測準确度的boosting算法。boosting是一種內建學習方法。它通過有序結合多個較弱的分類器/估測器的估計結果來提高預測準确度。這些boosting算法在kaggle,av hackthon, crowdanalytix等資料科學競賽中有出色發揮。

更多閱讀: know about gradient and adaboost in detail

<code>from sklearn.ensemble import gradientboostingclassifier</code>

<code># create gradient boosting classifier object</code>

<code>model= gradientboostingclassifier(n_estimators=100, learning_rate=1.0, max_depth=1, random_state=0)</code>

<code>library(caret)</code>

<code>fitcontrol &lt;- traincontrol( method = "repeatedcv", number = 4, repeats = 4)</code>

<code>fit &lt;- train(y ~ ., data = x, method = "gbm", trcontrol = fitcontrol,verbose = false)</code>

<code>predicted= predict(fit,x_test,type= "prob")[,2]</code>

gradientboostingclassifier 和随機森林是兩種不同的boosting分類樹。人們經常提問這兩個算法有什麼不同。

至此我相信讀者對于常用的機器學習算法已經有了一定了解。寫這篇文章并且提供r和python的代碼就是為了讓你可以立馬着手學習。動起手來去練一練吧,加深對這些算法過程的認識,運用他們,你會喜歡上機器學習的!

原文釋出時間為:2016-04-19

本文來自雲栖社群合作夥伴“大資料文摘”,了解相關資訊可以關注“bigdatadigest”微信公衆号