KNN-Verbesserung und tatsächlicher Kampf

Das Hauptprinzip des K-Nearest Neighbor-Algorithmus wurde im vorherigen Artikel vorgestellt. Es handelt sich um einen sehr einfachen und einfachen Klassifikator. Als Nächstes werden wir hauptsächlich Funktionen und kleine Verbesserungen hinzufügen, um ihn realistischer zu machen. Sehen Sie sich den vorherigen Artikel an. Klicken Sie hier. Alle Daten und Codes beziehen sich auf das Buch „Machine Learning in Practice

.

1. Parsen von Daten aus Textdateien

Angenommen, wir haben eine Textdatei, die Daten jeder Stichprobe belegen eine Zeile, insgesamt 1000 Zeilen, einschließlich 3 Merkmalen: 1. Die
Anzahl der jedes Jahr gesammelten Vielfliegermeilen
2. Der Prozentsatz der Zeit, die mit Videospielen verbracht wird
3. Die pro Woche konsumierten Liter Eiscreme
Einige Daten lauten wie folgt:

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

Die letzte Spalte stellt die Beschriftung dar.
Der Datenkonvertierungscode lautet wie folgt:

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 lautet wie folgt:

[[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]]

datingLabels[:10] lautet wie folgt:

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

2. Daten analysieren

Der Schritt der Datenanalyse ist sehr wichtig. Matplotlib wird hauptsächlich verwendet, um die Daten bis zu einem gewissen Grad zu visualisieren, den Differenzierungsgrad der Daten, den Anteil jedes Teils usw. zu beobachten und Vorschläge für spätere Verbesserungen bereitzustellen. Mit dem folgenden Code können wir den Datensatz visualisieren
:

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()

Das Bild ist wie folgt

3. Datennormalisierung

Durch die Visualisierung können wir die verschiedenen Datenkategorien klar erkennen und ihre Unterscheidung ist immer noch möglich. Bei der Berechnung des Abstands, z. B. beim Berechnen des Abstands zwischen [0, 20000, 1,1, 2] und [67, 32000, 0,1, 2], lautet die Formel jedoch wie folgt:

( 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 . 10 . 1 )2

Es ist ersichtlich, dass der Wert, der den größten Einfluss auf die Entfernung hat, der größte ist. Solche Daten haben eine gewisse Tendenz. Angenommen, wir glauben, dass die drei Merkmale gleich wichtig sind und das gleiche Gewicht haben. Daher müssen sie normalisiert werden.
Hier verwenden wir die Standardisierung der Streuung, um die Daten zu normalisieren. Die Formel zur Standardisierung der Streuung lautet wie folgt:

X ∗ = X − minmax − min X^*={X- min \over max-min}X=m a x m i nX m i n

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

Zu den häufig verwendeten Normalisierungsmethoden gehören neben der Standardisierung der Abweichung auch die Standardabweichungsmethode, die Dezimalkalibrierungsmethode usw.
Die normMat lautet wie folgt:

[[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]]

Es ist ersichtlich, dass die Normalisierung der Ergebnisse die Verteilung der Daten nicht veränderte, sondern die Lücke zwischen den Daten verringerte.

4. Testalgorithmus

Der Testalgorithmus ist ein sehr wichtiger Schritt beim maschinellen Lernen. Er wird verwendet, um die Klassifizierungsleistung des Modells zu messen. Wenn die Leistung nicht gut ist, muss überlegt werden, welche Aspekte zur Optimierung des Modells verwendet werden können.
Normalerweise verwenden wir 90 % des vorhandenen Datensatzes zum Trainieren des Modells und die restlichen 10 % zum Testen des Modells. Beachten Sie, dass es unterschiedliche Methoden zur Aufteilung des spezifischen Testsatzes und Trainingssatzes gibt. Im Allgemeinen gibt es die Hold-Out-Methode, die Selbsthilfemethode, die Kreuzvalidierungsmethode usw. Code wie folgt anzeigen:

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)))

Ausgang:

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

Es ist ersichtlich, dass die Fehlerquote 2 % beträgt, was bedeutet, dass die Genauigkeit des Modells 95 % beträgt, was ein sehr gutes Modell ist.

5. Verwendung von Algorithmen

Nachdem wir die Genauigkeit des Algorithmus getestet haben, können wir Vorhersagen darüber treffen.

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])

Geben Sie nach dem Aufruf von classifyPerson Ihre entsprechenden Informationen ein. Die vorhergesagten Ergebnisse lauten wie folgt:

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. Der vollständige Code lautet wie folgt

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()

Supongo que te gusta

Origin blog.csdn.net/JaysonWong/article/details/105729356
Recomendado
Clasificación