简体中文 繁體中文 English 日本語 Deutsch 한국 사람 بالعربية TÜRKÇE português คนไทย Français

站内搜索

搜索

活动公告

11-02 12:46
10-23 09:32
通知:本站资源由网友上传分享,如有违规等问题请到版务模块进行投诉,将及时处理!
10-23 09:31
10-23 09:28
通知:签到时间调整为每日4:00(东八区)
10-23 09:26

探索scikit-learn中KNN算法的广泛应用场景从分类到回归的实际案例分析与实践技巧

3万

主题

317

科技点

3万

积分

大区版主

木柜子打湿

积分
31893

财Doro三倍冰淇淋无人之境【一阶】立华奏小樱(小丑装)⑨的冰沙以外的星空【二阶】

发表于 2025-10-3 20:50:01 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
引言

KNN(K-Nearest Neighbors,K近邻)算法是一种基本的分类与回归方法,也是机器学习中最简单直观的算法之一。KNN算法的核心思想是”物以类聚”,即一个样本的类别或属性由其最近的K个邻居决定。作为非参数学习方法,KNN不需要训练过程,是一种”懒惰学习”(Lazy Learning)算法。在scikit-learn库中,KNN算法有完整的实现,可以方便地应用于分类和回归问题。本文将深入探讨KNN算法在分类和回归问题中的广泛应用,通过实际案例分析其使用方法,并分享实践中的优化技巧。

KNN算法在分类问题中的应用

基本原理

KNN分类算法的基本原理是:给定一个训练数据集,对于新的输入实例,在训练集中找到与该实例最邻近的K个实例,这K个实例的多数属于某个类别,就把该输入实例分为这个类别。算法的关键在于如何定义”最近邻”,通常使用距离度量来衡量样本之间的相似性,常用的距离度量包括欧氏距离、曼哈顿距离、闵可夫斯基距离等。

实际案例分析:鸢尾花分类

让我们使用scikit-learn中的KNN分类器来解决一个经典的鸢尾花分类问题。鸢尾花数据集包含3种不同类型的鸢尾花(Setosa、Versicolour和Virginica)的花萼和花瓣的长度和宽度。
  1. # 导入必要的库
  2. import numpy as np
  3. import matplotlib.pyplot as plt
  4. from sklearn import datasets
  5. from sklearn.model_selection import train_test_split
  6. from sklearn.preprocessing import StandardScaler
  7. from sklearn.neighbors import KNeighborsClassifier
  8. from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
  9. import seaborn as sns
  10. # 加载鸢尾花数据集
  11. iris = datasets.load_iris()
  12. X = iris.data
  13. y = iris.target
  14. # 将数据集分为训练集和测试集
  15. X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
  16. # 数据标准化
  17. scaler = StandardScaler()
  18. X_train_scaled = scaler.fit_transform(X_train)
  19. X_test_scaled = scaler.transform(X_test)
  20. # 创建KNN分类器
  21. knn = KNeighborsClassifier(n_neighbors=3)
  22. # 训练模型
  23. knn.fit(X_train_scaled, y_train)
  24. # 预测测试集
  25. y_pred = knn.predict(X_test_scaled)
  26. # 计算准确率
  27. accuracy = accuracy_score(y_test, y_pred)
  28. print(f"Accuracy: {accuracy:.2f}")
  29. # 输出分类报告
  30. print("\nClassification Report:")
  31. print(classification_report(y_test, y_pred, target_names=iris.target_names))
  32. # 绘制混淆矩阵
  33. cm = confusion_matrix(y_test, y_pred)
  34. plt.figure(figsize=(8, 6))
  35. sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=iris.target_names, yticklabels=iris.target_names)
  36. plt.xlabel('Predicted')
  37. plt.ylabel('Actual')
  38. plt.title('Confusion Matrix')
  39. plt.show()
  40. # 寻找最优的K值
  41. k_range = range(1, 31)
  42. k_scores = []
  43. for k in k_range:
  44.     knn = KNeighborsClassifier(n_neighbors=k)
  45.     knn.fit(X_train_scaled, y_train)
  46.     y_pred_k = knn.predict(X_test_scaled)
  47.     k_scores.append(accuracy_score(y_test, y_pred_k))
  48. # 绘制K值与准确率的关系图
  49. plt.figure(figsize=(10, 6))
  50. plt.plot(k_range, k_scores)
  51. plt.xlabel('Value of K for KNN')
  52. plt.ylabel('Testing Accuracy')
  53. plt.title('K Value vs Accuracy')
  54. plt.show()
复制代码

在这个例子中,我们首先加载了鸢尾花数据集,并将其分为训练集和测试集。然后,我们对数据进行了标准化处理,因为KNN算法对特征的尺度敏感。接下来,我们创建了一个KNN分类器,设置K=3,并在训练数据上拟合模型。最后,我们在测试数据上进行预测,并计算了准确率和分类报告。

此外,我们还绘制了混淆矩阵,以直观地查看模型在不同类别上的表现。最后,我们尝试了不同的K值(从1到30),并绘制了K值与准确率的关系图,以帮助我们选择最优的K值。

实践技巧

由于KNN算法基于距离度量,特征的尺度会显著影响算法的结果。因此,在使用KNN之前,通常需要对数据进行标准化或归一化处理。scikit-learn中的StandardScaler或MinMaxScaler可以用于此目的。
  1. from sklearn.preprocessing import StandardScaler, MinMaxScaler
  2. # 标准化:均值为0,方差为1
  3. scaler = StandardScaler()
  4. X_train_scaled = scaler.fit_transform(X_train)
  5. X_test_scaled = scaler.transform(X_test)
  6. # 归一化:将特征缩放到[0,1]范围
  7. normalizer = MinMaxScaler()
  8. X_train_normalized = normalizer.fit_transform(X_train)
  9. X_test_normalized = normalizer.transform(X_test)
复制代码

K值的选择对KNN算法的性能有重要影响。较小的K值可能会导致模型过拟合,而较大的K值可能会导致模型欠拟合。通常,通过交叉验证来选择最优的K值。
  1. from sklearn.model_selection import cross_val_score
  2. # 使用交叉验证选择最优K值
  3. k_range = range(1, 31)
  4. k_scores = []
  5. for k in k_range:
  6.     knn = KNeighborsClassifier(n_neighbors=k)
  7.     scores = cross_val_score(knn, X_train_scaled, y_train, cv=10, scoring='accuracy')
  8.     k_scores.append(scores.mean())
  9. # 找到最优K值
  10. best_k = k_range[np.argmax(k_scores)]
  11. print(f"Best K value: {best_k}")
复制代码

KNN算法可以使用不同的距离度量,如欧氏距离、曼哈顿距离、闵可夫斯基距离等。scikit-learn中的KNeighborsClassifier允许通过metric参数指定距离度量。
  1. # 使用欧氏距离(默认)
  2. knn_euclidean = KNeighborsClassifier(n_neighbors=5, metric='euclidean')
  3. # 使用曼哈顿距离
  4. knn_manhattan = KNeighborsClassifier(n_neighbors=5, metric='manhattan')
  5. # 使用闵可夫斯基距离,p=3
  6. knn_minkowski = KNeighborsClassifier(n_neighbors=5, metric='minkowski', p=3)
复制代码

在标准的KNN算法中,所有K个邻居的投票权重相同。但是,我们可以根据距离的倒数来加权邻居的投票,使得更近的邻居具有更大的影响力。
  1. # 使用距离权重
  2. knn_weighted = KNeighborsClassifier(n_neighbors=5, weights='distance')
复制代码

为了更准确地评估模型的性能,可以使用交叉验证而不是简单的训练-测试分割。
  1. from sklearn.model_selection import cross_val_score
  2. # 使用10折交叉验证评估模型
  3. knn = KNeighborsClassifier(n_neighbors=5)
  4. scores = cross_val_score(knn, X_scaled, y, cv=10, scoring='accuracy')
  5. print(f"Cross-validation accuracy: {scores.mean():.2f} (+/- {scores.std() * 2:.2f})")
复制代码

KNN算法在回归问题中的应用

基本原理

KNN回归算法的基本原理与分类算法类似,但输出的是连续值而不是离散的类别。对于一个新的输入实例,KNN回归算法在训练集中找到与该实例最邻近的K个实例,然后将这K个实例的目标值的平均值(或加权平均值)作为该输入实例的预测值。

实际案例分析:房价预测

让我们使用scikit-learn中的KNN回归器来解决一个房价预测问题。我们将使用加州房价数据集,这是一个包含房屋特征和其中位数价值的数据集。
  1. # 导入必要的库
  2. import numpy as np
  3. import matplotlib.pyplot as plt
  4. from sklearn.datasets import fetch_california_housing
  5. from sklearn.model_selection import train_test_split
  6. from sklearn.preprocessing import StandardScaler
  7. from sklearn.neighbors import KNeighborsRegressor
  8. from sklearn.metrics import mean_squared_error, r2_score, mean_absolute_error
  9. # 加载加州房价数据集
  10. housing = fetch_california_housing()
  11. X = housing.data
  12. y = housing.target
  13. # 将数据集分为训练集和测试集
  14. X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
  15. # 数据标准化
  16. scaler = StandardScaler()
  17. X_train_scaled = scaler.fit_transform(X_train)
  18. X_test_scaled = scaler.transform(X_test)
  19. # 创建KNN回归器
  20. knn_reg = KNeighborsRegressor(n_neighbors=5)
  21. # 训练模型
  22. knn_reg.fit(X_train_scaled, y_train)
  23. # 预测测试集
  24. y_pred = knn_reg.predict(X_test_scaled)
  25. # 计算评估指标
  26. mse = mean_squared_error(y_test, y_pred)
  27. rmse = np.sqrt(mse)
  28. mae = mean_absolute_error(y_test, y_pred)
  29. r2 = r2_score(y_test, y_pred)
  30. print(f"Mean Squared Error: {mse:.2f}")
  31. print(f"Root Mean Squared Error: {rmse:.2f}")
  32. print(f"Mean Absolute Error: {mae:.2f}")
  33. print(f"R² Score: {r2:.2f}")
  34. # 绘制预测值与实际值的散点图
  35. plt.figure(figsize=(10, 6))
  36. plt.scatter(y_test, y_pred, alpha=0.5)
  37. plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], 'r--', lw=2)
  38. plt.xlabel('Actual')
  39. plt.ylabel('Predicted')
  40. plt.title('Actual vs Predicted Values')
  41. plt.show()
  42. # 绘制残差图
  43. residuals = y_test - y_pred
  44. plt.figure(figsize=(10, 6))
  45. plt.scatter(y_pred, residuals, alpha=0.5)
  46. plt.axhline(y=0, color='r', linestyle='--')
  47. plt.xlabel('Predicted Values')
  48. plt.ylabel('Residuals')
  49. plt.title('Residual Plot')
  50. plt.show()
  51. # 寻找最优的K值
  52. k_range = range(1, 31)
  53. k_scores = []
  54. for k in k_range:
  55.     knn_reg = KNeighborsRegressor(n_neighbors=k)
  56.     knn_reg.fit(X_train_scaled, y_train)
  57.     y_pred_k = knn_reg.predict(X_test_scaled)
  58.     k_scores.append(mean_squared_error(y_test, y_pred_k))
  59. # 绘制K值与均方误差的关系图
  60. plt.figure(figsize=(10, 6))
  61. plt.plot(k_range, k_scores)
  62. plt.xlabel('Value of K for KNN')
  63. plt.ylabel('Mean Squared Error')
  64. plt.title('K Value vs MSE')
  65. plt.show()
复制代码

在这个例子中,我们首先加载了加州房价数据集,并将其分为训练集和测试集。然后,我们对数据进行了标准化处理。接下来,我们创建了一个KNN回归器,设置K=5,并在训练数据上拟合模型。最后,我们在测试数据上进行预测,并计算了均方误差、均方根误差、平均绝对误差和R²分数。

此外,我们还绘制了预测值与实际值的散点图,以直观地查看模型的预测性能。我们还绘制了残差图,以检查模型的假设是否满足。最后,我们尝试了不同的K值(从1到30),并绘制了K值与均方误差的关系图,以帮助我们选择最优的K值。

实践技巧

与KNN分类算法一样,KNN回归算法也对特征的尺度敏感,因此需要对数据进行标准化或归一化处理。
  1. from sklearn.preprocessing import StandardScaler
  2. # 标准化数据
  3. scaler = StandardScaler()
  4. X_train_scaled = scaler.fit_transform(X_train)
  5. X_test_scaled = scaler.transform(X_test)
复制代码

K值的选择对KNN回归算法的性能同样重要。较小的K值可能会导致模型对噪声敏感,而较大的K值可能会导致模型过于平滑。通常,通过交叉验证来选择最优的K值。
  1. from sklearn.model_selection import GridSearchCV
  2. # 使用网格搜索选择最优K值
  3. param_grid = {'n_neighbors': range(1, 31)}
  4. knn_reg = KNeighborsRegressor()
  5. grid_search = GridSearchCV(knn_reg, param_grid, cv=5, scoring='neg_mean_squared_error')
  6. grid_search.fit(X_train_scaled, y_train)
  7. print(f"Best K value: {grid_search.best_params_['n_neighbors']}")
复制代码

KNN回归算法也可以使用不同的距离度量,如欧氏距离、曼哈顿距离、闵可夫斯基距离等。
  1. # 使用曼哈顿距离
  2. knn_manhattan = KNeighborsRegressor(n_neighbors=5, metric='manhattan')
复制代码

在标准的KNN回归算法中,所有K个邻居的贡献相同。但是,我们可以根据距离的倒数来加权邻居的贡献,使得更近的邻居具有更大的影响力。
  1. # 使用距离权重
  2. knn_weighted = KNeighborsRegressor(n_neighbors=5, weights='distance')
复制代码

对于高维数据,KNN算法可能会受到”维度灾难”的影响。在这种情况下,可以考虑使用特征选择或降维技术,如主成分分析(PCA)。
  1. from sklearn.decomposition import PCA
  2. # 使用PCA降维
  3. pca = PCA(n_components=0.95)  # 保留95%的方差
  4. X_train_pca = pca.fit_transform(X_train_scaled)
  5. X_test_pca = pca.transform(X_test_scaled)
  6. # 在降维后的数据上使用KNN
  7. knn_pca = KNeighborsRegressor(n_neighbors=5)
  8. knn_pca.fit(X_train_pca, y_train)
  9. y_pred_pca = knn_pca.predict(X_test_pca)
  10. mse_pca = mean_squared_error(y_test, y_pred_pca)
  11. print(f"MSE with PCA: {mse_pca:.2f}")
复制代码

KNN算法的参数调优

K值的选择

K值是KNN算法中最重要的参数,它决定了用于预测的邻居数量。选择合适的K值对算法的性能至关重要。
  1. from sklearn.model_selection import cross_val_score
  2. import matplotlib.pyplot as plt
  3. # 创建一个KNN分类器
  4. knn = KNeighborsClassifier()
  5. # 尝试不同的K值
  6. k_range = range(1, 31)
  7. k_scores = []
  8. for k in k_range:
  9.     knn.set_params(n_neighbors=k)
  10.     scores = cross_val_score(knn, X_train_scaled, y_train, cv=10, scoring='accuracy')
  11.     k_scores.append(scores.mean())
  12. # 绘制K值与交叉验证准确率的关系图
  13. plt.figure(figsize=(10, 6))
  14. plt.plot(k_range, k_scores)
  15. plt.xlabel('Value of K for KNN')
  16. plt.ylabel('Cross-Validated Accuracy')
  17. plt.title('K Value vs Accuracy')
  18. plt.show()
  19. # 找到最优的K值
  20. best_k = k_range[np.argmax(k_scores)]
  21. print(f"Best K value: {best_k}")
复制代码

距离度量的选择

KNN算法可以使用不同的距离度量来计算样本之间的距离。常见的距离度量包括欧氏距离、曼哈顿距离、闵可夫斯基距离等。
  1. # 使用欧氏距离(默认)
  2. knn_euclidean = KNeighborsClassifier(n_neighbors=5, metric='euclidean')
  3. # 使用曼哈顿距离
  4. knn_manhattan = KNeighborsClassifier(n_neighbors=5, metric='manhattan')
  5. # 使用闵可夫斯基距离,p=3
  6. knn_minkowski = KNeighborsClassifier(n_neighbors=5, metric='minkowski', p=3)
  7. # 使用余弦相似度
  8. knn_cosine = KNeighborsClassifier(n_neighbors=5, metric='cosine')
复制代码

权重函数的选择

在标准的KNN算法中,所有K个邻居的投票权重相同。但是,我们可以根据距离的倒数来加权邻居的投票,使得更近的邻居具有更大的影响力。
  1. # 使用均匀权重(默认)
  2. knn_uniform = KNeighborsClassifier(n_neighbors=5, weights='uniform')
  3. # 使用距离权重
  4. knn_distance = KNeighborsClassifier(n_neighbors=5, weights='distance')
复制代码

算法选择

scikit-learn中的KNN算法提供了三种不同的算法来计算最近邻:
  1. # 使用暴力搜索
  2. knn_brute = KNeighborsClassifier(n_neighbors=5, algorithm='brute')
  3. # 使用KD树
  4. knn_kd_tree = KNeighborsClassifier(n_neighbors=5, algorithm='kd_tree')
  5. # 使用球树
  6. knn_ball_tree = KNeighborsClassifier(n_neighbors=5, algorithm='ball_tree')
  7. # 自动选择(默认)
  8. knn_auto = KNeighborsClassifier(n_neighbors=5, algorithm='auto')
复制代码

KNN算法在大数据集上的优化策略

当处理大规模数据集时,标准的KNN算法可能会面临计算效率和内存限制的问题。以下是一些优化策略:

1. 使用KD树或球树

KD树和球树是用于加速最近邻搜索的数据结构。它们通过划分数据空间来减少需要计算距离的样本数量。
  1. # 使用KD树加速
  2. knn_kd_tree = KNeighborsClassifier(n_neighbors=5, algorithm='kd_tree')
  3. # 使用球树加速
  4. knn_ball_tree = KNeighborsClassifier(n_neighbors=5, algorithm='ball_tree')
复制代码

2. 近似最近邻搜索

对于非常大的数据集,可以考虑使用近似最近邻(Approximate Nearest Neighbor, ANN)算法,如局部敏感哈希(Locality-Sensitive Hashing, LSH)或随机投影树(Random Projection Trees)。
  1. # 使用annoy库进行近似最近邻搜索
  2. from annoy import AnnoyIndex
  3. # 创建Annoy索引
  4. f = X_train.shape[1]  # 特征数量
  5. t = AnnoyIndex(f, 'euclidean')
  6. # 添加训练数据到索引
  7. for i, vector in enumerate(X_train):
  8.     t.add_item(i, vector)
  9. # 构建索引
  10. t.build(10)  # 10棵树
  11. # 查询最近邻
  12. indices, distances = t.get_nns_by_vector(X_test[0], 5, include_distances=True)
复制代码

3. 降维

对于高维数据,可以考虑使用降维技术,如主成分分析(PCA)或线性判别分析(LDA),来减少特征数量。
  1. from sklearn.decomposition import PCA
  2. # 使用PCA降维
  3. pca = PCA(n_components=0.95)  # 保留95%的方差
  4. X_train_pca = pca.fit_transform(X_train)
  5. X_test_pca = pca.transform(X_test)
  6. # 在降维后的数据上使用KNN
  7. knn_pca = KNeighborsClassifier(n_neighbors=5)
  8. knn_pca.fit(X_train_pca, y_train)
  9. accuracy = knn_pca.score(X_test_pca, y_test)
  10. print(f"Accuracy with PCA: {accuracy:.2f}")
复制代码

4. 特征选择

通过选择最重要的特征,可以减少特征数量,从而提高KNN算法的效率。
  1. from sklearn.feature_selection import SelectKBest, f_classif
  2. # 选择最重要的10个特征
  3. selector = SelectKBest(f_classif, k=10)
  4. X_train_selected = selector.fit_transform(X_train, y_train)
  5. X_test_selected = selector.transform(X_test)
  6. # 在选择后的特征上使用KNN
  7. knn_selected = KNeighborsClassifier(n_neighbors=5)
  8. knn_selected.fit(X_train_selected, y_train)
  9. accuracy = knn_selected.score(X_test_selected, y_test)
  10. print(f"Accuracy with feature selection: {accuracy:.2f}")
复制代码

5. 并行计算

scikit-learn中的KNN算法支持并行计算,可以通过设置n_jobs参数来使用多个CPU核心。
  1. # 使用所有可用的CPU核心
  2. knn_parallel = KNeighborsClassifier(n_neighbors=5, n_jobs=-1)
复制代码

6. 数据采样

对于非常大的数据集,可以考虑对数据进行采样,以减少训练集的大小。
  1. from sklearn.utils import resample
  2. # 对训练数据进行采样
  3. X_train_sampled, y_train_sampled = resample(X_train, y_train, n_samples=1000, random_state=42)
  4. # 在采样后的数据上使用KNN
  5. knn_sampled = KNeighborsClassifier(n_neighbors=5)
  6. knn_sampled.fit(X_train_sampled, y_train_sampled)
  7. accuracy = knn_sampled.score(X_test, y_test)
  8. print(f"Accuracy with sampling: {accuracy:.2f}")
复制代码

KNN算法与其他算法的比较

KNN vs 决策树
  1. from sklearn.tree import DecisionTreeClassifier
  2. # 比较KNN和决策树在鸢尾花数据集上的性能
  3. # KNN
  4. knn = KNeighborsClassifier(n_neighbors=3)
  5. knn.fit(X_train_scaled, y_train)
  6. knn_accuracy = knn.score(X_test_scaled, y_test)
  7. # 决策树
  8. dt = DecisionTreeClassifier(random_state=42)
  9. dt.fit(X_train, y_train)  # 决策树不需要数据标准化
  10. dt_accuracy = dt.score(X_test, y_test)
  11. print(f"KNN Accuracy: {knn_accuracy:.2f}")
  12. print(f"Decision Tree Accuracy: {dt_accuracy:.2f}")
复制代码

KNN vs 随机森林
  1. from sklearn.ensemble import RandomForestClassifier
  2. # 比较KNN和随机森林在鸢尾花数据集上的性能
  3. # KNN
  4. knn = KNeighborsClassifier(n_neighbors=3)
  5. knn.fit(X_train_scaled, y_train)
  6. knn_accuracy = knn.score(X_test_scaled, y_test)
  7. # 随机森林
  8. rf = RandomForestClassifier(random_state=42)
  9. rf.fit(X_train, y_train)  # 随机森林不需要数据标准化
  10. rf_accuracy = rf.score(X_test, y_test)
  11. print(f"KNN Accuracy: {knn_accuracy:.2f}")
  12. print(f"Random Forest Accuracy: {rf_accuracy:.2f}")
复制代码

KNN vs SVM
  1. from sklearn.svm import SVC
  2. # 比较KNN和SVM在鸢尾花数据集上的性能
  3. # KNN
  4. knn = KNeighborsClassifier(n_neighbors=3)
  5. knn.fit(X_train_scaled, y_train)
  6. knn_accuracy = knn.score(X_test_scaled, y_test)
  7. # SVM
  8. svm = SVC(random_state=42)
  9. svm.fit(X_train_scaled, y_train)  # SVM需要数据标准化
  10. svm_accuracy = svm.score(X_test_scaled, y_test)
  11. print(f"KNN Accuracy: {knn_accuracy:.2f}")
  12. print(f"SVM Accuracy: {svm_accuracy:.2f}")
复制代码

实际应用案例

案例1:手写数字识别

手写数字识别是机器学习中的经典问题,我们可以使用KNN算法来解决这个问题。
  1. from sklearn.datasets import load_digits
  2. from sklearn.model_selection import train_test_split
  3. from sklearn.preprocessing import StandardScaler
  4. from sklearn.neighbors import KNeighborsClassifier
  5. from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
  6. import matplotlib.pyplot as plt
  7. import seaborn as sns
  8. # 加载手写数字数据集
  9. digits = load_digits()
  10. X = digits.data
  11. y = digits.target
  12. # 显示一些数字图像
  13. fig, axes = plt.subplots(2, 5, figsize=(10, 4))
  14. for i, ax in enumerate(axes.ravel()):
  15.     ax.imshow(digits.images[i], cmap='binary')
  16.     ax.set_title(f"Label: {digits.target[i]}")
  17.     ax.axis('off')
  18. plt.tight_layout()
  19. plt.show()
  20. # 将数据集分为训练集和测试集
  21. X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
  22. # 数据标准化
  23. scaler = StandardScaler()
  24. X_train_scaled = scaler.fit_transform(X_train)
  25. X_test_scaled = scaler.transform(X_test)
  26. # 创建KNN分类器
  27. knn = KNeighborsClassifier(n_neighbors=3)
  28. # 训练模型
  29. knn.fit(X_train_scaled, y_train)
  30. # 预测测试集
  31. y_pred = knn.predict(X_test_scaled)
  32. # 计算准确率
  33. accuracy = accuracy_score(y_test, y_pred)
  34. print(f"Accuracy: {accuracy:.2f}")
  35. # 输出分类报告
  36. print("\nClassification Report:")
  37. print(classification_report(y_test, y_pred))
  38. # 绘制混淆矩阵
  39. cm = confusion_matrix(y_test, y_pred)
  40. plt.figure(figsize=(10, 8))
  41. sns.heatmap(cm, annot=True, fmt='d', cmap='Blues')
  42. plt.xlabel('Predicted')
  43. plt.ylabel('Actual')
  44. plt.title('Confusion Matrix')
  45. plt.show()
  46. # 显示一些预测错误的图像
  47. incorrect_indices = np.where(y_pred != y_test)[0]
  48. if len(incorrect_indices) > 0:
  49.     fig, axes = plt.subplots(2, 5, figsize=(10, 4))
  50.     for i, ax in enumerate(axes.ravel()):
  51.         if i < len(incorrect_indices):
  52.             idx = incorrect_indices[i]
  53.             ax.imshow(digits.images[idx + len(X_train)], cmap='binary')
  54.             ax.set_title(f"True: {y_test[idx]}, Pred: {y_pred[idx]}")
  55.         ax.axis('off')
  56.     plt.tight_layout()
  57.     plt.show()
复制代码

案例2:客户流失预测

客户流失预测是商业分析中的重要问题,我们可以使用KNN算法来预测客户是否会流失。
  1. import pandas as pd
  2. from sklearn.model_selection import train_test_split
  3. from sklearn.preprocessing import StandardScaler, LabelEncoder
  4. from sklearn.neighbors import KNeighborsClassifier
  5. from sklearn.metrics import accuracy_score, classification_report, confusion_matrix, roc_curve, auc
  6. import matplotlib.pyplot as plt
  7. import seaborn as sns
  8. # 假设我们有一个客户数据集
  9. # 这里我们创建一个模拟数据集
  10. np.random.seed(42)
  11. n_samples = 1000
  12. # 创建特征
  13. age = np.random.normal(40, 15, n_samples)
  14. income = np.random.normal(50000, 15000, n_samples)
  15. tenure = np.random.randint(1, 72, n_samples)
  16. monthly_charge = np.random.normal(70, 20, n_samples)
  17. usage = np.random.normal(20, 10, n_samples)
  18. # 创建目标变量(客户是否流失)
  19. churn_prob = 1 / (1 + np.exp(-(-5 + 0.01 * age - 0.00002 * income - 0.02 * tenure + 0.03 * monthly_charge - 0.05 * usage)))
  20. churn = np.random.binomial(1, churn_prob)
  21. # 创建DataFrame
  22. data = pd.DataFrame({
  23.     'Age': age,
  24.     'Income': income,
  25.     'Tenure': tenure,
  26.     'MonthlyCharge': monthly_charge,
  27.     'Usage': usage,
  28.     'Churn': churn
  29. })
  30. # 显示数据的前几行
  31. print(data.head())
  32. # 将数据集分为特征和目标
  33. X = data.drop('Churn', axis=1)
  34. y = data['Churn']
  35. # 将数据集分为训练集和测试集
  36. X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
  37. # 数据标准化
  38. scaler = StandardScaler()
  39. X_train_scaled = scaler.fit_transform(X_train)
  40. X_test_scaled = scaler.transform(X_test)
  41. # 创建KNN分类器
  42. knn = KNeighborsClassifier(n_neighbors=5)
  43. # 训练模型
  44. knn.fit(X_train_scaled, y_train)
  45. # 预测测试集
  46. y_pred = knn.predict(X_test_scaled)
  47. y_pred_proba = knn.predict_proba(X_test_scaled)[:, 1]
  48. # 计算准确率
  49. accuracy = accuracy_score(y_test, y_pred)
  50. print(f"Accuracy: {accuracy:.2f}")
  51. # 输出分类报告
  52. print("\nClassification Report:")
  53. print(classification_report(y_test, y_pred))
  54. # 绘制混淆矩阵
  55. cm = confusion_matrix(y_test, y_pred)
  56. plt.figure(figsize=(8, 6))
  57. sns.heatmap(cm, annot=True, fmt='d', cmap='Blues')
  58. plt.xlabel('Predicted')
  59. plt.ylabel('Actual')
  60. plt.title('Confusion Matrix')
  61. plt.show()
  62. # 绘制ROC曲线
  63. fpr, tpr, thresholds = roc_curve(y_test, y_pred_proba)
  64. roc_auc = auc(fpr, tpr)
  65. plt.figure(figsize=(8, 6))
  66. plt.plot(fpr, tpr, color='darkorange', lw=2, label=f'ROC curve (area = {roc_auc:.2f})')
  67. plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')
  68. plt.xlim([0.0, 1.0])
  69. plt.ylim([0.0, 1.05])
  70. plt.xlabel('False Positive Rate')
  71. plt.ylabel('True Positive Rate')
  72. plt.title('Receiver Operating Characteristic (ROC) Curve')
  73. plt.legend(loc="lower right")
  74. plt.show()
  75. # 寻找最优的K值
  76. k_range = range(1, 31)
  77. k_scores = []
  78. for k in k_range:
  79.     knn = KNeighborsClassifier(n_neighbors=k)
  80.     knn.fit(X_train_scaled, y_train)
  81.     y_pred_k = knn.predict(X_test_scaled)
  82.     k_scores.append(accuracy_score(y_test, y_pred_k))
  83. # 绘制K值与准确率的关系图
  84. plt.figure(figsize=(10, 6))
  85. plt.plot(k_range, k_scores)
  86. plt.xlabel('Value of K for KNN')
  87. plt.ylabel('Testing Accuracy')
  88. plt.title('K Value vs Accuracy')
  89. plt.show()
  90. # 找到最优的K值
  91. best_k = k_range[np.argmax(k_scores)]
  92. print(f"Best K value: {best_k}")
  93. # 使用最优K值重新训练模型
  94. knn_best = KNeighborsClassifier(n_neighbors=best_k)
  95. knn_best.fit(X_train_scaled, y_train)
  96. y_pred_best = knn_best.predict(X_test_scaled)
  97. accuracy_best = accuracy_score(y_test, y_pred_best)
  98. print(f"Accuracy with best K: {accuracy_best:.2f}")
复制代码

总结与展望

KNN算法是一种简单而强大的机器学习算法,可以用于分类和回归问题。在scikit-learn库中,KNN算法通过KNeighborsClassifier和KNeighborsRegressor类实现,提供了丰富的参数和选项,可以满足不同场景的需求。

本文详细介绍了KNN算法在分类和回归问题中的应用,包括基本原理、实际案例分析和实践技巧。我们还讨论了KNN算法的优缺点、参数调优方法、在大数据集上的优化策略,以及与其他算法的比较。

尽管KNN算法有一些缺点,如计算复杂度高和内存需求大,但通过适当的优化策略,如使用KD树或球树、降维、特征选择等,可以在一定程度上克服这些问题。

随着机器学习领域的不断发展,KNN算法也在不断演进。例如,近似最近邻搜索算法的发展使得KNN算法可以应用于更大规模的数据集;深度学习与KNN的结合也产生了一些新的算法,如深度KNN(Deep KNN)等。

总的来说,KNN算法是一种值得掌握的机器学习算法,它在许多实际应用中表现出色,特别是在数据量不大、特征维度不高的情况下。通过理解KNN算法的原理和应用技巧,我们可以更好地利用它来解决实际问题。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

频道订阅

频道订阅

加入社群

加入社群

联系我们|TG频道|RSS

Powered by Pixtech

© 2025 Pixtech Team.