天天看點

【機器學習實戰系列】讀書筆記之KNN算法(三)

本次讀書筆記在于延續上一篇部落格的工程,做出微小的改動,即使用Matplotlib建立散點圖(散點圖使用DataMat矩陣的第一、第二列資料)。

首先還是介紹一個相關知識點,友善代碼浏覽。

知識點一:

1、在使用Matplotlib生成圖表時,預設不支援漢字,所有漢字都會顯示成框框。

解決方法:代碼中指定中文字型

# -*- coding:utf-8 -*-

importmatplotlib.pyplot as plt

import matplotlib

zhfont1 =matplotlib.font_manager.FontProperties(fname='C:/Windows/Fonts/simsun.ttc')

plt.xlabel(u"橫坐标xlabel",fontproperties=zhfont1)

  到C:\Windows\Fonts\中找到新宋體對應的字型檔案simsun.ttf(Window 8和Windows10系統是simsun.ttc,也可以使用其他字型)

下面貼出代碼:

from numpy import *
import knn1


def file2matrix(filename):
    """該函數将約會檔案内容轉換成資料處理格式,傳回一個測試特征集(格式二維數組),和測試集類别集(格式清單)

    """
    fr = open(filename)
    arrayOnLines = fr.readlines()
    numberOfLines = len(arrayOnLines) #擷取 n=樣本的行數
    returnMat = zeros((numberOfLines, 3))   #建立一個2維矩陣用于存放訓練樣本資料,一共有n行,每一行存放3個資料
    classLabel = []  #建立一個1維數組用于存放訓練樣本标簽。
    for i in range(numberOfLines):
        line = arrayOnLines[i]
        line = line.strip()  # 把回車符号給去掉
        listFromLine = line.split('\t') # 把每一行資料用\t分割
        returnMat[i, :] = listFromLine[0:3]  # 把分割好的資料放至資料集,其中i是該樣本資料的下标,就是放到第幾行
        classLabel.append(int(listFromLine[-1]))   # 把該樣本對應的标簽放至标簽集,順序與樣本集對應。
    return returnMat, classLabel


def autoNorm(dataSet):
    """
    該函數将資料集的是以特征歸一化,傳回歸一化後的特征集(格式為數組),特征集最小值(格式為一維數組),特征集範圍(格式為一維數組)

    """
    # 擷取資料集中每一列的最小數值
    # 以createDataSet()中的資料為例,group.min(0)=[0,0]
    minVals = dataSet.min(axis=0)
    # 擷取資料集中每一列的最大數值
    # group.max(0)=[1, 1.1]
    maxVals = dataSet.max(axis=0)
    # 最大值與最小的內插補點
    ranges = maxVals - minVals
    # 建立一個與dataSet同shape的全0矩陣,用于存放歸一化後的資料
    normDataSet = zeros(shape(dataSet))
    dataSize = dataSet.shape[0]
    # 把最小值擴充為與dataSet同shape,然後作差,具體tile請翻看 第三節 代碼中的tile
    normDataSet = dataSet - tile(minVals, (dataSize, 1))
    # 把最大最小內插補點擴充為dataSet同shape,然後作商,是指對應元素進行除法運算,而不是矩陣除法。
    # 矩陣除法在numpy中要用linalg.solve(A,B)
    normDataSet = normDataSet / tile(ranges, (dataSize, 1))
    return normDataSet, minVals, ranges


def dateClassTest(filename, k):
    """
    測試KNN算法對于約會資料的錯誤率

    """
    # 将資料集中10%的資料留作測試用,其餘的90%用于訓練
    ratio = 0.10
    dataSet, labels = file2matrix(filename)
    normDateSet, minVals, ranges = autoNorm(dataSet)
    dataSize = dataSet.shape[0]
    numTestVecs = int(dataSize * ratio)
    errorcount = 0.0
    print("m : %d" % dataSize)
    for i in range(numTestVecs):
        #分别對應前面的 classify(int X, dataSet, labels, k)
        #normDateSet[i, :]對應資料中随機的1000*0.1=100行的資料,normDateSet[numTestVecs:dataSize, :]對應剩下的900行資料
        classifyResult = knn1.classify0(normDateSet[i, :], normDateSet[numTestVecs:dataSize, :], \
                                      labels[numTestVecs:dataSize], k)
        if classifyResult != labels[i]:
            errorcount += 1
        print("the real answer is: %d, the classify answer is: %d" % (labels[i], classifyResult))
    print("the total error ratio is %f" % (errorcount / float(numTestVecs)))


if __name__ == '__main__':
    filename = '/Users/Administrator/Desktop/machine learning inaction/Ch02/datingTestSet2.txt'
    dateClassTest(filename, 3)
    datingDataMat, datingLabels = file2matrix(filename)

    import matplotlib
    import matplotlib.pyplot as plt
    from matplotlib.font_manager import FontProperties

    zhfont = FontProperties(fname='C:/Windows/Fonts/simsun.ttc', size=12)
    # 建立畫闆
    fig = plt.figure()
    # 畫圖之前首先設定figure對象,此函數相當于設定一塊自定義大小的畫布,使得後面的圖形輸出在這塊規定了大小的畫布上,
    # 其中參數figsize設定畫布大小
    plt.figure(figsize=(8, 5), dpi=80)
    # 例子:plt.subplot(221)将figure設定的畫布大小分成幾個部分,參數‘221’表示2(row)x2(colu),即将畫布分成2x2,兩行兩列的4塊區域,
    # 1表示選擇圖形輸出的區域在第一塊,圖形輸出區域參數必須在“行x列”範圍,此處必須在1和2之間選擇
    # 如果參數設定為subplot(111),則表示畫布整個輸出,不分割成小塊區域,圖形直接輸出在整塊畫布上
    ax = plt.subplot(111)

    datingLabels = array(datingLabels)
    idx_1 = where(datingLabels == 1)
    p1 = ax.scatter(datingDataMat[idx_1, 0], datingDataMat[idx_1, 1], marker='*', color='r', label='1', s=10)
    idx_2 = where(datingLabels == 2)
    p2 = ax.scatter(datingDataMat[idx_2, 0], datingDataMat[idx_2, 1], marker='o', color='g', label='2', s=20)
    idx_3 = where(datingLabels == 3)
    p3 = ax.scatter(datingDataMat[idx_3, 0], datingDataMat[idx_3, 1], marker='+', color='b', label='3', s=30)

    plt.xlabel(u'每年擷取的飛行裡程數', fontproperties=zhfont)
    plt.ylabel(u'玩視訊遊戲所消耗的事件百分比', fontproperties=zhfont)
    #loc(設定圖例顯示的位置),'upper left' : 2
    ax.legend((p1, p2, p3), (u'不喜歡', u'魅力一般', u'極具魅力'), loc=2, prop=zhfont)
    plt.show() #顯示
           

然後貼出結果圖:

【機器學習實戰系列】讀書筆記之KNN算法(三)

繼續閱讀