機器學習(六)-基於KNN分類算法的自動劃分電影的題材類型實現

1 分類算法引言

衆所周知,電影能夠按照題材分類,然而題材自己是如何定義的?由誰來斷定某部電影屬於哪一個題材?也就是說同一題材的電影具備哪些公共特徵?這些都是在進行電影分類時必需要考慮的問題。python

  • 動做片中也會存在接吻鏡頭,愛情片中也會存在打鬥場景,咱們不能單純依靠是否存在打鬥或者親吻來判斷影片的類型。
  • 愛情片中的親吻鏡頭更多,動做片中的打鬥場景也更頻繁,基於此類場景在某部電影中出現的次數能夠用來進行電影分類。

那麼如何基於電影中出現的親吻、打鬥出現的次數,使用k-近鄰算法構造程序,自動劃分電影的題材類型。算法

2 KNN算法及工做原理

k-近鄰(KNN)算法採用測量不一樣特徵值之間的距離方法進行分類。測試

  • 存在一個樣本數據集合,也稱做訓練樣本集,而且樣本集中每一個數據都存在標籤,即咱們知道樣本集中每一數據與所屬分類的對應關係。
  • 輸入沒有標籤的新數據後,將新數據的每一個特徵與樣本集中數據對應的特徵進行比較,而後算法提取樣本集中特徵最類似數據(最近鄰)的分類標籤。

通常來講,咱們只選擇樣本數據集中前k個最類似的數據,一般k是不大於20的整數。最後,選擇k個最類似數據中出現次數最多的分類,做爲新數據的分類。spa

3 KNN的第一個實例:電影的分類

3.1 項目介紹

動做,愛情,喜劇,災難…???code

在這裏插入圖片描述

  • 使用打鬥和接吻鏡頭數分類電影

在這裏插入圖片描述

  • 每部電影的打鬥鏡頭數、接吻鏡頭數以及電影評估類型

在這裏插入圖片描述

  • 已知電影與未知電影的距離

獲得了距離後,選擇前k個電影來判斷未知電影的類型
在這裏插入圖片描述排序

3.2 如何求距離?------歐氏距離公式

  • 二維空間

在這裏插入圖片描述

  • 多維空間

在這裏插入圖片描述

3.3 k-近鄰算法的通常流程

(1) 收集數據:可使用任何方法。
(2) 準備數據:距離計算所須要的數值,最好是結構化的數據格式。
(3) 分析數據:可使用任何方法。
(4) 訓練算法:此步驟不適用於k-近鄰算法。
(5) 測試算法:計算錯誤率。
(6) 使用算法:首先須要輸入樣本數據和結構化的輸出結果,而後運行k-近鄰算法斷定輸
入數據分別屬於哪一個分類,最後應用對計算出的分類執行後續的處理。索引

3.4 數據準備:使用 Python 導入數據

import numpy as np
def createDataSet():
    """建立數據集"""
    # 每組數據包含打鬥數和接吻數;
    group = np.array([[3, 104], [2, 100], [1, 81], [101, 10], [99, 5], [98, 2]])
    # 每組數據對應的標籤類型;
    labels = ['Roman', 'Roman', 'Roman', 'Action', 'Action', 'Action']
    return group, labels

3.5 實施 KNN 算法

對未知類別屬性的數據集中的每一個點依次執行如下操做:
(1) 計算已知類別數據集中的點與當前點之間的距離;
(2) 按照距離遞增次序排序;
(3) 選取與當前點距離最小的k個點;
(4) 肯定前k個點所在類別的出現頻率;
(5) 返回前k個點出現頻率最高的類別做爲當前點的預測分類。圖片

def classify(inx, dataSet, labels, k):
    """
    KNN分類算法實現
    :param inx:要預測電影的數據, e.g.[18, 90]
    :param dataSet:傳入已知數據集,e.g. group 至關於x
    :param labels:傳入標籤,e.g. labels至關於y
    :param k:KNN裏面的k,也就是咱們要選擇幾個近鄰
    :return:電影類新的排序
    """
    dataSetSize = dataSet.shape[0]  # (6,2) -- 6行2列 ===> 6 獲取行數
    # tile會重複inx, 把它重複成(dataSetSize, 1)型的矩陣
    # (x1 - y1), (x2 - y2)
    diffMat = np.tile(inx, (dataSetSize, 1)) - dataSet
    # 平方
    sqDiffMat = diffMat ** 2
    # 相加, axis=1行相加
    sqDistance = sqDiffMat.sum(axis=1)
    # 開根號
    distance = sqDistance ** 0.5
    # 排序索引: 輸出的是序列號index, 而不是值
    sortedDistIndicies = distance.argsort()
    # print(sortedDistIndicies)

    classCount = {}
    for i in range(k):
        # 獲取排前k個的標籤名;
        voteLabel = labels[sortedDistIndicies[i]]
        classCount[voteLabel] = classCount.get(voteLabel, 0) + 1

    sortedClassCount = sorted(classCount.items(),
                              key=lambda d: float(d[1]),
                              reverse=True)
    return sortedClassCount[0]

3.6 如何測試分類器

  • 分類器並不會獲得百分百正確的結果,咱們可使用多種方法檢測分類器的正確率。
  • 爲了測試分類器的效果,咱們可使用已知答案的數據,固然答案不能告訴分類器,檢驗分類器給出的結果是否符合預期結果。ci

    • 完美分類器的錯誤率爲0
    • 最差分類器的錯誤率是1.0

完整代碼rem

import numpy as np


def createDataSet():
    """建立數據集"""
    # 每組數據包含打鬥數和接吻數;
    group = np.array([[3, 104], [2, 100], [1, 81], [101, 10], [99, 5], [98, 2]])
    # 每組數據對應的標籤類型;
    labels = ['Roman', 'Roman', 'Roman', 'Action', 'Action', 'Action']
    return group, labels


def classify(inx, dataSet, labels, k):
    """
    KNN分類算法實現
    :param inx:要預測電影的數據, e.g.[18, 90]
    :param dataSet:傳入已知數據集,e.g. group 至關於x
    :param labels:傳入標籤,e.g. labels至關於y
    :param k:KNN裏面的k,也就是咱們要選擇幾個近鄰
    :return:電影類新的排序
    """
    dataSetSize = dataSet.shape[0]  # (6,2) -- 6行2列 ===> 6 獲取行數
    # tile會重複inx, 把它重複成(dataSetSize, 1)型的矩陣
    # (x1 - y1), (x2 - y2)
    diffMat = np.tile(inx, (dataSetSize, 1)) - dataSet
    # 平方
    sqDiffMat = diffMat ** 2
    # 相加, axis=1行相加
    sqDistance = sqDiffMat.sum(axis=1)
    # 開根號
    distance = sqDistance ** 0.5
    # 排序索引: 輸出的是序列號index, 而不是值
    sortedDistIndicies = distance.argsort()
    # print(sortedDistIndicies)

    classCount = {}
    for i in range(k):
        # 獲取排前k個的標籤名;
        voteLabel = labels[sortedDistIndicies[i]]
        classCount[voteLabel] = classCount.get(voteLabel, 0) + 1

    sortedClassCount = sorted(classCount.items(),
                              key=lambda d: float(d[1]),
                              reverse=True)
    return sortedClassCount[0][0]


if __name__ == '__main__':
    group, label = createDataSet()
    result = classify([3, 104], group, label, 5)
    print("[3, 104]的電影類型:",  result)
  • 效果展現

在這裏插入圖片描述

相關文章
相關標籤/搜索