1. 程式人生 > >機器學習實戰一(kNN)

機器學習實戰一(kNN)

.com block 個數 indices 操作 來看 空間 計算機 python3

機器學習實戰一(kNN)

跟著老師做一個項目,關於行車記錄儀識別前方車輛,並判斷車距,不太好做。本來是用OpenCV,做著做著,突然發現需要補習一下機器學習的內容。《機器學習實戰(machine learing in action)》這本書買了很久了,當時還是看了很多人推薦,不過到現在才想起翻出來看。第二章kNN的例子剛跟著做完,書裏講的很清楚,代碼條理分明,只不過我是用Python3實現的。具體的過程不再贅述,只是把自己的理解放在這裏。

先來看看書裏第一章的部分。

  1. 機器學習就是把無序的數據轉換成有用的信息。
  2. 機器學習橫跨計算機科學、工程技術和統計學等多個學科。
  3. 機器學習的主要任務,可分為監督學習
    非監督學習:監督學習可用於預測目標變量的值,可分為分類,針對離散型目標變量,和回歸,針對連續型目標變量;非監督學習不預測目標變量的值,將數據劃分為離散的組,則稱為聚類,如果還需要估計數據與每個分組的相似度,則為密度估計
  4. 步驟:
    • 收集數據(前期采集)
    • 準備輸入數據(數據格式化)
    • 分析輸入數據(探索型分析)
    • 訓練算法
    • 測試算法
    • 使用算法

kNN(k-近鄰算法)

優點:精度高、對異常值不敏感、無數據輸入假定

缺點:計算復雜度高、空間復雜度高

適用數據範圍:數值型和標稱型

原理:已知一組數據的屬性值和類別標簽,給定一個輸入數據,判斷所屬類別。kNN的做法是計算輸入數據與所有已知數據的空間距離(歐氏距離),然後從小到大排列,取前k個數據,出現次數最多的類別標簽作為輸入數據的所屬類別。

歐式距離計算:$\sqrt {\left( x-x_{i}\right) ^{2}+\left( y-y_{i}\right) ^{2}+\ldots }$

核心代碼如下:

"""
Created on 2017/12/30 19:13
kNN: k-近鄰算法

Input:  inX: 用於判斷類別的矩陣 (1xN)
        dataSet: 已知類別的數據集向量 (NxM)
        labels: 數據集的標簽 (1xN)
        k: 用於比較的近鄰的數量 (應該是奇數)

Output: 最可能的類標簽


@author: Lucifer
@site: plantree.me
@email: [email protected]
"""
import numpy as np
import os
import operator
# kNN
def classify0(inX, dataSet, labels, k):
    dataSetSize = dataSet.shape[0]
    # np.tile()將inX重復(dataSetSize, 1)次
    diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet
    sqDiffMat = diffMat ** 2
    sqDistances = sqDiffMat.sum(axis=1)
    distances = sqDistances ** 0.5
    # 排序後的索引
    sortedDistanceIndices = distances.argsort()
    classCount = {}
    for i in range(k):
        # 尋找出現次數最的標簽
        voteILabel = labels[sortedDistanceIndices[i]]
        classCount[voteILabel] = classCount.get(voteILabel, 0) + 1
    # 字典的排序
    sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1),
                              reverse=True)
    return sortedClassCount[0][0]

核心的代碼並不算復雜,這裏用到了numpy提供的tile()函數,用於將矩陣橫向或者縱向復制,然後利用numpy中廣播的概念:對於矩陣的操作,會具體到矩陣中每一個元素上,這樣計算效率無疑會很高。

書裏提供的兩個例子:

  • 使用k-近鄰算法改進約會網站的配對效果
  • 手寫識別系統

兩個例子都提供了原始數據,都很有意思,具體代碼詳見我的GitHub。

這兩個例子,有幾點經驗需要學習。

1、數據格式化

第一步,數據的格式化是非常有必要的。因為現在數據來源廣泛,可以來自網絡,可以來自文本文件,也可以來自數據庫,但是具體到算法,輸入數據的格式是固定的,這就有必要進行數據的格式化,但是具體格式化的方式是不固定的,這個要看具體算法輸入的要求,像這裏輸入的數據必須是numpy的array格式,但是數據源是文本文件,這就需要另寫方法來自動執行這些轉換。

2、數據歸一化

不同屬性之間的數據,不具備可對比度,有些尺度相差很大,很影響算法執行的效果,因此在真正的輸入數據到算法之前,需要進行歸一化。其實歸一化也很簡單,方式也不止一種,比如:

newValue = (oldValue - min) / (max - min)

可以看出,歸一化後的數據,範圍落在[-1, 1],而且避免了不同尺度數據造成的偏差。

3、探索型數據分析

說是探索型數據分析,顯得有些專業,其實就是在具體執行機器學習算法之前,先來看看數據長什麽樣子。可以采用一些統計參數,如均值和方差等,另外一種很重要的方式就是可視化,Python中最常見的自然是Matplotlib繪圖庫了,Seaborn也不錯,可以嘗試學學,可以很直觀的看到數據長什麽樣子。

4、訓練集和預測集

通常會將原始數據分割為訓練集和預測集,比如90%的數據作為訓練集,用於訓練模型,剩下10%作為預測集,來預測模型的準確度,由於預測集的預測目標值已知,因此可以通過判斷模型輸出結果與原有結果比較,得出錯誤的數量,然後除以預測集總數,即可得到錯誤率,來表征模型質量。

kNN存在的問題:

  • 訓練樣本數量較大,而且必須保存全部數據集
  • 對數據集中的每個數據計算距離值,計算量較大,十分耗時
  • 無法給出任何數據的基礎結構信息,對於數據的特征並不了解

Next:下一章將使用改率測量方法處理分類問題,即決策樹。


總結:初次接觸機器學習,從數據中挖掘信息聽起來十分誘人,也十分有趣。kNN作為一種比較簡單的算法,單純通過比較與已知數據的距離,這是一種十分別致的思考方式,將屬性放在坐標系空間,然後計算空間距離,方法簡單,實現起來也比較容易。

Reference:https://github.com/plantree/Machine-Learing-In-Action/tree/master/chapter2

機器學習實戰一(kNN)