1. 程式人生 > >6個步驟從頭開始編寫機器學習演算法:感知器案例研究

6個步驟從頭開始編寫機器學習演算法:感知器案例研究

摘要:通用版學習機器學習演算法的方法,你值得擁有!

640?wx_fmt=png

從0開始編寫機器學習演算法是一種非常好的體驗

當你點選之後你會感到壓力,因為其中有些演算法比其他演算法更復雜,所以我建議你從一些簡單甚至更簡單的演算法開始,比如單層感知器。

以感知器為例從頭開始編寫演算法,主要為以下6個步驟:

1.對演算法有一個基本的瞭解;

2.找到一些不同的學習來源;

3.將演算法分解成塊;

4.從一個簡單的例子開始;

5.使用可行的實現進行驗證;

6.寫下你的過程。

1、對演算法進行基本的瞭解

如果你不瞭解基礎知識,不要從零開始編寫演算法。

至少,你應該能夠回答以下問題:

1.它是什麼?

2.它的典型用途是什麼?

3.使用條件是什麼?

對於感知器,至少能夠回答以下問題:

1.單層感知器是最基本的神經網路。它通常用於二分類問題(1或0,“是”或“否”)。

2.一些簡單的用法可能是情緒分析(積極或消極反應)或貸款違約預測(“將違約”或“將不違約”)。對於這兩種情況,決策邊界都必須是線性的。

3.如果決策邊界是非線性的,你就不能用感知器。對於這些問題,需要使用其他不同的方法。

640?wx_fmt=png

2、使用不同的學習資源

在你對模型有了基本的瞭解之後,這個時候可以開始你的研究了。

有些人用教材學得更好,有些人用視訊學得更好。我個人喜歡到處轉轉,使用各種各樣的資源。

對於數學細節,教材講的比較詳細,但對於更實際的例子,我更喜歡部落格帖子和視訊。

對於感知器,這裡有一些很好的學習資源:

教材

統計學習基礎

https://web.stanford.edu/~hastie/Papers/ESLII.pdf

機器學習理解:從理論到演算法https://www.cs.huji.ac.il/~shais/UnderstandingMachineLearning/understanding-machine-learning-theory-algorithms.pdf

部落格

如何在Python中從Scratch開始實現感知器演算法,JasonBrownlee

https://machinelearningmastery.com/implement-perceptron-algorithm-scratch-python/

單層神經網路與梯度下降,SebastianRaschkahttps://sebastianraschka.com/Articles/2015_singlelayer_neurons.html

視訊

感知器訓練

https://www.youtube.com/watch

感知器演算法的原理

https://www.youtube.com/watch

3、將演算法分解成塊

現在我們已經收集了各種學習資源,是時候開始學習了。

與其從頭到尾讀一篇部落格文章,不如先瀏覽一下章節標題和其他重要資訊,寫下要點,並試著概述演算法。

在瀏覽了這些資料之後,我將感知器分為以下5個部分:

1.初始化權重;

2.將權重乘以輸入,然後求和;

3.將結果與閾值進行比較以計算輸出(1或0);

4.更新權重;

5.重複以上步驟;

讓我們詳細討論每一個部分。

1.初始化權重

首先初始化權重向量。權重的數量需要與特徵的數量匹配。假設我們有三個特徵,則權重向量如下所示:

640?wx_fmt=png

權重向量通常被初始化為0,在本文中我們將繼續使用它。

2.將權重乘以輸入,然後求和

接下來,我們將權重乘以輸入,然後求和。為了更容易理解,我在第一行中對權重及其對應的特徵進行了著色。

640?wx_fmt=png

在權重乘以特徵之後,我們把它們加起來,這也被稱為點積。

640?wx_fmt=png

最後的結果為0,將這個零時的結果設為f。

3.和閾值進行比較

在計算出點積之後,我們需要將它與閾值進行比較。

這裡選擇用0作為閾值,但也可以用其他值作為閾值。

640?wx_fmt=png

由於我們計算出來的點積f不大於我們的閾值(0),所以估計值等於0。

我將估計值表示為帶帽的y(又名“y hat”),下標0表示第一行,也可以用1表示第一行,這無所謂。這裡選擇從0開始。

如果我們將這個結果與實際值進行比較,可以看到當前的權重沒有正確地預測實際輸出。

640?wx_fmt=png

因為我們的預測不正確,所以進行下一步來更新權重。

4.更新權重

接下來更新權重,以下是要使用的方程:

640?wx_fmt=png

基本原理是在迭代“n”處調整當前權重,以便在下一個迭代中得到一個新的權重“n+1”。

為了調整權重,我們需要設定一個“學習率”。這是用希臘字母“eta”表示。       

這裡選擇用0.1表示學習率,也可以用其他值表示學習率,就像閾值的設定一樣。

以下是到目前為止的總結:

640?wx_fmt=png

繼續計算在n=2時的權重。

640?wx_fmt=png

我們已經成功地完成了感知器演算法的第一次迭代。

5.重複以上步驟

由於演算法沒有計算出正確的輸出,我們需要繼續。通常需要多次迭代,遍歷資料集中的每一行來更新權重。對資料集的一次完整遍歷稱為“epoch”。

因為資料集有3行,我們需要3次迭代才能完成1個epoch。

我們可以設定總的迭代次數或epoch來繼續執行演算法,比如指定30次迭代(或10個epochs)。

與閾值和學習率一樣,epoch的數量是一個可以隨意使用的引數。

在下一個迭代中,我們將繼續討論第二行特徵。

640?wx_fmt=png

這裡不一一重複每一步了,以下是下一個點積的計算。

640?wx_fmt=png

接下來,將點積和閾值進行比較,以計算新的估計值,更新權重,然後繼續。如果資料是線性可分的,感知器就會收斂。

4、從一個簡單的例子開始

現在我們已經手工將演算法分解成塊,現在用程式碼開始實現它。為了簡單起見,從一個非常小的“玩具資料集”開始。對於這種型別的問題,一個好的小的線性可分離資料集是NAND門。這是數電中常用的邏輯閘。

640?wx_fmt=png

因為這是一個非常小的資料集,我們可以手動將其輸入到Python中。

為了讓模型計算偏差項,新增一個虛擬的特徵“x0”表示第一列。

可以將偏差看作是截距項,模型可以正確地分離這兩個類。

以下是輸入資料的程式碼:

640?wx_fmt=png

與前一節一樣,我將逐步詳細介紹演算法,編寫程式碼並測試它。

1.初始化權重

第一步是初始化權重

640?wx_fmt=png

請記住,權重向量的長度需要與特徵的數量相匹配。對於這個NAND門的例子,長度是3。

2.將權重乘以輸入,然後求和

接下來,我們將權重乘以輸入,然後求和(即點積)。

同樣,我們可以使用Numpy的dot()函式輕鬆地執行此操作。

我們從權重向量和第一行特徵的點積開始。

640?wx_fmt=png

正如預期的那樣,結果是0。

為了與上一節保持一致,我將點積賦給變數f。

3.與閾值進行比較

在計算了點積之後,將結果與閾值進行比較,從而對輸出進行預測。

設定閾值z等於0。如果點積f大於0,我們的預測是1。否則,它就是零。

記住,這個預測通常是用一克拉的頂部來表示的,也被稱為“帽子”,把預測值賦給變數yhat。

640?wx_fmt=png

正如預期的那樣,預測為0。

在上面的註釋中,將這些程式碼稱為“啟用函式”,是更正式的名稱。

檢視NAND輸出的第一行,可以看到實際值是1,由於我們的預測是錯誤的,所以需要繼續更新權重。

4.更新權重

現在已經得出了預測值,準備更新權重。

我們需要設定一個學習率才能做到這一點。為了與前面的例子保持一致,將學習率“eta”賦值為0.1。

我將對每個權重的更新進行硬編碼,使其更容易閱讀。

640?wx_fmt=png

可以看到權重現在已經更新了,繼續下去。

5.重複以上步驟

現在我們已經完成了每一個步驟,現在是時候把所有的東西放在一起了。

最後一個還沒有討論的是損失函式,即實現最小化的函式。在例子中,這將是平方和(SSE)誤差。

640?wx_fmt=png

這就是我們用來計算誤差的方法,看看模型是如何執行的。

把所有這些都聯絡起來,完整的函式如下所示:

640?wx_fmt=png

現在已經編寫了感知器的所有程式碼,開始執行它:

640?wx_fmt=png

看一看上方的誤差,可以看到誤差在第6次迭代時趨於0,對於之後的迭代,始終為0。當誤差趨於0時,表示模型收斂了。也就是說模型已經正確地“學習”了適當的權重。

在下一節中,我們將在更大的資料集上使用計算過的權重來做預測。

5、使用可行的實現進行驗證

到目前為止,我們已經找到了不同的學習資源,手動完成了演算法,並通過一個簡單的例子在程式碼中測試了它。

現在是時候將結果與可行的實現進行比較了。為了比較,我們將使用scikit-learn中的感知器。

步驟如下:

1.匯入資料;

2.將資料分成訓練/測試集;

3.訓練我們的感知器;

4.測試感知器;

5.和scikit-learn的感知器相比;

1.匯入資料

從匯入資料開始,可以在這裡獲得資料集的副本。

為了確保感知器能夠正常工作,所建立的資料集是線性可分的。為了驗證,繼續繪製資料。

640?wx_fmt=png640?wx_fmt=png

上圖很容易看出資料集輕易地被一條直線分開。

在繼續之前,先來解釋繪製資料的程式碼。

使用panda匯入csv,它自動將資料放入dataframe中。

為了繪製資料,必須從dataframe中提取值,所以使用了.values方法。

特徵在第1和第2列中,所以在散點圖函式中使用了這些特徵。第0列是包含1的虛擬特徵,這樣就能計算出截距。這與我們在前一節中對NAND gate所做的事情相似。

最後,在scatterplot函式中使用c = df['3']和alpha = 0.8為兩個類著色。輸出是第3列(0或1)中的資料,因此告訴函式使用第3列為兩個類著色。

你可以在這裡找到關於Matplotlib的散點函式的更多資訊。

2.將資料分成訓練/測試集

既然我們已經確認了資料可以線性分離,那麼現在就該分離資料了。在單獨的資料集上訓練模型和測試資料集是很好的實踐,能夠避免過擬合。分離資料有不同的方法,但為了簡單起見,這裡使用一個訓練集和一個測試集。

我先整理一下我的資料。如果檢視原始檔案,你會看到資料是按輸出(第三列)中0的行進行分組的,然後是所有的1。我想要改變一下,增加一些隨機性,所以我要洗牌。

640?wx_fmt=png

我首先將資料從dataframe改為numpy陣列。這將更容易地使用許多numpy函式,例如.shuffle。

為了讓結果重現,我設定了一個隨機種子(5)。完成後,嘗試改變隨機種子,看看結果如何變化。

接下來把70%的資料分成訓練集,30%分成測試集。

640?wx_fmt=png

最後一步是分離訓練和測試集的特徵和輸出。

640?wx_fmt=png

我選擇了70%/30%作為訓練/測試集,只是為了這個示例,但我希望你研究其他方法 ,比如k-fold交叉驗證。

3.訓練感知器

接下來,我們要訓練感知器。

這非常簡單,我們將重用在前一節中構建的程式碼。

640?wx_fmt=jpeg

讓我們來看看權重和平方誤差之和。

640?wx_fmt=png

權值現在對我們來說意義不大,但我們將在下一節中使用這些數字來測試感知器,還將使用權重來比較我們的模型和scikit-learn模型。

看一下平方誤差之和,我們可以看到感知器已經收斂,這是我們期望的,因為資料是線性可分的。

4.測試感知器

現在是測試感知器的時候了。為此,我們將構建一個小型的perceptron_test函式。這和我們已經看到的很相似。這個函式使用perceptron_train函式計算的權值的點積,以及特徵,以及啟用函式來進行預測。

我們唯一沒有看到的是accuracy_score,這是一個來自scikit-learn的評估度量函式,你可以在這裡瞭解更多。

把所有這些放在一起,以下是具體的程式碼實現:

640?wx_fmt=png

準確度為1.0表明我們的模型正確地預測了所有的測試資料。這個資料集顯然是可分離的,所以我們期望這個結果。

5、和scikit-learn的感知器相比

最後一步是將我們的結果與scikit-learn的感知器進行比較。下面是這個模型的程式碼:

640?wx_fmt=png

現在我們已經訓練了模型,讓我們將權重與模型計算的權重進行比較。

640?wx_fmt=png

scikit-learn模型中的權重與我們的相同,這意味著我們的模型工作正常。

在我們結束之前,有幾個小問題需要解決一下。在scikit-learn模型中,我們必須將隨機狀態設定為“None”並關閉變換,但我們已經設定了一個隨機種子並打亂了資料,所以我們不需要再這樣做了。

我們還必須將學習率“eta0”設定為0.1,以與我們的模型相同。

最後一點是截距。因為我們已經包含了一個虛擬的特徵列1s,我們正在自動擬合截距,所以我們不需要在scikit-learn感知器中開啟它。

這些看起來都是次要的細節,但如果我們不設定這些,就無法達到與我們的模型相同的結果。

這一點很重要。在使用模型之前,閱讀文件並理解所有不同設定的作用是非常重要的。

6、寫下你的過程

這個過程中的最後一步可能是最重要的。你已經完成了所有的工作,包括學習、記筆記、從頭開始編寫演算法,並將其與可行的實現進行比較,不要讓所有的好工作白白浪費掉!

寫下這個過程很重要,原因有二:

1、你會得到更深的理解,因為你正在教導別人你剛剛學到的東西。

2、你可以向潛在僱主展示它。

證明你可以從機器學習庫中實現一個演算法是一回事,但如果你可以自己從頭實現它,那就更令人印象深刻了。一個展示你作品的好方法是使用GitHub頁面組合。

結論

在這篇文章中,我們學習瞭如何從零開始編寫實現感知器。更重要的是,我們學習瞭如何找到有用的學習資源,以及如何將演算法分解成塊。

然後,我們學習瞭如何使用一個玩具資料集在程式碼中實現和測試演算法。

最後,我們通過比較我們的模型和可行實現的結果來結束本文。要獲得使用的Python程式碼的完整副本,單擊下面的綠色按鈕。

這是在更深層次上學習演算法的一個很好的方法,這樣就可以自己實現它了。

大多數情況下,你將使用可行的實現,但如果你真的想深入瞭解底層的情況,從頭實現它是一個很好的練習。

本文由阿里云云棲社群組織翻譯。

文章原標題《machine-learning-from-scratch》

作者:dataoptimal 譯者:虎說八道,審校:。

640?wx_fmt=jpeg

end

更多精彩