Машинное обучение — алгоритм регрессии KNN (практика машинного обучения)

машинное обучение

«Это 11-й день моего участия в ноябрьском испытании обновлений, ознакомьтесь с подробностями события: [Испытание последнего обновления 2021 года] (nuggets.capable/post/702364… "nuggets.capable/post/702364…

В этой статье будет подробно объяснена проблема измерения в алгоритме KNN, чтобы получить глубокое понимание того, как KNN реализует проблему регрессии.

Алгоритм KNN

(Практика машинного обучения) Алгоритм K-ближайшего соседа использует для классификации метод измерения расстояния между разными собственными значениями. Как это работает: уже существует набор выборочных данных, обучающий набор, и у каждого данных в обучающем наборе есть соответствующая метка классификации. После ввода новых данных без меток каждый признак новых данных сравнивается с признаками, соответствующими данным в выборке, а затем алгоритм извлекает классификационные метки данных с наиболее похожими характеристиками в выборке. То есть посмотрите на метки k ближайших данных и сделайте это большинством голосов.

выбор метрики расстояния

Евклидово расстояние: евклидова метрика (также известная как евклидово расстояние) — это обычно используемое определение расстояния, которое относится к истинному расстоянию между двумя точками в ?-мерном пространстве или к вектору естественной длины (то есть к расстоянию от этой точки до Происхождение). Евклидово расстояние в 2D и 3D пространстве — это фактическое расстояние между двумя точками.

Дистанционная формула:image.png

Манхэттенское расстояние: представьте, что вы едете от одного перекрестка к другому по городской дороге.Является ли расстояние вождения расстоянием по прямой между двумя точками? По-видимому, нет, если только вы не сможете пройти через здание. Фактическое расстояние вождения - это «Манхэттенское расстояние». Отсюда и название Манхэттенское расстояние, также известное как расстояние городского квартала.

Формула расстояния:image.png

Расстояние Чебышева (Cebyshev Distance): Расстояние между двумя точками определяется как максимальное значение абсолютной величины разности их координат. Расстояние Чебышева между двумя позициями на шахматной доске — это количество ходов, которое необходимо сделать королю, чтобы перейти из одной позиции в другую. Поскольку король может двигаться на одно поле по диагонали вперед или по диагонали назад, он может более эффективно достигать целевого поля.

Формула расстояния:image.png

Расстояние Минковского: наиболее часто используется расстояние Минковского, когда ? принимает значение 1 или 2. ? = 2 — евклидово расстояние, а ? = 1 — манхэттенское расстояние. Когда ? достигает предела бесконечности, можно получить расстояние Чебышева.

image.png

Расстояние Хэмминга: Расстояние Хэмминга используется при кодировании с контролем ошибок при передаче данных.Расстояние Хэмминга представляет собой понятие, которое представляет количество битов, соответствующих двум словам (одинаковой длины).Расстояние Хэмминга между ними. Выполните операцию XOR для двух строк и подсчитайте количество единиц, тогда это число будет расстоянием Хэмминга.

Формула расстояния:image.png

Косинусное сходство: когда два вектора имеют одинаковое направление, значение косинусного сходства равно 1; когда угол между двумя векторами равен 90°, значение косинусного сходства равно 0; когда два вектора указывают в строго противоположных направлениях, значение косинусного сходства равен 0. Сходство имеет значение -1. Предполагая, что ? и ? являются двумя ?-мерными векторами, ? есть ?1, ?2,..., ?? и ? есть ?1, ?2,..., ??, тогда косинус угла между ? и ? равен:

image.png

алгоритм выбора knn

кд деление дерева:

KD-дерево (K-Dimension Tree), также известное как K-мерное дерево, может делить пространство с более высокой эффективностью, а его структура очень удобна для поиска ближайших соседей и обнаружения столкновений. Предполагая, что есть 6 двумерных точек данных, процесс построения дерева KD: ? = { (2,3), (5,7), (9,6), (4,5), (6,4) , (7 ,2)}.

1. Начиная с оси ?, согласно значениям оси ? 2, 5, 9, 4, 6, 7, медиана равна 6, поэтому разделительная линия: ? = 6.

2. В соответствии с дисперсией данных по оси ? и оси ? в качестве первого витка оси деления может быть выбрана ось с наибольшей дисперсией.

Левое подпространство (обозначаемое как ?1) содержит точки (2,3), (4,5), (5,7), а ось деления вращается, начиная с оси ?, а линия деления: ? = 5 .

Правое подпространство (вспомним ?2) содержит точки (9, 6), (7, 2), вращение отрезанного вала, отделенное от вала, линия разреза: ? = 6.

3. Левое подпространство ?1 (обозначается как ?3) содержит точку (2,3), а ось деления вращается, начиная с оси x, а линия деления: ? = 2.

Его левое подпространство обозначается ?7 , а правое подпространство обозначается ?8 . Так как ?7 , ?8 не содержат точек, мы не продолжаем разбивать по ним.

Правое подпространство ?1 (обозначается как ?4) содержит точку (5,7), а ось деления вращается, начиная с оси x, а линия деления: ? = 5.

Его левое подпространство обозначается ?9, а правое подпространство обозначается ?10. Поскольку ?9 и ?10 не содержат точек, мы не будем продолжать их разбивать.

4. Левое подпространство ?2 (обозначается как ?5) содержит точку (7,2), а ось деления вращается, начиная с оси x, а линия деления: ? = 7.

Его левое подпространство обозначается ?11, а правое подпространство обозначается ?12. Поскольку ?11, ?12 не содержат точек, мы не продолжаем их разбивать.

Правое подпространство ?2 (обозначаемое как ?6) не содержит точек, поэтому прекратите расщепление.

Блок-схема выглядит следующим образом:

图片.png

поиск по дереву kd

1. Сначала найдите листовой узел целевой точки, затем возьмите целевую точку в качестве центра и расстояние от целевой точки до конечного узла в качестве радиуса, чтобы установить гиперсферу, Ближайшая соседняя точка, которую мы хотим найти, должна находиться внутри сферы.

При поиске ближайшего соседа (4,4). Во-первых, начните с корневого узла (6,4), установите текущего ближайшего соседа на (6,4) и выполните обход дерева KD в глубину. Нарисуйте окружность с (4,4) в качестве центра и расстоянием от (6,4) в качестве радиуса (многомерное пространство является гиперсферой).Видно, что площадь в правой части (7, 2) не пересекается с окружностью, поэтому ( 7,2) и все правые поддеревья игнорируются.

2. Вернитесь к родительскому узлу листового узла и проверьте, пересекает ли гиперпрямоугольник, содержащийся в другом дочернем узле, гиперсферу.Если пересекает, перейдите к этому дочернему узлу, чтобы узнать, есть ли более близкий сосед, и если да, обновите ближайший сосед.

Затем перейдите к левому корневому узлу поддерева (4,5) из (6,4), после сравнения расстояния с исходным ближайшим соседом обновите текущий ближайший сосед до (4,5). Нарисуйте окружность с (4,4) в качестве центра и расстоянием от (4,5) в качестве радиуса.Обнаружено, что площадь справа от (6,4) не пересекается с окружностью, и все узлы на этой стороне игнорируются, так что (6,4) помечен как игнорируемый.

3. Если пересечения нет, вернуться непосредственно к родительскому узлу и продолжить поиск ближайшего соседа в другом поддереве.

4. При возврате к корневому узлу алгоритм завершается, и ближайший соседний узел, сохраненный в это время, является окончательным ближайшим соседом. После обхода левого и правого листовых узлов (4,5) обнаруживается, что расстояние равно текущему оптимальному расстоянию, а ближайший сосед не обновляется. Таким образом, ближайшим соседом (4,4) является (4,5).

图片.png

KNN-регрессия

Регрессия с использованием алгоритма knn

Для новой выборки в качестве прогнозируемого значения используется среднее значение меток ее ? ближайших соседей обучающих выборок.

Внедрение тестов классификации рукописных цифр

Реализовано с использованием алгоритма knn, инкапсулированного в библиотеке sklearn. Картинки рукописных цифр выглядят следующим образом:

image.png

image.png

import numpy as np
from os import listdir
from sklearn.neighbors import KNeighborsClassifier as KNN

"""
函数说明:将32x32的二进制图像转换为1x1024向量
"""


def img2vector(filename):
    # 创建1x1024零向量
    returnVect = np.zeros((1, 1024))
    # 打开文件
    fr = open(filename)
    # 按行读取
    for i in range(32):
        # 读一行数据
        lineStr = fr.readline()
        # 每一行的前32个元素依次添加到returnVect中
        for j in range(32):
            returnVect[0, 32 * i + j] = int(lineStr[j])
    # 返回转换后的1x1024向量
    return returnVect


"""
函数说明:手写数字分类测试
"""


def handwritingClassTest():
    # 训练集的Labels
    hwLabels = []
    # 返回trainingDigits目录下的文件名
    trainingFileList = listdir('trainingDigits')
    # 返回文件夹下文件的个数
    m = len(trainingFileList)
    # 初始化训练的Mat矩阵,训练集
    trainingMat = np.zeros((m, 1024))
    # 从文件名中解析出训练集的类别
    for i in range(m):
        # 获得文件的名字
        fileNameStr = trainingFileList[i]
        # 获得分类的数字
        classNumber = int(fileNameStr.split('_')[0])
        # 将获得的类别添加到hwLabels中
        hwLabels.append(classNumber)
        # 将每一个文件的1x1024数据存储到trainingMat矩阵中
        trainingMat[i, :] = img2vector('trainingDigits/%s' % (fileNameStr))
    # 构建kNN分类器
    neigh = KNN(n_neighbors=3, algorithm='kd_tree')
    # 拟合模型, trainingMat为训练矩阵,hwLabels为对应的标签
    neigh.fit(trainingMat, hwLabels)
    # 返回testDigits目录下的文件列表
    testFileList = listdir('testDigits')
    # 错误检测计数
    errorCount = 0.0
    # 测试数据的数量
    mTest = len(testFileList)
    # 从文件中解析出测试集的类别并进行 分类测试
    for i in range(mTest):
        # 获得文件的名字
        fileNameStr = testFileList[i]
        # 获得分类的数字
        classNumber = int(fileNameStr.split('_')[0])
        # 获得测试集的1x1024向量,用于训练
        vectorUnderTest = img2vector('testDigits/%s' % (fileNameStr))
        # 获得预测结果
        classifierResult = neigh.predict(vectorUnderTest)
        print("分类返回结果为%d\t真实结果为%d" % (classifierResult, classNumber))
        if (classifierResult != classNumber):
            errorCount += 1.0
    print("总共错了%d个数据\n错误率为%f%%" % (errorCount, errorCount / mTest * 100))


"""
函数说明:main函数
"""
if __name__ == '__main__':
    handwritingClassTest()

Используйте алгоритм как kd-дерево.

Прогнозируемый результат:

image.png