Алгоритм K-ближайшего соседа для машинного обучения

машинное обучение алгоритм

Алгоритм k-ближайших соседей классифицируется путем измерения расстояния между различными собственными значениями.

Принцип алгоритма k-ближайших соседей

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

k-алгоритм ближайшего соседа

Здесь представлен только прогноз одних новых данных, а прогноз нескольких новых данных одновременно будет дан позже.

Предположим, что имеется обучающая выборка X_train (X_train.shape=(10, 2)), соответствующая метка y_train (y_train.shape=(10,), включая 0, 1), использоватьmatplotlib.pyplotГрафик выглядит следующим образом (зеленые точки представляют маркер 0, красные точки представляют маркер 1):

clipboard.png

Есть новые данные: x (x = np.array([3.18557125, 6.03119673])), нанесенный следующим образом (синие точки):

clipboard.png

Сначала рассчитайте расстояние от x до каждой выборки в X_train, используя формулу расстояния Эйлера:

import math

distances = [math.sqrt(np.sum((x_train - x) ** 2)) for x_train in X_train]

Во-вторых, чтобы выполнить операцию возрастания на расстояниях, используйтеnp.argsort()Метод возвращает отсортированный индекс без какого-либо влияния на порядок исходных данных:

import numpy as np

nearest = np.argsort(distances)

В-третьих, возьмите метки, соответствующие k ближайшим образцам:

topK_y = [y_train[i] for i in nearest[:k]]

Наконец, подсчитайте теги, соответствующие k ближайшим образцам, и найдите прогнозируемую классификацию с наибольшей долей тега, равной x. В этом случае прогнозируемая классификация равна 0:

from collections import Counter

votes = Counter(topK_y)
votes.most_common(1)[0][0]

Оберните приведенный выше код в метод:

import numpy as np
import math

from collections import Counter


def kNN(k, X_train, y_train, x):
    distances = [math.sqrt(np.sum((x_train - x) ** 2)) for x_train in X_train]
    nearest = np.argsort(distances)

    topK_y = [y_train[i] for i in nearest[:k]]
    votes = Counter(topK_y)
    return votes.most_common(1)[0][0]

Алгоритм k-ближайших соседей в Scikit Learn

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

clipboard.png

Для алгоритма k-ближайших соседей это специальный алгоритм без модели, но мы рассматриваем его обучающий набор данных как модель. Вот как это обрабатывается в Scikit Learn.

Алгоритм k-ближайшего соседа, используемый в Scikit Learn

Алгоритм k-neighbor в Scikit Learn находится в модуле Neighbors, а входящий параметр n_neighbors равен 6 во время инициализации, то есть указанному выше k:

from sklearn.neighbors import KNeighborsClassifier

kNN_classifier = KNeighborsClassifier(n_neighbors=6)

fit()Метод «обучает» классификатор на обучающем наборе данных, который возвращает сам классификатор:

kNN_classifier.fit(X_train, y_train)

predict()Метод предсказывает результат ввода, и метод требует, чтобы передаваемый тип параметра был матрицей. Поэтому здесь мы сначала делаем xreshapeработать:

X_predict = x.reshape(1, -1)
y_predict = kNN_classifier.predict(X_predict)

Значение y_predict равно 0, что согласуется с результатом метода kNN, реализованного ранее.

Внедрение классификатора KNeighborsClassifier в Scikit Learn

Определите класс KNNClassifier, метод конструктора которого передает параметр k, представляющий количество наиболее похожих данных, выбранных во время прогнозирования:

class KNNClassifier:
    def __init__(self, k):
        self.k = k
        self._X_train = None
        self._y_train = None

fit()метод обучает классификатор и возвращает сам классификатор:

def fit(self, X_train, y_train):
    self._X_train = X_train
    self._y_train = y_train
    return self

predict()Метод прогнозирует набор данных для проверки, а параметр X_predict имеет тип matrix. Этот метод перебирает X_predict, используя понимание списка, вызывая один раз для каждых тестируемых данных._predict()метод.

def predict(self, X_predict):
    y_predict = [self._predict(x) for x in X_predict]
    return np.array(y_predict)

def _predict(self, x):
    distances = [math.sqrt(np.sum((x_train - x) ** 2))
                 for x_train in self._X_train]
    nearest = np.argsort(distances)

    topK_y = [self._y_train[i] for i in nearest[:self.k]]
    votes = Counter(topK_y)

    return votes.most_common(1)[0][0]

Точность алгоритма

Проблемы с моделью

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

  1. Если модель плоха, прогнозы не те, что нам нужны. При этом в реальных ситуациях получить настоящую этикетку сложно, а протестировать модель невозможно.
  2. Обучающие выборки не содержали всех меток при обучении модели.

Для первого вопроса определенная доля (например, 20%) данных в выборке обычно используется в качестве тестовых данных, а остальные данные используются в качестве обучающих данных.

Возьмем в качестве примера данные радужной оболочки, представленные в Scikit Learn, которые содержат 150 образцов.

import numpy as np
from sklearn import datasets

iris = datasets.load_iris()
X = iris.data
y = iris.target

Теперь разделите выборку на 20% выборочных тестовых данных и 80% данных обучения масштаба:

test_ratio = 0.2
test_size = int(len(X) * test_ratio)

X_train = X[test_size:]
y_train = y[test_size:]

X_test = X[:test_size]
y_test = y[:test_size]

Используйте X_train и y_train в качестве обучающих данных для обучения модели, а X_test и y_test в качестве тестовых данных для проверки точности модели.

Для второго вопроса возьмите в качестве примера данные радужной оболочки, предоставленные в Scikit Learn, содержание метки y:

array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2])

Обнаружено, что по порядку сохраняются 0, 1 и 2. В процессе разделения выборок на обучающие данные и тестовые данные, если в обучающие данные включены только 0 и 1, такие обучающие данные будут фатальными для обучающей модели. . Следовательно, выборочные данные должны быть предварительно обработаны случайным образом.

np.random.permutation()Метод передает целое число n и возвращает случайно отсортированный одномерный массив в интервале [0, n). Передача длины X в качестве параметра возвращает случайный массив индексов X:

shuffle_indexes = np.random.permutation(len(X))

Разделите массив рандомизированных индексов на две части: индекс обучающих данных и индекс тестовых данных:

test_ratio = 0.2
test_size = int(len(X) * test_ratio)

test_indexes = shuffle_indexes[:test_size]
train_indexes = shuffle_indexes[test_size:]

Затем данные выборки делятся на обучающие данные и тестовые данные с помощью индекса, состоящего из двух частей:

X_train = X[train_indexes]
y_train = y[train_indexes]

X_test = X[test_indexes]
y_test = y[test_indexes]

Решение этих двух проблем может быть заключено в метод, начальное число представляет собой начальное число случайного числа, которое действует наnp.randomсередина:

import numpy as np

def train_test_split(X, y, test_ratio=0.2, seed=None):
    if seed:
        np.random.seed(seed)
    shuffle_indexes = np.random.permutation(len(X))

    test_size = int(len(X) * test_ratio)
    test_indexes = shuffle_indexes[:test_size]
    train_indexes = shuffle_indexes[test_size:]

    X_train = X[train_indexes]
    y_train = y[train_indexes]

    X_test = X[test_indexes]
    y_test = y[test_indexes]

    return X_train, X_test, y_train, y_test

Упаковано в Scikit Learntrain_test_split()метод, размещенный в модуле model_selection:

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

Точность алгоритма

пройти черезtrain_test_split()После предварительной обработки выборочных данных метод начинает обучать модель и проверяет тестовые данные:

from sklearn.neighbors import KNeighborsClassifier

kNN_classifier = KNeighborsClassifier(n_neighbors=6)
kNN_classifier.fit(X_train, y_train)
y_predict = kNN_classifier.predict(X_test)

y_predict — это результат прогнозирования тестовых данных X_test, в котором число, равное y_test, деленное на число y_test, является правильной скоростью модели, Сравнивая ее с y_test, можно рассчитать правильную скорость модели:

def accuracy_score(y_true, y_predict):
    return sum(y_predict == y_true) / len(y_true)

Вызовите этот метод, чтобы вернуть число с плавающей запятой, меньшее или равное 1:

accuracy_score(y_test, y_predict)

Также инкапсулирован в модуль метрик Scikit Learn.accuracy_score()метод:

from sklearn.metrics import accuracy_score

accuracy_score(y_test, y_predict)

Родительский класс ClassifierMixin класса KNeighborsClassifier в Scikit Learn имеетscore()метод, который называетсяaccuracy_score()метод, передайте тестовые данные X_test и y_test в качестве параметров в этот метод, и точность алгоритма может быть рассчитана напрямую.

class ClassifierMixin(object):
    def score(self, X, y, sample_weight=None):
        from .metrics import accuracy_score
        return accuracy_score(y, self.predict(X), sample_weight=sample_weight)

Гиперпараметры

Упомянутое в предыдущей статье k — это своего рода гиперпараметр, а гиперпараметр — это параметр, который необходимо определить перед запуском алгоритма. Алгоритм k-ближайшего соседа в Scikit Learn содержит множество гиперпараметров, которые указываются в конструкторе инициализации:

def __init__(self, n_neighbors=5,
             weights='uniform', algorithm='auto', leaf_size=30,
             p=2, metric='minkowski', metric_params=None, n_jobs=None,
             **kwargs):
    # code here

Значение этих гиперпараметров есть в исходниках и официальной документации[scikit-learn.org] описаны.

Преимущества и недостатки алгоритмов

Алгоритм k-ближайших соседей — это относительно простой алгоритм, который имеет свои преимущества, но также и недостатки.

Преимущество в том, что идея проста, но эффект мощный, и он, естественно, подходит для задач с несколькими классификациями.

Недостатком является низкая эффективность, например, если обучающий набор имеет m выборок и n признаков, сложность алгоритма прогнозирования новых данных составляет O (m * n), расстояние между двумя точками также может быть большим, например расстояние между (0,0,0,...,0) и (1,1,1,...,1) (10000 измерений) равно 100.

Адрес источника

Github | ML-Algorithms-Action