"Machine Learning Formula Derivation and Code Implementation" chapitre 6-k Algorithme du plus proche voisin

Notes d'étude "Machine Learning Formula Derivation and Code Implementation", enregistrez votre propre processus d'apprentissage, veuillez acheter le livre de l'auteur pour un contenu détaillé.

k algorithme du plus proche voisin

L'algorithme des k plus proches voisins ( k-nearest neighbor, k-NN) est un algorithme de classification classique. L'algorithme des k plus proches voisins détermine la classification d'une nouvelle instance d'entrée selon la catégorie des k instances les plus proches voisines. Par conséquent, l'algorithme k-plus proche voisin n'a pas de processus d'apprentissage et de formation explicite comme les algorithmes d'apprentissage automatique traditionnels. De ce fait, l'implémentation de l'algorithme du k plus proche voisin est légèrement différente du modèle de régression décrit dans les chapitres précédents. k值的选择, 距离度量方式et 分类决策规则sont les trois éléments de l'algorithme du k plus proche voisin.

1 Méthode de mesure des distances

Afin de mesurer la similarité entre deux instances dans l'espace des caractéristiques, nous utilisons la distance pour la décrire. Les mesures de distance couramment utilisées incluent 闵氏距离etc.马氏距离

(1) 闵氏距离Autrement dit 闵可夫斯基距离( Minkowski distance), la distance est définie comme suit, étant donné un mensemble d'échantillons vectoriels dimensionnels X, pour xi, xjX, xi= (x1i,x2i,...xmi)T, alors la distance de Min entre l'échantillon xi et l'échantillon xj peut être définie comme suit :
dij = ( ∑ k = 1 m ∣ xki − xkj ∣ p ) 1 p , p ≥ 1 d_{ij}=\left ( \sum_{k=1}^{m}\left | x_{ki}-x_{kj} \right | ^ {p} \right )^{\frac{1}{p} }, p\ge 1dje=(k = 1m∣x _pourXkjp )p1,p1
On voit facilement qu'à p=1ce moment闵氏距离il devient曼哈顿距离(Manhatan distance) :
dij = ∑ k = 1 m ∣ xki − xkj ∣ d_{ij}=\sum_{k=1}^{m}\left | x_{ki }-x_{kj} \right |dje=k = 1m∣x _pourXkj∣A
ce momentp=2 ,闵氏距离il devient欧氏距离(Euclidean distance) :
dij = ( ∑ k = 1 m ∣ xki − xkj ∣ 2 ) 1 2 d_{ij}=\left ( \sum_{k=1}^{m}\left | x_ {ki}-x_{kj} \right | ^{2} \right )^{\frac{1}{2} }dje=(k = 1m∣x _pourXkj2 )21
A cette époquep=∞ , 闵氏距离on l'appelle aussi 切比雪夫距离( Chebyshev distance) :
dij = max ∣ xki − xkj ∣ d_{ij}=max\left | x_{ki}-x_{kj} \right |dje=ma x∣x _pourXkj
(2)马氏距离Le nom complet马哈拉诺比斯距离(Mahalanobis distance), est une méthode de mesure de regroupement pour mesurer la corrélation entre diverses caractéristiques. Étant donné un ensemble d'échantillonsX=(xij)mxn, en supposant que la matrice de covariance de l'échantillon estS, alors la distance de Mahalanobis entre l'échantillon xi et l'échantillon xj peut être définie comme suit :
dij = [ ( xi − xj ) TS − 1 ( xi − xj ) ] 1 2 d_ {ij}=\left [\left(x_{i}-x_{j}\right)^{T} S^{-1}\left(x_{i}-x_{j}\right)\right] ^{\fra{1}{2}}dje=[ ( xjeXje)JS1( xjeXje) ]21
Lorsqu'il Ss'agit d'une matrice d'identité, c'est-à-dire lorsque les caractéristiques de l'échantillon sont indépendantes les unes des autres et que la variance est de 1, la distance de Mahalanobis est la distance euclidienne.

L'espace des caractéristiques de l'algorithme du k plus proche voisin est un espace vectoriel de nombres réels à n dimensions, et la distance euclidienne est généralement utilisée directement comme mesure de distance entre les instances.

Le principe de base de l'algorithme du plus proche voisin 2k

Étant donné un ensemble d'apprentissage, pour une nouvelle instance d'entrée, recherchez les k voisins les plus proches de l'instance dans l'ensemble d'apprentissage, à quelle classe appartient la majorité des k instances et à quelle classe appartient l'instance. Par conséquent, quelques points clés sont résumés :

  • Trouvez l'instance qui est la voisine la plus proche de cette instance. Voici comment la trouver. Généralement, la distance euclidienne est utilisée.
  • Il y a k instances, comment choisir la taille de k.
  • A quelle catégorie appartient la majorité des k instances ?Généralement, la règle de classement du vote majoritaire est retenue.

Parmi les trois points clés, nous devons prêter attention à la sélection de la valeur k. Lorsque la valeur k est petite, le résultat de la prédiction sera très sensible à l'instance et le classificateur a une faible capacité anti-bruit, qui est sujette à surajustement ; si la valeur de k est grande, la classification correspondante L'erreur augmentera et le modèle global deviendra plus simple, ce qui entraînera un certain degré de sous-ajustement. Généralement, la validation croisée est utilisée pour sélectionner la valeur k appropriée.

knn et k-means
k近邻法 ( knn) sont une méthode de classification et de régression de base.
k-meansC'est une méthode de regroupement simple et efficace.

3 Implémentation de l'algorithme k plus proche voisin basé sur numpy

Définir la fonction de distance euclidienne entre la nouvelle instance d'échantillon et l'échantillon d'apprentissage

import numpy as np

# 定义欧式距离函数
def compute_distances(X_test, X_train): # 测试样本实例矩阵,训练样本实例矩阵

    num_test = X_test.shape[0] # 45
    num_train = X_train.shape[0] # 105
    dists = np.zeros((num_test, num_train)) # 基于训练和测试维度的欧式距离初始化 45*105
    M = np.dot(X_test, X_train.T) # 测试样本与训练样本的矩阵点乘 45*105
    te = np.square(X_test).sum(axis=1) # 测试样本矩阵平方 45*feature_dim
    tr = np.square(X_train).sum(axis=1) # 训练样本矩阵平方 105*feature_dim
    dists = np.sqrt(-2 * M + tr + np.matrix(te).T) # 计算欧式距离,广播
    return dists # 欧氏距离
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.utils import shuffle

# 加载鸢尾花数据集
iris = datasets.load_iris() # 加载鸢尾花数据集
X, y = shuffle(iris.data, iris.target, random_state=13) # 打乱数据
X = X.astype(np.float32)

offset = int(X.shape[0] * 0.7)
X_train, y_train, X_test, y_test = X[:offset], y[:offset], X[offset:], y[offset:]
y_train = y_train.reshape(-1, 1)
y_test = y_test.reshape(-1, 1)

dists = compute_distances(X_test, X_train)
plt.imshow(dists, interpolation='none')
plt.show()

insérez la description de l'image ici
Fonction de prédiction d'étiquette, y compris la valeur k par défaut et la règle de décision de classification

from collections import Counter

# 标签预测函数
def predict_labels(y_train, dists, k=1): # 训练集标签, 测试集与训练集的欧氏距离, k值

    num_test = dists.shape[0] # 测试样本量
    y_pred = np.zeros(num_test) # 初始化测试集预测结果
    for i in range(num_test):
        closest_y = [] # 初始化最近邻列表
        # 按欧式距离矩阵排序后取索引,并用训练集标签按排序后的索引取值,最后展开列表
        labels = y_train[np.argsort(dists[i, :])].flatten() # argsort函数返回的是数组值从小到大的索引值
        closest_y = labels[0:k] # 取最近的k个值进行计数统计
        c = Counter(closest_y) # Counter
        y_pred[i] = c.most_common(1)[0][0] # 取计数最多的那个类别
    return y_pred # 测试集预测结果
# 尝试对测试集进行预测,在默认k值取1的情况下,观察分类准确率
y_test_pred = predict_labels(y_train, dists, k=10)
y_test_pred = y_test_pred.reshape(-1, 1)
num_correct = np.sum(y_test_pred == y_test) # 找出预测正确的实例
accuracy = float(num_correct / y_test.shape[0])
print(accuracy)
0.9777777777777777

Afin de trouver la valeur k optimale, nous essayons d'utiliser la méthode de validation croisée quintuple pour rechercher

from sklearn.metrics import accuracy_score

num_folds = 5
k_choices = [1, 3, 5, 8, 10, 12, 15, 20, 50, 100]
X_train_folds = np.array_split(X_train, num_folds)
y_train_folds = np.array_split(y_train, num_folds)
k_to_accuracies = dict()

for k in k_choices:
    for fold in range(num_folds):
        # 为传入的训练集单独划分出一个验证集作为测试集
        validation_X_test = X_train_folds[fold]
        validation_y_test = y_train_folds[fold]
        temp_X_train = np.concatenate(X_train_folds[:fold] + X_train_folds[fold + 1:])
        temp_y_train = np.concatenate(y_train_folds[:fold] + y_train_folds[fold + 1:])
        temp_dists = compute_distances(validation_X_test, temp_X_train)
        temp_y_test_pred = predict_labels(temp_y_train, temp_dists, k)
        temp_y_test_pred = temp_y_test_pred.reshape(-1, 1)
        accuracy = accuracy_score(temp_y_test_pred, validation_y_test)
        k_to_accuracies[k] = k_to_accuracies.get(k, []) + [accuracy]
        
# 不同k值下的分类准确率    
for k in k_to_accuracies:
    for accuracy in k_to_accuracies[k]:
        print(f'k = {
      
      k}, accuracy = {
      
      accuracy}')
k = 1, accuracy = 0.9047619047619048
k = 1, accuracy = 1.0
k = 1, accuracy = 0.9523809523809523
k = 1, accuracy = 0.8571428571428571
k = 1, accuracy = 0.9523809523809523
k = 3, accuracy = 0.8571428571428571
k = 3, accuracy = 1.0
k = 3, accuracy = 0.9523809523809523
k = 3, accuracy = 0.8571428571428571
k = 3, accuracy = 0.9523809523809523
k = 5, accuracy = 0.8571428571428571
k = 5, accuracy = 1.0
k = 5, accuracy = 0.9523809523809523
k = 5, accuracy = 0.9047619047619048
k = 5, accuracy = 0.9523809523809523
k = 8, accuracy = 0.9047619047619048
k = 8, accuracy = 1.0
k = 8, accuracy = 0.9523809523809523
k = 8, accuracy = 0.9047619047619048
k = 8, accuracy = 0.9523809523809523
k = 10, accuracy = 0.9523809523809523
k = 10, accuracy = 1.0
k = 10, accuracy = 0.9523809523809523
k = 10, accuracy = 0.9047619047619048
k = 10, accuracy = 0.9523809523809523
...
k = 100, accuracy = 0.38095238095238093
k = 100, accuracy = 0.3333333333333333
k = 100, accuracy = 0.23809523809523808
k = 100, accuracy = 0.19047619047619047

Tracer des barres d'erreur avec des intervalles de confiance

for k in k_choices:
    accuracies = k_to_accuracies[k]
    plt.scatter([k] * len(accuracies), accuracies)
accuracies_mean = np.array([np.mean(v) for k, v in k_to_accuracies.items()]) # 计算标准差
accuracies_std = np.array([np.std(v) for k, v in k_to_accuracies.items()]) # 计算方差
plt.errorbar(k_choices, accuracies_mean, yerr=accuracies_std) # 误差棒图 
plt.title('cross-validation on k')
plt.xlabel('k')
plt.ylabel('cross_validation accuracy')
plt.show()

insérez la description de l'image ici

4 Réalisation de l'algorithme k plus proche voisin basé sur sklearn

from sklearn.neighbors import KNeighborsClassifier
neigh = KNeighborsClassifier(n_neighbors=10)
neigh.fit(X_train, y_train)
y_pred = neigh.predict(X_test)
y_pred = y_pred.reshape(-1, 1)
accuracy = accuracy_score(y_pred, y_test)
print(accuracy)
0.9777777777777777

Adresse Notebook_Github

Je suppose que tu aimes

Origine blog.csdn.net/cjw838982809/article/details/131365728
conseillé
Classement