KNNの改善と実戦

K 近傍アルゴリズムの主な原理は、前の記事で紹介しました。これは非常に基本的で単純な分類器です。次に、主に関数を追加し、現実により適したものにするための小さな改良を加えます。前の記事を表示します。ここをクリックしてください。すべてのデータとコードは、書籍「実践的な機械学習」を参照してい
ます

1. テキスト ファイルからのデータの解析

テキスト ファイルがあり、各サンプルのデータが 1 行、合計 1000 行を占めているとします。次の 3 つの特性が含まれます。 1. 毎年獲得されるマイレージ マイルの数 2. ビデオ ゲームのプレイに費やされる時間の割合 3. 1 週間に消費されるアイスクリームのリットル データの一部は次

とおり
です

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
72993  10.141740  1.032955   1

最後の列はラベルを表し、
データ変換コードは次のとおりです。

def file2matrix(filename):
    fr = open(filename)
    # 获取行数
    arrayOLines = fr.readlines()
    numberOflines = len(arrayOLines)
    # print(numberOflines)
    # 构造矩阵
    returnMat = np.zeros((numberOflines, 3))
    # print(returnMat)
    classLabelVector = []
    index = 0
    # 写入矩阵
    for line in arrayOLines:
        # 去除所有的回车字符
        line = line.strip()
        # 数据分割为元素列表
        listFromLine = line.split('\t')
        # print(listFromLine)
        returnMat[index, :] = listFromLine[0: 3]
        classLabelVector.append(int(listFromLine[-1]))
        index += 1
    return returnMat, classLabelVector

returnMat は次のとおりです。

[[4.0920000e+04 8.3269760e+00 9.5395200e-01]
 [1.4488000e+04 7.1534690e+00 1.6739040e+00]
 [2.6052000e+04 1.4418710e+00 8.0512400e-01]
 ...
 [2.6575000e+04 1.0650102e+01 8.6662700e-01]
 [4.8111000e+04 9.1345280e+00 7.2804500e-01]
 [4.3757000e+04 7.8826010e+00 1.3324460e+00]]

日付ラベル[:10]は次のとおりです。

[3, 2, 1, 1, 1, 1, 3, 3, 1, 3]

2. データを分析する

データを分析するステップは非常に重要です。主に matplotlib を使用してデータをある程度視覚化し、データの差別化の度合い、各部分の割合などを観察し、その後の改善のための提案を提供します。次のコードを通じて、データセットを視覚化できます

datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')
# print(datingDataMat)
# print(datingLabels[:10])
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
num = len(datingDataMat)
for i in range(num):
    if datingLabels[i] == 1:
        ax.scatter(datingDataMat[i][0], datingDataMat[i][1], datingDataMat[i][2], c='b', marker='x')
    elif datingLabels[i] == 2:
        ax.scatter(datingDataMat[i][0], datingDataMat[i][1], datingDataMat[i][2], c='r', marker='o')
    elif datingLabels[i] == 3:
        ax.scatter(datingDataMat[i][0], datingDataMat[i][1], datingDataMat[i][2], c='g', marker='*')
plt.show()

写真は次のとおりです

3. データの正規化

視覚化すると、データのさまざまなカテゴリを明確に確認でき、それらを区別することは可能ですが、[0, 20000, 1.1, 2] と [67, 32000, 0.1, 2] の間の距離を計算するなど、距離を計算する場合、式は次のようになります。

( 0 − 67 ) 2 + ( 20000 − 32000 ) 2 + ( 1.1 − 0.1 ) 2 \sqrt{(0-67)^2+(20000-32000)^2+(1.1-0.1)^2}( 06 7 )2+( 2 0 0 0 03 2 0 0 0 )2+( 1.1 _ _0 1 )2

距離に最も大きな影響を与える値が最も大きいことがわかります。このようなデータには一定の傾向があります。3 つの特徴が同等に重要で同じ重みを占めると考えると、正規化する必要があります。
ここでは、分散の標準化を使用してデータを正規化します。分散の標準化の式は次のとおりです。

X ∗ ​​= X − minmax − min X^*={X- min \over max-min}バツ=m a x min _ _X _ _

def autoNorm(dataSet):
    minVals = dataSet.min(0)
    maxVals = dataSet.max(0)
    ranges = maxVals - minVals
    normDataSet = np.zeros(np.shape(dataSet))
    m = dataSet.shape[0]
    normDataSet = dataSet - np.tile(minVals, (m, 1))
    normDataSet = normDataSet/np.tile(ranges, (m, 1))
    return normDataSet, ranges, minVals

偏差の標準化に加えて、一般的に使用される正規化方法には、標準偏差法、10 進校正法などが含まれます。
ノルムマットは次のとおりです。

[[0.44832535 0.39805139 0.56233353]
 [0.15873259 0.34195467 0.98724416]
 [0.28542943 0.06892523 0.47449629]
 ...
 [0.29115949 0.50910294 0.51079493]
 [0.52711097 0.43665451 0.4290048 ]
 [0.47940793 0.3768091  0.78571804]]

結果の正規化によってデータの分布は変化しませんでしたが、データ間のギャップが狭まったことがわかります。

4. テストアルゴリズム

テスト アルゴリズムは機械学習の非常に重要なステップです。モデルの分類パフォーマンスを測定するために使用されます。パフォーマンスが良好でない場合は、どの側面を使用してモデルを最適化できるかを検討する必要があります。
通常、既存のデータセットの 90% をモデルのトレーニングに使用し、残りの 10% をモデルのテストに使用します。特定のテスト セットとトレーニング セットを分割するにはさまざまな方法があることに注意してください。一般的には、ホールドアウト方法、セルフヘルプ方法、交差検証方法などがあります。コードは以下のように表示されます:

def datingClassTest():
    hoRatio = 0.10
    datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')
    normMat, ranges, minVals = autoNorm(datingDataMat)
    m = normMat.shape[0]
    numTestVecs = int(m*hoRatio)
    errorCount = 0.0
    for i in range(numTestVecs):
        classifierResult = classfiy0(normMat[i, :], normMat[numTestVecs:m, :], datingLabels[numTestVecs:m], 3)
        print("the classifier came back with {}, the real answer is : {}".format(classifierResult, datingLabels[i]))
        if classifierResult != datingLabels[i]:
            errorCount += 1.0
    print("the total error rate is {}".format(errorCount/float(numTestVecs)))

出力:

the classifier came back with 3, the real answer is : 3
the classifier came back with 2, the real answer is : 2
...
the classifier came back with 2, the real answer is : 2
the total error rate is 0.05

エラー率が 2% であることがわかります。これは、モデルの精度が 95% であることを意味し、非常に優れたモデルであることがわかります。

5. アルゴリズムの使用

アルゴリズムの精度をテストした後、それについて予測を行うことができます。

def classifyPerson():
    resultList = ['not at all', 'in small doses', 'in large doses']
    percentTats = float(input('percentage of time spent playing video games?'))
    ffMiles = float(input('frequent flier miles earned per year?'))
    iceCream = float(input('liters of ice cream consumed per year?'))
    datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')
    normMat, ranges, minVals = autoNorm(datingDataMat)
    inArr = np.array([ffMiles, percentTats, iceCream])
    classifierResult = classfiy0((inArr - minVals)/ranges, normMat, datingLabels, 3)
    print('you will probably like this person:', resultList[classifierResult - 1])

assignperson を呼び出した後、対応する情報を入力すると、予測結果は次のようになります。

percentage of time spent playing video games?>? 12
frequent flier miles earned per year?>? 20000
liters of ice cream consumed per year?>? 0.1
you will probably like this person: in large doses

6. 完全なコードは次のとおりです。

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import matplotlib
import operator

def classfiy0(inX, dataset, labels, k):
    dataSetSize = dataset.shape[0]
    # print("dataSetSize", dataSetSize)
    diffMat = np.tile(inX, (dataSetSize, 1)) - dataset
    # print("diffMat", diffMat)
    sqDiffMat = diffMat**2
    # print("sqDiffMat", sqDiffMat)
    sqDistances = sqDiffMat.sum(axis=1)
    # print("sqDistances", sqDistances)
    distances = sqDistances**0.5
    sortedDistIndicies = distances.argsort()
    classCount = {
    
    }
    for i in range(k):
        voteILabel = labels[sortedDistIndicies[i]]
        classCount[voteILabel] = classCount.get(voteILabel, 0) + 1
    # print("classCount", classCount)
    sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
    # print("sortedClassCount", sortedClassCount)
    return sortedClassCount[0][0]

def file2matrix(filename):
    fr = open(filename)
    arrayOLines = fr.readlines()
    numberOflines = len(arrayOLines)
    # print(numberOflines)
    returnMat = np.zeros((numberOflines, 3))
    # print(returnMat)
    classLabelVector = []
    index = 0
    for line in arrayOLines:
        line = line.strip()
        listFromLine = line.split('\t')
        # print(listFromLine)
        returnMat[index, :] = listFromLine[0: 3]
        classLabelVector.append(int(listFromLine[-1]))
        index += 1
    return returnMat, classLabelVector

def autoNorm(dataSet):
    minVals = dataSet.min(0)
    maxVals = dataSet.max(0)
    ranges = maxVals - minVals
    normDataSet = np.zeros(np.shape(dataSet))
    m = dataSet.shape[0]
    normDataSet = dataSet - np.tile(minVals, (m, 1))
    normDataSet = normDataSet/np.tile(ranges, (m, 1))
    return normDataSet, ranges, minVals

def datingClassTest():
    hoRatio = 0.50
    datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')
    normMat, ranges, minVals = autoNorm(datingDataMat)
    m = normMat.shape[0]
    numTestVecs = int(m*hoRatio)
    errorCount = 0.0
    for i in range(numTestVecs):
        classifierResult = classfiy0(normMat[i, :], normMat[numTestVecs:m, :], datingLabels[numTestVecs:m], 3)
        print("the classifier came back with {}, the real answer is : {}".format(classifierResult, datingLabels[i]))
        if classifierResult != datingLabels[i]:
            errorCount += 1.0
    print("the total error rate is {}".format(errorCount/float(numTestVecs)))

def classifyPerson():
    resultList = ['not at all', 'in small doses', 'in large doses']
    percentTats = float(input('percentage of time spent playing video games?'))
    ffMiles = float(input('frequent flier miles earned per year?'))
    iceCream = float(input('liters of ice cream consumed per year?'))
    datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')
    normMat, ranges, minVals = autoNorm(datingDataMat)
    inArr = np.array([ffMiles, percentTats, iceCream])
    classifierResult = classfiy0((inArr - minVals)/ranges, normMat, datingLabels, 3)
    print('you will probably like this person:', resultList[classifierResult - 1])
    
classifyPerson()

おすすめ

転載: blog.csdn.net/JaysonWong/article/details/105729356