老闆:來了,老弟!python
我:來了來了。算法
老闆:今天你要去看看KNN了,而後我給你安排一個工做!機器學習
我:好嘞!就是第二章嗎?函數
老闆:對!去吧!性能
可惡的老闆又給我安排任務了!學習
《機器學習實戰》這本書中的第二章爲咱們介紹了K-近鄰算法,這是本書中第一個機器學習算法,它很是有效並且易於掌握,因此能夠算是入門級算法了。測試
那咱們如今就一塊兒去學習一下!網站
簡單的說,k-近鄰算法採用測量不一樣特徵值之間的距離進行分類。3d
其工做原理是:code
其實,光看概念,仍是比較抽象的。那麼接下來,咱們來看一個例子(原諒我思惟沒有那麼豐富,就給你們說一下書中的例子吧,但我稍微作了一些修改,使其更形象一些)。書中的例子也不難,就是一個簡單的電影題材分類問題。
老闆:小韓啊,看完KNN的原理了吧?
我:看完了!
老闆:那我先給你一個簡單的任務。
我:≧ ﹏ ≦
老闆:你先去預測一下新上映的電影《諾手的愛情》是什麼題材的。
我:(啥,這是什麼鬼?)沒問題沒問題!
老闆給了一個已知電影題材的數據集,這也就是咱們的訓練樣本集,其中只有兩種類型的電影:愛情片和動做片。好,第一步,咱們先來看看數據:
電影名稱 | 打鬥鏡頭 | 接吻鏡頭 | 電影類型 |
---|---|---|---|
蓋倫的愛情 | 3 | 104 | 愛情片 |
蓋倫的愛情2 | 2 | 100 | 愛情片 |
蓋倫的愛情3 | 1 | 81 | 愛情片 |
諾手VS奧特曼 | 101 | 10 | 動做片 |
諾手VS葫蘆娃 | 99 | 5 | 動做片 |
諾手VS豬豬俠 | 98 | 2 | 動做片 |
諾手的愛情 | 18 | 90 | ??? |
咱們如今知道每部電影的兩個特徵,一個是打鬥鏡頭次數,一個是接吻鏡頭次數。那麼,根據KNN的原理,咱們就須要計算《蓋倫VS諾手》,也就是未知電影與樣本集中其餘電影的距離。咱們先不看怎麼計算距離(後面算會提供),咱們先來看結果。
電影名稱 | 與未知電影的距離 |
---|---|
蓋倫的愛情 | 20.5 |
蓋倫的愛情2 | 18.7 |
蓋倫的愛情3 | 19.2 |
諾手VS奧特曼 | 115.3 |
諾手VS葫蘆娃 | 117.4 |
諾手VS豬豬俠 | 118.9 |
好了,通過一番計算,咱們獲得了樣本集中全部電影與未知電影的距離,按照距離遞增排序,能夠找到k個距離最近的電影。
咱們假設k=3,那麼距離最近的三部電影分別是:蓋倫的愛情,蓋倫的愛情2,蓋倫的愛情3。這三部電影都是愛情片,因此咱們斷定《諾手的愛情》是愛情片!
Bingo!!!老闆說,加雞腿!!!
好了,老闆也加雞腿了,流程也走完了,放假了!!!等等,好像少了點啥???少了代碼怎麼行!!!
老闆佈置了新的任務,用Python代碼實現K-近鄰算法。沒事,不要慌,慢慢來
首先,新建一個名爲kNN.py的文件,寫入如下代碼:
from numpy import * import operator def createDataSet(): group = array([[1.0, 1.1], [1.0, 1.0], [0, 0], [0, 0.1]]) labels = ['A', 'A', 'B', 'B'] return group, labels
在上面的代碼中,咱們導入了兩個模塊:第一個是科學計算包NumPy;第二個是運算符模塊,k-近鄰算法執行排序操做時將使用這個模塊提供的函數。
createDataSet()函數,顧名思義,咱們能夠看出,這個函數用來建立數據集,與此同時,也建立了對應的標籤。group就是咱們的數據集,而每一條數據對應的類別標籤就是labels。
接下來,寫好代碼後,咱們先測試一下。無論你用什麼電腦,咱們都先進入python交互式環境,而後輸入下列命令導入上面編輯的程序模塊:
>>> import kNN
而後,咱們繼續輸入如下命令,建立兩個變量,分別表明數據集和標籤。
>>> group, labels = kNN.createDataSet()
在python命令提示符下,輸入變量的名字以檢驗是否正確的定義變量:
>>> group array([[1. , 1.1], [1. , 1. ], [0. , 0. ], [0. , 0.1]])
>>> labels ['A', 'A', 'B', 'B']
這裏定義了4組數據,每組數據有兩個咱們已知的屬性或者特徵值。上面的group矩陣每行包含一個不一樣的數據,因爲人類大腦的限制, 咱們一般只能可視化處理三維如下的事務。所以爲了簡單地實現數據可視化,對於每一個數據點我 們一般只使用兩個特徵。
向量labels包含了每一個數據點的標籤信息,labels包含的元素個數等於group矩陣行數。這裏咱們將數據點(1, 1.1)定義爲類A,數據點(0, 0.1)定義爲類B。爲了說明方便,例子中的數值是任意選擇的,並無給出軸標籤,圖2-2是帶有類標籤信息的四個數據點。
表格形式:
數據點 | 特徵1 | 特徵2 | 類別 |
---|---|---|---|
1 | 1.0 | 1.1 | A |
2 | 1.0 | 1.0 | A |
3 | 0 | 0 | B |
4 | 0 | 0.1 | B |
圖表形式(引用書中內容):
好了,咱們已經知道了Python如何解析數據、加載數據以及kNN算法的工做原理,接下來咱們就用這些方法編寫KNN分類算法。
首先,咱們先來看一下k-近鄰算法的僞代碼:
對未知類別屬性的數據集中的每一個點依次執行如下操做: (1) 計算已知類別數據集中的點與當前點之間的距離; (2) 按照距離遞增次序排序; (3) 選取與當前點距離最小的k個點; (4) 肯定前k個點所在類別的出現頻率; (5) 返回前k個點出現頻率最高的類別做爲當前點的預測分類。
而後,咱們再來看一下實際的Python代碼:
# inX: 分類的輸入向量 # dataSet: 輸入的訓練樣本集 # labels: 標籤向量 # k: 選擇最近鄰居的數目 def classify0(inX, dataSet, labels, k): # 1.計算距離,這裏採用的是歐式距離 dataSetSize = dataSet.shape[0] # 獲取數據集大小,也就是有多少條數據 diffMat = tile(inX, (dataSetSize, 1)) - dataSet # 將待測試數據擴展 sqDiffMat = diffMat ** 2 # 差值矩陣中,矩陣元素分別平方 sqDistances = sqDiffMat.sum(axis = 1) # 橫向求和,獲得矩陣 distances = sqDistances ** 0.5 # 矩陣中,每一個元素都開方 sortedDistIndicies = distances.argsort() # 距離排序 # 2.選擇距離最小的k個點 classCount = {} for i in range(k): voteIlabel = labels[sortedDistIndicies[i]] classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1 # 3.排序 sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=Ture) return sortedClassCount[0][0]
上述代碼中有幾點須要解釋一下,也是我在學習的過程當中查閱相關資料的地方。
第一,tile函數:
Numpy的 tile() 函數,就是將原矩陣橫向、縱向地複製。
定義原矩陣:
>>> originMat = array([[1, 3], [2, 4]])橫向:
>>> tile(originMat, 4) array([[1, 3, 1, 3, 1, 3, 1, 3], [2, 4, 2, 4, 2, 4, 2, 4]])縱向:
>>> tile(originMat, (3, 1)) array([[1, 3], [2, 4], [1, 3], [2, 4], [1, 3], [2, 4]])橫向 + 縱向:
>>> tile(originMat, (3, 2)) array([[1, 3, 1, 3], [2, 4, 2, 4], [1, 3, 1, 3], [2, 4, 2, 4], [1, 3, 1, 3], [2, 4, 2, 4]])
第二,歐式距離,兩個點的歐式距離公式以下:
$$
d = \sqrt{(x_1 - x_2)^2 + (y_1 - y_2)^2}
$$
第三,分組後的排序。將classCount字典分解爲元組列表,而後使用程序第二行導入運算符模塊的itemgetter方法,按照第二個元素的次序對元組進行排序 。此處的排序爲逆序,即從大到小排序。
到如今爲止,咱們已經構造了第一個分類器,使用這個分類器能夠完成不少分類任務。從這個實例出發,構造使用分類算法將會更加容易。
搞定!!!老闆此次給咱們加了一瓶可樂!!!有雞腿有可樂!!!美滋滋!!!
咱們在老闆的安排下,已經使用k-近鄰算法構造了第一個分類器,也能夠檢驗分類器給出的答案是否符合咱們的預期。
可是,分類器並不會獲得百分百正確的結果,咱們可使用多種方法檢測分類器的正確率。 此外分類器的性能也會受到多種因素的影響,如分類器設置和數據集等。不一樣的算法在不一樣數據集上的表現可能徹底不一樣。
那麼,問題來了,咱們該如何測試分類器的效果呢?其中一種方法就是錯誤率。這是一種比較經常使用的評估方法,主要用於評估分類器在某個數據集上的執行效果。後面咱們還會遇到更加適合的方法來測試分類器,但這裏咱們先只介紹錯誤率。
$$
錯誤率 = \frac {分類器給出錯誤結果的次數} {預測執行的總數}
$$
咱們在已知答案的數據上進行測試,固然答案不能告訴分類器,檢驗分類器給出的結果是否符合預期結果。簡單點說,咱們用KNN訓練出來了一個分類器,而後咱們再把訓練集丟到分類器裏面,看看分類器的分類效果。
到如今,老闆給出的任務咱們也完成了,代碼也寫了一部分,也掌握了kNN算法的基本使用,仍是很開心的!!
可是,老闆又來了。
老闆:小韓啊,你這個分類器卻是出來了,可是隻在你本身捏造的數據集上運行,不行啊!!
我:(什麼?敢說個人算法不行!!!)
老闆:這樣吧,明天我給你安排一個實在一點的任務,去改進一下約會網站的配對效果。
我:約會網站?聽起來不錯啊!那加雞腿不?
老闆:不加!!!
我: ̄へ ̄,老闆,我先下班了,明天見!!!
最後,歡迎你們關注個人公衆號,有什麼問題也能夠給我留言哦!