小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

刻意練習:機器學習實戰(zhàn) -- Task01. K鄰近算法

 老馬的程序人生 2020-08-17

背景

這是我們?yōu)閾碛?Python 基礎(chǔ)的同學推出的精進技能的“機器學習實戰(zhàn)” 刻意練習活動,這也是我們本學期推出的第三次活動了。

我們準備利用8周時間,夯實機器學習常用算法,完成以下任務(wù):

  • 分類問題:K鄰近算法

  • 分類問題:決策樹

  • 分類問題:樸素貝葉斯

  • 分類問題:邏輯回歸

  • 分類問題:支持向量機

  • 分類問題:AdaBoost

  • 回歸問題:線性回歸、嶺回歸、套索方法、逐步回歸等

  • 回歸問題:樹回歸

  • 聚類問題:K均值聚類

  • 相關(guān)問題:Apriori

  • 相關(guān)問題:FP-Growth

  • 簡化數(shù)據(jù):PCA主成分分析

  • 簡化數(shù)據(jù):SVD奇異值分解

本次任務(wù)的核心是熟悉K鄰近算法的原理,并實現(xiàn)《機器學習實戰(zhàn)》這本書給出的兩個案例。


算法原理

KNN 算法采用測量不同特征之間的距離方法進行分類,通俗的講就是:給定一個樣本數(shù)據(jù)集,并且樣本集中每個數(shù)據(jù)都存在標簽,即我們知道樣本集中每個數(shù)據(jù)與所屬分類的對應(yīng)關(guān)系。對新輸入沒有標簽的實例,在訓練數(shù)據(jù)集中找到與該實例最鄰近的 k 個實例,這 k 個實例的多數(shù)屬于某個類,就把該輸入實例分為這個類。

對于每一個在數(shù)據(jù)集中的數(shù)據(jù)點:
    計算目標的數(shù)據(jù)點(需要分類的數(shù)據(jù)點)與該數(shù)據(jù)點的距離
    將距離排序:從小到大
    選取前 K 個最短距離
    選取這 K 個中最多的分類類別
    返回該類別來作為目標數(shù)據(jù)點的預(yù)測值

項目案例1:優(yōu)化約會網(wǎng)站的配對效果

項目概述

海倫使用約會網(wǎng)站尋找約會對象。經(jīng)過一段時間之后,她發(fā)現(xiàn)曾交往過三種類型的人:

  • 1:不喜歡的人

  • 2:魅力一般的人

  • 3:極具魅力的人

她希望:

  • 不喜歡的人則直接排除掉

  • 工作日與魅力一般的人約會

  • 周末與極具魅力的人約會

現(xiàn)在她收集到了一些約會網(wǎng)站未曾記錄的數(shù)據(jù)信息,這更有助于匹配對象的歸類。

開發(fā)流程

Step1:收集數(shù)據(jù)

此案例書中提供了文本文件。

海倫把這些約會對象的數(shù)據(jù)存放在文本文件 datingTestSet2.txt 中,總共有 1000 行。海倫約會的對象主要包含以下 3 種特征:

  • Col1:每年獲得的飛行??屠锍虜?shù)

  • Col2:玩視頻游戲所耗時間百分比

  • Col3:每周消費的冰淇淋公升數(shù)

文本文件數(shù)據(jù)格式如下:

40920    8.326976    0.953952    3
14488    7.153469    1.673904    2
26052    1.441871    0.805124    1
75136    13.147394   0.428964    1
38344    1.669788    0.134296    1

Step2:準備數(shù)據(jù)

使用 Python 解析文本文件。將文本記錄轉(zhuǎn)換為 NumPy 的解析程序如下所示:

import numpy as np

def file2matrix(filename):
    """
    Desc:
        導入訓練數(shù)據(jù)
    parameters:
        filename: 數(shù)據(jù)文件路徑
    return:
        數(shù)據(jù)矩陣 returnMat 和對應(yīng)的類別 classLabelVector
    """

    fr = open(filename)
    # 獲得文件中的數(shù)據(jù)行的行數(shù)
    lines = fr.readlines()
    numberOfLines = len(lines)  # type: int
    # 生成對應(yīng)的空矩陣
    # 例如:zeros(2,3)就是生成一個 2*3的矩陣,各個位置上全是 0
    returnMat = np.zeros((numberOfLines, 3))  # prepare matrix to return
    classLabelVector = []  # prepare labels return
    index = 0
    for line in lines:
        # str.strip([chars]) --返回已移除字符串頭尾指定字符所生成的新字符串
        line = line.strip()
        # 以 '\t' 切割字符串
        listFromLine = line.split('\t')
        # 每列的屬性數(shù)據(jù)
        returnMat[index, :] = listFromLine[0:3]
        # 每列的類別數(shù)據(jù),就是 label 標簽數(shù)據(jù)
        classLabelVector.append(int(listFromLine[-1]))
        index += 1
    # 返回數(shù)據(jù)矩陣returnMat和對應(yīng)的類別classLabelVector
    return returnMat, classLabelVector

Step3:分析數(shù)據(jù)

使用 Matplotlib 畫二維散點圖。

import matplotlib.pyplot as plt

if __name__ == '__main__':
    datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')
    color = ['r''g''b']
    fig = plt.figure()
    ax = fig.add_subplot(311)
    for i in range(14):
        index = np.where(np.array(datingLabels) == i)
        ax.scatter(datingDataMat[index, 0], datingDataMat[index, 1], c=color[i - 1], label=i)
    plt.xlabel('Col.0')
    plt.ylabel('Col.1')
    plt.legend()
    bx = fig.add_subplot(312)
    for i in range(14):
        index = np.where(np.array(datingLabels) == i)
        bx.scatter(datingDataMat[index, 0], datingDataMat[index, 2], c=color[i - 1], label=i)
    plt.xlabel('Col.0')
    plt.ylabel('Col.2')
    plt.legend()
    cx = fig.add_subplot(313)
    for i in range(14):
        index = np.where(np.array(datingLabels) == i)
        cx.scatter(datingDataMat[index, 1], datingDataMat[index, 2], c=color[i - 1], label=i)
    plt.xlabel('Col.1')
    plt.ylabel('Col.2')
    plt.legend()
    plt.show()

圖中清晰地標識了三個不同的樣本分類區(qū)域,具有不同愛好的人其類別區(qū)域也不同。

歸一化特征值,消除特征之間量級不同導致的影響。

def autoNorm(dataSet):
    """
    Desc:
        歸一化特征值,消除特征之間量級不同導致的影響
    parameter:
        dataSet: 數(shù)據(jù)集
    return:
        歸一化后的數(shù)據(jù)集 normDataSet.ranges和minVals即最小值與范圍,并沒有用到

    歸一化公式:
        Y = (X-Xmin)/(Xmax-Xmin)
        其中的 min 和 max 分別是數(shù)據(jù)集中的最小特征值和最大特征值。該函數(shù)可以自動將數(shù)字特征值轉(zhuǎn)化為0到1的區(qū)間。
    """

    # 計算每種屬性的最大值、最小值、范圍
    minVals = np.min(dataSet, axis=0)
    maxVals = np.max(dataSet, axis=0)
    # 極差
    ranges = maxVals - minVals
    m = dataSet.shape[0]
    # 生成與最小值之差組成的矩陣
    normDataSet = dataSet - np.tile(minVals, (m, 1))
    # 將最小值之差除以范圍組成矩陣
    normDataSet = normDataSet / np.tile(ranges, (m, 1))  # element wise divide
    return normDataSet, ranges, minVals

Step4:訓練算法

此步驟不適用于 k-近鄰算法。因為測試數(shù)據(jù)每一次都要與全部的訓練數(shù)據(jù)進行比較,所以這個過程是沒有必要的。

import operator

def classify0(inX, dataSet, labels, k):
    dataSetSize = dataSet.shape[0]
    # 距離度量 度量公式為歐氏距離
    diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet
    sqDiffMat = diffMat ** 2
    sqDistances = np.sum(sqDiffMat, axis=1)
    distances = sqDistances ** 0.5
    # 將距離排序:從小到大
    sortedDistIndicies = distances.argsort()
    # 選取前K個最短距離, 選取這K個中最多的分類類別
    classCount = {}
    for i in range(k):
        voteIlabel = labels[sortedDistIndicies[i]]
        classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
    sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
    return sortedClassCount[0][0]

Step5:測試算法

計算錯誤率,使用海倫提供的部分數(shù)據(jù)作為測試樣本。如果預(yù)測分類與實際類別不同,則標記為一個錯誤。

def datingClassTest():
    """
    Desc:
        對約會網(wǎng)站的測試方法
    parameters:
        none
    return:
        錯誤數(shù)
    """

    # 設(shè)置測試數(shù)據(jù)的的一個比例
    hoRatio = 0.1  # 測試范圍,一部分測試一部分作為樣本
    # 從文件中加載數(shù)據(jù)
    datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')  # load data setfrom file
    # 歸一化數(shù)據(jù)
    normMat, ranges, minVals = autoNorm(datingDataMat)
    # m 表示數(shù)據(jù)的行數(shù),即矩陣的第一維
    m = normMat.shape[0]
    # 設(shè)置測試的樣本數(shù)量, numTestVecs:m表示訓練樣本的數(shù)量
    numTestVecs = int(m * hoRatio)
    print('numTestVecs=', numTestVecs)
    errorCount = 0.0
    for i in range(numTestVecs):
        # 對數(shù)據(jù)測試
        classifierResult = classify0(normMat[i, :], normMat[numTestVecs:m, :], datingLabels[numTestVecs:m], 3)
        print("分類器返回結(jié)果: %d, 實際結(jié)果: %d" % (classifierResult, datingLabels[i]))
        if classifierResult != datingLabels[i]:
            errorCount += 1.0
    print("錯誤率: %f" % (errorCount / float(numTestVecs)))
    print(errorCount)

Step6:使用算法

產(chǎn)生簡單的命令行程序,然后海倫可以輸入一些特征數(shù)據(jù)以判斷對方是否為自己喜歡的類型。

約會網(wǎng)站預(yù)測函數(shù)如下:

def classifyPerson():
    resultList = ['不喜歡的人''魅力一般的人''極具魅力的人']
    ffMiles = float(input("每年獲得的飛行??屠锍虜?shù)?"))
    percentTats = float(input("玩視頻游戲所耗時間百分比?"))
    iceCream = float(input("每周消費的冰淇淋公升數(shù)?"))
    datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')
    normMat, ranges, minVals = autoNorm(datingDataMat)
    inArr = np.array([ffMiles, percentTats, iceCream])
    intX = (inArr - minVals) / ranges
    classifierResult = classify0(intX, normMat, datingLabels, 3)
    print("這個人屬于: ", resultList[classifierResult - 1])

實際運行效果如下:

if __name__ == '__main__':
    classifyPerson()

'''
每年獲得的飛行常客里程數(shù)? 10000
玩視頻游戲所耗時間百分比? 10
每周消費的冰淇淋公升數(shù)? 0.5
這個人屬于:  魅力一般的人
'''

項目案例2:手寫識別系統(tǒng)

項目概述

構(gòu)造一個能識別數(shù)字 0 到 9 的基于 KNN 分類器的手寫數(shù)字識別系統(tǒng)。

需要識別的數(shù)字是存儲在文本文件中的具有相同的色彩和大小:寬高是 32 像素 * 32 像素的黑白圖像。

開發(fā)流程

Step1:收集數(shù)據(jù)

本案例書中提供了文本文件。

目錄 trainingDigits 中包含了大約 2000 個例子,每個例子內(nèi)容如下圖所示,每個數(shù)字大約有 200 個樣本;目錄 testDigits 中包含了大約 900 個測試數(shù)據(jù)。

Step2:準備數(shù)據(jù)

編寫函數(shù) img2vector(), 將圖像文本數(shù)據(jù)轉(zhuǎn)換為分類器使用的向量。

def img2vector(filename):
    returnVect = np.zeros((11024))
    fr = open(filename)
    for i in range(32):  # 32行
        lineStr = fr.readline()
        for j in range(32):  # 32列
            returnVect[032 * i + j] = int(lineStr[j])
    return returnVect

Step3:分析數(shù)據(jù)

在 Python 命令提示符中檢查數(shù)據(jù),確保它符合要求。

testVector = img2vector(r'./digits/trainingDigits/0_13.txt')
print(testVector[00:32])
# [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  1.  1.  1.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
print(testVector[032:64])
# [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  1.  1.  1.  1.  1.  1.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]

Step4:訓練算法

此步驟不適用于 k-近鄰算法。因為測試數(shù)據(jù)每一次都要與全部的訓練數(shù)據(jù)進行比較,所以這個過程是沒有必要的。

Step5:測試算法

計算錯誤率,編寫函數(shù)使用提供的部分數(shù)據(jù)集作為測試樣本,如果預(yù)測分類與實際類別不同,則標記為一個錯誤。

import os

def handwritingClassTest():
    # 1. 導入訓練數(shù)據(jù)
    hwLabels = []
    trainingFileList = os.listdir(r'./digits/trainingDigits')  # load the training set
    m = len(trainingFileList)
    trainingMat = np.zeros((m, 1024))
    # hwLabels存儲0~9對應(yīng)的index位置, trainingMat存放的每個位置對應(yīng)的圖片向量
    for i in range(m):
        fileNameStr = trainingFileList[i]
        fileStr = fileNameStr.split('.')[0]  # take off .txt
        classNumStr = int(fileStr.split('_')[0])
        hwLabels.append(classNumStr)
        # 將 32*32的矩陣->1*1024的矩陣
        trainingMat[i, :] = img2vector(r'./digits/trainingDigits/%s' % fileNameStr)

    # 2. 導入測試數(shù)據(jù)
    testFileList = os.listdir(r'./digits/testDigits')  # iterate through the test set
    errorCount = 0.0
    mTest = len(testFileList)
    for i in range(mTest):
        fileNameStr = testFileList[i]
        fileStr = fileNameStr.split('.')[0]  # take off .txt
        classNumStr = int(fileStr.split('_')[0])
        vectorUnderTest = img2vector(r'./digits/testDigits/%s' % fileNameStr)
        classifierResult = classify0(vectorUnderTest, trainingMat, hwLabels, 3)
        print("分類器返回結(jié)果: %d, 實際結(jié)果: %d" % (classifierResult, classNumStr))
        if classifierResult != classNumStr:
            errorCount += 1.0
    print("分類錯誤數(shù)量: %d" % errorCount)
    print("分類錯誤率: %f" % (errorCount / float(mTest)))

Step6:使用算法

可以構(gòu)造一個小的軟件系統(tǒng),從圖像中提取數(shù)字,并完成數(shù)字識別,我們現(xiàn)實中使用的OCR,以及車牌識別都類似于這樣的系統(tǒng)。


總結(jié)

到此為止 KNN 算法的兩個案例就全部搞定了,這個算法看起來很簡單,但參數(shù) K 的選擇,距離的選擇都需要不斷的配置和測試才能得到滿意的效果。當然,KNN 算法的主要缺點是不提取訓練數(shù)據(jù)的特征,測試實例需要與每個訓練實例計算距離導致算法的執(zhí)行速度很慢。為了提升搜索 K 個最鄰近實例的速度,后面有了K-D Tree的結(jié)構(gòu),這些都不是這本書的重點了,我們主要是先掌握基本算法,有個武器能處理數(shù)據(jù)再說,等后面實際應(yīng)用的時候再來考慮效率問題。好了,就這樣吧!See You!


參考文獻

  • https://github.com/apachecn/AiLearning/tree/master/docs/ml

  • https://blog.csdn.net/c406495762/column/info/16415

  • https://www.bilibili.com/video/av36993857

  • https://space.bilibili.com/97678687/channel/detail?cid=22486

  • https://space.bilibili.com/97678687/channel/detail?cid=13045


    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多