赞
踩
近邻算法(k-Nearest Neighbors,简称k-NN)是一种常用的机器学习算法,用于分类和回归问题。它的基本思想是根据样本之间的相似性来进行预测。在分类问题中,k-NN算法会将待预测样本的k个最近邻样本的标签进行统计,然后将出现次数最多的标签作为预测结果。在回归问题中,k-NN算法会将待预测样本的k个最近邻样本的标签进行加权平均,然后将得到的平均值作为预测结果。
计算待预测样本与每个训练样本之间的距离。常用的距离度量方法包括欧氏距离、曼哈顿距离等。
根据距离的大小,选择与待预测样本最近的k个训练样本。
统计k个最近邻样本中各类别的出现次数(对于分类问题)或计算k个最近邻样本的加权平均(对于回归问题)。
如果是分类问题,选择出现次数最多的标签作为预测结果;如果是回归问题,将加权平均作为预测结果。
k-NN算法的优点是简单、易于理解和实现。它不需要进行模型的训练,直接使用训练样本进行预测。因此,k-NN算法适用于数据量较小、特征维度较低的问题。然而,k-NN算法的计算复杂度较高,特别是当训练样本数量较大时,需要计算大量的距离。此外,k-NN算法对于噪声数据较为敏感,因此需要进行数据清洗和特征选择的工作。
在应用k-NN算法时,需要注意以下几点:
选择合适的k值:k值的选择会对算法的性能产生影响。较小的k值会使算法对噪声数据更敏感,较大的k值会使算法更加平滑,但可能忽略了局部结构。
特征归一化:在计算距离时,需要将特征进行归一化,以避免某些特征对距离的计算产生过大的影响。
处理数据不平衡问题:如果训练样本的类别分布存在不平衡情况,例如某一类样本数量较少,需要对样本进行采样或调整权重,以保证算法的性能。
下面是一个使用Python实现k-NN算法的简单示例:
- import numpy as np
- from collections import Counter
-
- # 计算两个样本之间的欧氏距离
- def euclidean_distance(x1, x2):
- return np.sqrt(np.sum((x1 - x2)**2))
-
- # k-NN算法
- def k_nearest_neighbors(X_train, y_train, X_test, k):
- y_pred = []
-
- for test_sample in X_test:
- # 计算测试样本与所有训练样本之间的距离
- distances = [euclidean_distance(test_sample, train_sample) for train_sample in X_train]
-
- # 按照距离从小到大排序,并取出前k个样本的索引
- k_indices = np.argsort(distances)[:k]
-
- # 根据索引找到对应的标签
- k_labels = [y_train[i] for i in k_indices]
-
- # 统计标签出现的次数,选择出现次数最多的标签作为预测结果
- most_common = Counter(k_labels).most_common(1)
- y_pred.append(most_common[0][0])
-
- return y_pred
-
- # 使用示例
- X_train = np.array([[1, 2], [3, 4], [5, 6], [7, 8]])
- y_train = np.array([0, 0, 1, 1])
- X_test = np.array([[2, 3], [6, 7]])
-
- k = 2
- y_pred = k_nearest_neighbors(X_train, y_train, X_test, k)
- print(y_pred)

上述代码中,我们定义了一个euclidean_distance
函数来计算两个样本之间的欧氏距离。然后,我们实现了k_nearest_neighbors
函数来执行k-NN算法。在该函数中,我们首先计算测试样本与训练样本之间的距离,然后按照距离排序并取出前k个最近邻样本的索引。接下来,我们根据索引找到对应的标签,并统计出现次数最多的标签作为预测结果。最后,我们使用示例数据对算法进行了简单的测试。
请注意,这只是一个简单示例,实际应用中可能需要考虑更多的因素,如特征归一化、处理数据不平衡等。另外,这里的示例是针对分类问题,如果是回归问题,需要做相应的修改,例如计算加权平均值作为预测结果。
以下是一个使用Java实现k-NN算法的简单示例:
- import java.util.*;
-
- public class KNN {
-
- // 计算两个样本之间的欧氏距离
- public static double euclideanDistance(double[] x1, double[] x2) {
- double sum = 0.0;
- for (int i = 0; i < x1.length; i++) {
- sum += Math.pow(x1[i] - x2[i], 2);
- }
- return Math.sqrt(sum);
- }
-
- // k-NN算法
- public static int[] kNearestNeighbors(double[][] X_train, int[] y_train, double[][] X_test, int k) {
- int[] y_pred = new int[X_test.length];
-
- for (int i = 0; i < X_test.length; i++) {
- double[] test_sample = X_test[i];
-
- // 计算测试样本与所有训练样本之间的距离
- double[] distances = new double[X_train.length];
- for (int j = 0; j < X_train.length; j++) {
- distances[j] = euclideanDistance(test_sample, X_train[j]);
- }
-
- // 按照距离从小到大排序,并取出前k个样本的索引
- int[] k_indices = new int[k];
- for (int j = 0; j < k; j++) {
- k_indices[j] = j;
- }
- for (int j = k; j < distances.length; j++) {
- double maxDistance = distances[k_indices[0]];
- int maxIndex = 0;
- for (int l = 1; l < k; l++) {
- if (distances[k_indices[l]] > maxDistance) {
- maxDistance = distances[k_indices[l]];
- maxIndex = l;
- }
- }
- if (distances[j] < maxDistance) {
- k_indices[maxIndex] = j;
- }
- }
-
- // 根据索引找到对应的标签
- int[] k_labels = new int[k];
- for (int j = 0; j < k; j++) {
- k_labels[j] = y_train[k_indices[j]];
- }
-
- // 统计标签出现的次数,选择出现次数最多的标签作为预测结果
- Map<Integer, Integer> labelCounts = new HashMap<>();
- for (int label : k_labels) {
- labelCounts.put(label, labelCounts.getOrDefault(label, 0) + 1);
- }
- int mostCommon = -1;
- int maxCount = -1;
- for (Map.Entry<Integer, Integer> entry : labelCounts.entrySet()) {
- if (entry.getValue() > maxCount) {
- mostCommon = entry.getKey();
- maxCount = entry.getValue();
- }
- }
-
- y_pred[i] = mostCommon;
- }
-
- return y_pred;
- }
-
- // 使用示例
- public static void main(String[] args) {
- double[][] X_train = {{1, 2}, {3, 4}, {5, 6}, {7, 8}};
- int[] y_train = {0, 0, 1, 1};
- double[][] X_test = {{2, 3}, {6, 7}};
- int k = 2;
-
- int[] y_pred = kNearestNeighbors(X_train, y_train, X_test, k);
-
- for (int label : y_pred) {
- System.out.println(label);
- }
- }
-
- }

上述代码中,我们定义了一个euclideanDistance
方法来计算两个样本之间的欧氏距离。然后,我们实现了kNearestNeighbors
方法来执行k-NN算法。在该方法中,我们首先计算测试样本与训练样本之间的距离,然后按照距离排序并取出前k个最近邻样本的索引。接下来,我们根据索引找到对应的标签,并统计出现次数最多的标签作为预测结果。最后,我们使用示例数据对算法进行了简单的测试。
请注意,这只是一个简单示例,实际应用中可能需要考虑更多的因素,如特征归一化、处理数据不平衡等。另外,这里的示例是针对分类问题,如果是回归问题,需要做相应的修改,例如计算加权平均值作为预测结果。
以下是一个使用MATLAB实现k-NN算法的简单示例:
- function y_pred = k_nearest_neighbors(X_train, y_train, X_test, k)
- % 计算两个样本之间的欧氏距离
- euclidean_distance = @(x1, x2) sqrt(sum((x1 - x2).^2));
-
- % 初始化预测结果数组
- y_pred = zeros(size(X_test, 1), 1);
-
- % 对每个测试样本进行预测
- for i = 1:size(X_test, 1)
- test_sample = X_test(i, :);
-
- % 计算测试样本与所有训练样本之间的距离
- distances = zeros(size(X_train, 1), 1);
- for j = 1:size(X_train, 1)
- distances(j) = euclidean_distance(test_sample, X_train(j, :));
- end
-
- % 按照距离从小到大排序,并取出前k个样本的索引
- [~, k_indices] = mink(distances, k);
-
- % 根据索引找到对应的标签
- k_labels = y_train(k_indices);
-
- % 统计标签出现的次数,选择出现次数最多的标签作为预测结果
- label_counts = histcounts(k_labels, unique(y_train));
- [~, max_idx] = max(label_counts);
- y_pred(i) = label_counts(max_idx);
- end
- end
-
- % 使用示例
- X_train = [1 2; 3 4; 5 6; 7 8];
- y_train = [0; 0; 1; 1];
- X_test = [2 3; 6 7];
- k = 2;
-
- y_pred = k_nearest_neighbors(X_train, y_train, X_test, k);
-
- disp(y_pred);

上述代码中,我们定义了一个匿名函数euclidean_distance
来计算两个样本之间的欧氏距离。然后,我们实现了k_nearest_neighbors
函数来执行k-NN算法。在该函数中,我们首先计算测试样本与训练样本之间的距离,然后按照距离排序并取出前k个最近邻样本的索引。接下来,我们根据索引找到对应的标签,并统计出现次数最多的标签作为预测结果。最后,我们使用示例数据对算法进行了简单的测试。
请注意,这只是一个简单示例,实际应用中可能需要考虑更多的因素,如特征归一化、处理数据不平衡等。另外,这里的示例是针对分类问题,如果是回归问题,需要做相应的修改,例如计算平均值作为预测结果。
以下是一个使用Python实现k-NN算法和其他常见近邻算法(包括最近邻、半径最近邻、KD树)的代码对比:
- from sklearn.neighbors import KNeighborsClassifier, NearestNeighbors, RadiusNeighborsClassifier, KDTree
- from sklearn.datasets import load_iris
- from sklearn.model_selection import train_test_split
- from sklearn.metrics import accuracy_score
-
- # 加载鸢尾花数据集
- iris = load_iris()
- X = iris.data
- y = iris.target
-
- # 划分数据集
- X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
-
- # k-NN算法
- knn = KNeighborsClassifier(n_neighbors=3)
- knn.fit(X_train, y_train)
- y_pred_knn = knn.predict(X_test)
- accuracy_knn = accuracy_score(y_test, y_pred_knn)
-
- # 最近邻算法
- nn = NearestNeighbors(n_neighbors=3)
- nn.fit(X_train)
- distances, indices = nn.kneighbors(X_test)
-
- # 半径最近邻算法
- rnn = RadiusNeighborsClassifier(radius=1.0)
- rnn.fit(X_train, y_train)
- y_pred_rnn = rnn.predict(X_test)
- accuracy_rnn = accuracy_score(y_test, y_pred_rnn)
-
- # KD树算法
- tree = KDTree(X_train)
- distances, indices = tree.query(X_test, k=3)
-
- print("k-NN Accuracy:", accuracy_knn)
- print("Radius Neighbors Accuracy:", accuracy_rnn)

在上述代码中,我们首先使用sklearn
库加载了鸢尾花数据集,并将数据集划分为训练集和测试集。然后,我们分别使用KNeighborsClassifier
、NearestNeighbors
、RadiusNeighborsClassifier
和KDTree
实现了k-NN、最近邻、半径最近邻和KD树算法。接着,我们使用训练集拟合模型,并使用测试集进行预测。最后,我们使用accuracy_score
计算了每个算法的准确率,并输出结果进行对比。
请注意,这里只是一个简单示例,实际应用中可能需要根据具体问题选择合适的算法,并进行参数调优和性能评估。
总结来说,k-NN算法是一种简单而有效的机器学习算法,适用于小规模和低维度的问题。它的原理简单,但需要注意调整参数和处理数据不平衡问题。
##欢迎关注交流,开发逆商潜力,提升个人反弹力:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。