機器學習入門及基本算法圖解

基本算法

最近在學習神經網絡,整理了一些算法,寫出來給自己一點交代吧,本人剛入算法沒多久,如果有不對的地方,請指出來大家一起學習,謝謝。

費曼算法(Feynman algorithm)

將這個算法放在最前面是因爲該算法提供了一些我們思考問題的方法,根據吉德林法則:把問題清楚的寫下來,就已經解決了一半!很多時候我們不知道怎麼去解決問題,可以通過下面的三步來一步一步實施。這個算法是以著名物理學家理查德·費曼命名的,其步驟如下:
(1) 將問題寫下來。
(2) 好好思考。
(3) 將答案寫下來。
——Aditya Bhargava《算法圖解》

算法簡介

在百度百科上,算法是這麼定義的:

算法(Algorithm)是指解題方案的準確而完整的描述,是一系列解決問題的清晰指令,算法代表着用系統的方法描述解決問題的策略機制。也就是說,能夠對一定規範的輸入,在有限時間內獲得所要求的輸出。如果一個算法有缺陷,或不適合於某個問題,執行這個算法將不會解決這個問題。不同的算法可能用不同的時間、空間或效率來完成同樣的任務。一個算法的優劣可以用空間複雜度與時間複雜度來衡量。

簡單來說呢算法就是完成任務的指令,你可以把你曾經寫過的代碼想成要完成任務的指令,也就是算法,在這裏介紹一些基本的算法以及示例,有很多人問我機器學習怎麼入門,到底應該準備哪些基礎知識。其實這個問題我也是頭大,因爲我是半路出家學習的算法,不過以前接觸過一些算法方向的,比如做推薦系統時候的協同過濾算法,有興趣的可以去看一下怎麼實現的,本博客的KNN近鄰算法裏也有涉及到一些,對算法的思想入門還是有一點幫助的。emmmm 跑題了,咱們繼續說機器學習需要具備的知識

  1. 數學基礎
  2. 典型機器學習算法
  3. 編程基礎

很多盆友滿懷激情來到了本博客,想要開始學習機器學習,但是在看到數學基礎的那一刻就想放棄了,機器學習相對於其他開發工作來說,算的上門檻的也就是數學公式這一塊了,每一個算法,要在訓練集上最大程度擬合的同時又要保證泛化能力,就需要不斷分析結果和數據,調優參數。這就需要我們對數據分佈和模型底層的數學原理有一定的理解,所幸的是,如果只是想合理的應用機器學習,而不是做相關方向高精尖的research,需要的基礎數學知識啃一啃還是基本能理解下來的,在這裏有一句送給大家:“天下事以難而廢者十之一,以惰而廢者十之九

微積分

微分的計算的意義及其幾何、物理意義。是機器學習中大多數算法的求解過程的核心。比如算法中運用中的梯度下降法,牛頓法等。如果對幾何意義有充分的理解的話,就可以理解爲“梯度下降是用平面來逼近局部,而牛頓法是用曲面來逼近局部”,凸優化和條件最優化在算法裏面隨處可見,如果可以系統的學習的話會讓你對算法的認識有一個新的高度。

線性代數

大多數機器學習的算法要應用起來,依賴於高效的計算,這種場景下,程序員GG們習慣的多層for循環通常就行不通了,而大多數的循環操作可轉化成矩陣之間的乘法運算,這就和線性代數有莫大的關係了
向量的內積運算更是隨處可見。矩陣乘法與分解在機器學習的主成分分析(PCA)和奇異值分解(SVD) 等部分呈現刷屏狀地出現。

概率與統計

廣義來說,機器學習在做的很多事情,和統計層面數據分析和發掘隱藏的模式,是非常類似的。
極大似然思想、貝葉斯模型 是理論基礎,樸素貝葉斯(Na?ve Bayes )、語言模型(N-gram)、隱馬爾科夫(HMM)、隱變量混合概率模型是他們的高級形態。
常見分佈如高斯分佈是混合高斯模型(GMM)等的基礎。

圖算法

在衆多算法中,圖算法算是比較經典的算法了,首先,我們說說什麼是圖

百度百科:圖,漢語常用字,最早見於甲骨文 ,其本意原指古代在皮、絹等材料上標畫城邦鄉邑及邊界的示意資料,後引伸爲思慮、謀求、謀劃,又引申爲描畫出來的形象化的作品、文件。

在算法中,圖的意義大致上是模擬了一組連接關係。如下圖,Alexmer是Bob的朋友,而Blue和kalin也是Bob的朋友。但是Alexmer和Blue並不認識。

圖連接關係

沒錯,圖就是這個樣子,圖由節點和邊組成,一個節點可能與很多其他節點相連,這些節點叫做該節點的鄰居,如上圖Alexmer,Blue,kalin 就是Bob的鄰居。但Alexmer不是Blue的鄰居,因爲他們沒有相連,圖就是來模擬各個節點之間的關係的。

圖

圖的兩種搜索方式

搜索是人工智能中的一種基本方法,是一項非常普遍使用的算法策略,能夠解決許許多多的常見問題,在某些情況下我們很難想到高效的解法時,搜索往往是可選的唯一選擇。按照標準的話來講:搜索算法是利用計算機的高性能來有目的的窮舉一個問題的部分或所有的可能情況,從而求出問題的解的一種方法。深度優先搜索與廣度優先搜索都是用於圖的查找算法,深度優先搜索用於早起的爬蟲以及後來的搜索引擎算法,廣度優先搜索常用於計算最短路徑問題。

深度優先搜索(depth-first-search DFS)

有很多人要問,爲什麼直接就來到了圖的深度優先搜索,因爲這個是我們要介紹的第一種圖算法,其過程簡要來說是對每一個可能的分支路徑深入到不能再深入爲止,而且每個節點只能訪問一次。每當訪問一個節點時,將其標記爲已訪問的節點,然後遞歸其相鄰的節點,直到沒有可以直接訪問該節點的時候,就達到了該算法的目的。

深度優先搜索原理圖

深度優先搜索動畫:
深度優先搜索動畫

廣度優先搜索(breadth-first search,BFS)

廣度優先搜索又叫寬度優先搜索,是最簡便的搜索圖的算法之一,後續介紹的狄克斯特拉算法就是採用了寬度優先搜索類似的思想。屬於一種盲目搜索法,他不會去考慮結果的位置,而是徹底搜索整張圖,直到查到結果爲止。
廣度優先搜索
如上圖所示,假設你居住在A地,想要去往F,那麼就會延伸出兩個問題:

  1. 從A出發,有前往F的路徑嗎
  2. 從A出發到F的最短路徑是哪條

從A出發前往F,首先離你最近的兩個點是B和C,你並不能一步走到F,所以首先來到了B和C,我們再接着走一步,很顯然,兩步也不能走到F,我們來到了B,D,Z,E,假設這四個節點對外突出,但是我們還是沒有到達目標幾點F,所以我們走出第三步,發現對外突出的節點D可以到達目標節點F,也就是我們所求的最短路徑了。

廣度優先搜素動態圖

散列表

不管如何,我們最終都要用代碼來實現算法,圖由多個節點構成,我們如何來表達各個節點構成的關係呢,它就是散列表。
在這裏插入圖片描述
在這裏插入圖片描述
散列表可以通過這種鍵值對的形式來將你的鍵映射到值。表示他的python代碼如下:

graph={}
graph["Alexmer"]=["Bob"]
graph["Bob"]=["Blue"],["kalin"],["Alexmer"]
graph["kalin"]=["Bob"],["Blue"]
graph["Blue"]=["kalin"],["Blue"]

上面這種寫法只是實現了散列表的一些基本結構,如訪問該節點的判斷還沒寫進去,真正開發的時候要考慮很多情況,這裏只是做一個簡單的參考。

迪傑斯特拉算法(Dijkstra)

迪傑斯特拉算法是由荷蘭計算機科學家狄克斯特拉於1959 年提出的,因此又叫狄克斯特拉算法。是從一個頂點到其餘各頂點的最短路徑算法,解決的是有權圖中最短路徑問題。迪傑斯特拉算法主要特點是以起始點爲中心向外層層擴展,直到擴展到終點爲止。在我們用上面的廣度優先搜索來求最短路徑問題的時候,我們忽略了一個問題,就是時間,雖然從A-B-D-F是路徑最短的,但是時間並不是最短的。
在這裏插入圖片描述
假設我們從A到B需要6分鐘,但是從A到C只需要兩分鐘,再從C到B也需要兩分鐘,那麼我們A-B>A-C-B,但是通過廣度優先搜索的算法我們得到的路徑確是A-B-D-F,這無疑會讓你的路程多耗時兩分鐘(相對A-C-B-D-F而言),下面我們來看一下狄克斯特拉算法是怎麼做的:
在這裏插入圖片描述
Dijkstra主要分爲以下四個步驟:

  1. 找出在“最短時間”內可以到達的節點
  2. 更新一下所需要的“時間”,如上圖從A到B記錄爲6,但是我們後來發現通過了C點到B比較“近”,就把“時間”更新爲4
  3. 重複1,2步驟,更新每個到每個節點所需的“最短時間”
  4. 取目的節點的“最短時間”,計算完成

我們上文的“時間”其實就是權重,廣度優先搜索所使用的不帶權重的用來計算最短路徑的圖我們可以把它叫無權圖,而狄克斯特拉算法所使用的帶權重的圖我們可以把它叫做有權圖。其中,帶有箭頭指向的節點圖我們可以把它叫有向圖,而沒有箭頭指向的圖我們可以把它叫做無向圖,兩個節點的無向圖我們可以把它看做互相指向,構成了一個環形圖,如下圖所示:
在這裏插入圖片描述
很顯然,我們的狄克斯特拉算法並不適用於有環圖,因爲假設從別的節點流入A節點,那麼每次繞環走都會增加權重,所得的路徑不可能爲最短路徑,畢竟我們的狄克斯特拉要走完所有的路徑,所以我們這裏可以得出結論:狄克斯特拉算法只適用於有向無環圖(directed acyclic graph,DAG)

貝爾曼福特算法(Bellman-Ford)

接下來,我們通過狄克斯特拉算法的一個例子來引出我們的貝爾曼福特算法:
在這裏插入圖片描述
跟上面的圖有所出入,這裏我們按照狄克斯特拉的算法來求“最短路徑問題”,可以看出我們從A-B<A-C,所以我們更新了第一次權重A-B,接下來我們再求第二次權重:這次權重計算的有兩個,從C-B和從B-D,可以直接計算出從B-D爲7,C-B爲-2,計算完畢,這裏就更新了從A-D的最短路徑爲13,暫且先不糾結爲什麼從C-B是負的,有的朋友可能會問了,明明我A-C-B只需要5再到D只需要12,爲什麼你計算完畢了,這是因爲狄克斯特拉算法只支持不帶負權邊的圖。同時這也解釋了爲什麼會有負的權重,因爲我們從來計算的都不是最短距離,而只是替代權重的一個說法罷了。而計算這種帶負權邊的圖就需要用到我們接下來要說的貝爾曼福特算法了。

貝爾曼-福特算法(Bellman-Ford)是由理查德·貝爾曼(Richard Bellman) 和 萊斯特·福特 創立的,求解單源最短路徑問題的一種算法。有時候這種算法也被稱爲 Moore-Bellman-Ford 算法,因爲 Edward F. Moore 也爲這個算法的發展做出了貢獻。它的原理是對圖進行V-1次鬆弛操作,得到所有可能的最短路徑。

貝爾曼福特算法支持帶有負權邊的圖,首先來說一下他的鬆弛操作,什麼是鬆弛呢,看過很多文檔,上面都沒有詳細的說明,都是直接進行的鬆弛操作,我的理解是鬆弛就是求所有節點和節點的“距離”,在我的印象中有點類似於笛卡爾積,比如上圖的鬆弛操作爲:求A-B,A-C,B-C,B-D的距離,計算完畢後再求A-C-B是否是否小於A-B,也就是最短路徑,如果小於則更新最短路徑,假設我們的圖節點數量爲V,邊爲E,那麼我們的計算的時間複雜度爲O(V*E),相比狄克斯特拉算法最大的好處就是貝爾曼福特算法可以進行鬆弛操作且支持負權邊的計算。缺點則是時間複雜度過高。像狄克斯特拉算法優先選取沒有被訪問過的節點進行計算,實際上這種計算方法叫做貪婪算法。但是所得的結果並不全面。優點則是計算速度比較快。

計算機科學中,算法的時間複雜度是一個函數,它定性描述了該算法的運行時間。這是一個關於代表算法輸入值的字符串的長度的函數。時間複雜度常用大O符號表述,不包括這個函數的低階項和首項係數。使用這種方式時,時間複雜度可被稱爲是漸近的,它考察當輸入值大小趨近無窮時的情況。

貪心算法(又稱貪婪算法)是指,在對問題求解時,總是做出在當前看來是最好的選擇。也就是說,不從整體最優上加以考慮,他所做出的是在某種意義上的局部最優解。

KNN近鄰算法(k-Nearest Neighbor,KNN)

歡樂的時光總是短暫的,下面我們來看一下這最後一種基本算法,KNN近鄰算法。

K最近鄰(k-Nearest Neighbor,KNN)分類算法,是一個理論上比較成熟的方法,也是最簡單的機器學習算法之一。該方法的思路是:如果一個樣本在特徵空間中的k個最相似(即特徵空間中最鄰近)的樣本中的大多數屬於某一個類別,則該樣本也屬於這個類別。
在這裏插入圖片描述

該算法通常用於做推薦算法。比如某電影APP,方塊用戶代表的是A類用戶,不喜歡恐怖,也不喜歡驚悚的電影。五邊形用戶代表的是喜歡恐怖驚悚的用戶,那麼這時候來了一位新的用戶A,根據A用戶所觀看的電影數據來看,距離方塊用戶比較近而且有兩個方塊鄰居,距離五邊形用戶比較遠,且鄰居節點只有一個,那麼你下次會向該用戶推薦什麼電影呢,很顯然,會推薦一些不恐怖也不驚悚的,比如愛情片,文藝片。再通過愛情,文藝的KNN算法得出該用戶最終喜歡的電影類型。這個問題就是機器學習中的分類問題,根據電影,用戶的數據來對喜好進行分類。

這裏要注意的是KNN算法中,所選擇的鄰居都是已經正確分類的對象。該方法在定類決策上只依據最鄰近的一個或者幾個樣本的類別來決定待分樣本所屬的類別。KNN 算法本身簡單有效,它是一種 lazy-learning 算法,分類器不需要使用訓練集進行訓練,訓練時間複雜度爲0。KNN 分類的計算複雜度和訓練集中的文檔數目成正比,也就是說,如果訓練集中文檔總數爲 n,那麼 KNN 的分類時間複雜度爲O(n)。

其實在我們的生活中,有很多很多都離不開算法,比如早餐店,週一到週五會多準備一些食物,因爲週一到週五上班的人比較多,但是比如週三下雨他就會準備的相對少一點,又比如週四是端午節,很多人放假,他就會少準備一些早餐(因爲很多人不上班早上就不起牀喫早餐),這些都是根據歷史的經驗來判斷的,這裏我們假設工作日爲0,天氣晴爲0,沒有節假日爲0,那麼我們週一賣的食物數量爲A(0,0,0)=200,再假設週二是工作日,天氣陰,不是節假日,我們週二賣出去的食物數量爲B(0,1,0)=150,到了這裏想必你們已經會記錄每天的數據了,也可以根據“經驗”來判斷第二天需要準備的食物的數量了。這類問題在機器學習中叫做迴歸問題,也就是我們基於“經驗”來做的預測問題。

餘弦相似度
前面計算兩位用戶的距離時,使用的都是距離公式。還有更合適的公式嗎?在實際工作中,經常使用 餘弦相似度(cosine similarity)。假設有兩位品味類似的用戶,但其中一位打分時更保守。他們都很喜歡Manmohan Desai的電影Amar Akbar Anthony,但Paul給了5星,而Rowan只給4星。如果你使用距離公式,這兩位用戶可能不是鄰居,雖然他們的品味非常接近。
餘弦相似度不計算兩個矢量的距離,而比較它們的角度,因此更適合處理前面所說的情況。

總結

將KNN近鄰算法作爲最後一個算法來講解是因爲這個算法真的很有用,其實大體上的算法都是算一下係數啊,權重啊,來讓機器進行學習,因爲計算機只懂得這種語言,我們通過經驗來將數據轉換爲計算機的語言來讓計算機進行學習,這裏我們已經接觸了機器學習的第一個例子:推薦系統,希望大家可以去多瞭解一下機器學習的知識,最後還是要強調一下機器學習的三個門檻:

  1. 數學基礎
  2. 典型機器學習算法
  3. 編程基礎

本文對這三個門檻都沒有進行詳細的講解,因爲這些知識都是需要大家不斷的進行學習去累積,才能應用到真正的機器學習,而不是像作者一樣只會“紙上談兵”,哈哈,路漫漫其修遠兮,吾將上下而求索。

參考文獻

  • 深度學習(DEEP LEARNING)
  • 算法圖解(Algorithmic Graphics)
  • AI基礎入門(AI Foundation)
  • 百度百科(hhaha)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章