引言

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)的花萼和花瓣的长度和宽度。

# 导入必要的库 import numpy as np import matplotlib.pyplot as plt from sklearn import datasets from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.neighbors import KNeighborsClassifier from sklearn.metrics import accuracy_score, classification_report, confusion_matrix import seaborn as sns # 加载鸢尾花数据集 iris = datasets.load_iris() X = iris.data y = iris.target # 将数据集分为训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42) # 数据标准化 scaler = StandardScaler() X_train_scaled = scaler.fit_transform(X_train) X_test_scaled = scaler.transform(X_test) # 创建KNN分类器 knn = KNeighborsClassifier(n_neighbors=3) # 训练模型 knn.fit(X_train_scaled, y_train) # 预测测试集 y_pred = knn.predict(X_test_scaled) # 计算准确率 accuracy = accuracy_score(y_test, y_pred) print(f"Accuracy: {accuracy:.2f}") # 输出分类报告 print("nClassification Report:") print(classification_report(y_test, y_pred, target_names=iris.target_names)) # 绘制混淆矩阵 cm = confusion_matrix(y_test, y_pred) plt.figure(figsize=(8, 6)) sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=iris.target_names, yticklabels=iris.target_names) plt.xlabel('Predicted') plt.ylabel('Actual') plt.title('Confusion Matrix') plt.show() # 寻找最优的K值 k_range = range(1, 31) k_scores = [] for k in k_range: knn = KNeighborsClassifier(n_neighbors=k) knn.fit(X_train_scaled, y_train) y_pred_k = knn.predict(X_test_scaled) k_scores.append(accuracy_score(y_test, y_pred_k)) # 绘制K值与准确率的关系图 plt.figure(figsize=(10, 6)) plt.plot(k_range, k_scores) plt.xlabel('Value of K for KNN') plt.ylabel('Testing Accuracy') plt.title('K Value vs Accuracy') plt.show() 

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

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

实践技巧

1. 数据标准化

由于KNN算法基于距离度量,特征的尺度会显著影响算法的结果。因此,在使用KNN之前,通常需要对数据进行标准化或归一化处理。scikit-learn中的StandardScalerMinMaxScaler可以用于此目的。

from sklearn.preprocessing import StandardScaler, MinMaxScaler # 标准化:均值为0,方差为1 scaler = StandardScaler() X_train_scaled = scaler.fit_transform(X_train) X_test_scaled = scaler.transform(X_test) # 归一化:将特征缩放到[0,1]范围 normalizer = MinMaxScaler() X_train_normalized = normalizer.fit_transform(X_train) X_test_normalized = normalizer.transform(X_test) 

2. 选择合适的K值

K值的选择对KNN算法的性能有重要影响。较小的K值可能会导致模型过拟合,而较大的K值可能会导致模型欠拟合。通常,通过交叉验证来选择最优的K值。

from sklearn.model_selection import cross_val_score # 使用交叉验证选择最优K值 k_range = range(1, 31) k_scores = [] for k in k_range: knn = KNeighborsClassifier(n_neighbors=k) scores = cross_val_score(knn, X_train_scaled, y_train, cv=10, scoring='accuracy') k_scores.append(scores.mean()) # 找到最优K值 best_k = k_range[np.argmax(k_scores)] print(f"Best K value: {best_k}") 

3. 距离度量的选择

KNN算法可以使用不同的距离度量,如欧氏距离、曼哈顿距离、闵可夫斯基距离等。scikit-learn中的KNeighborsClassifier允许通过metric参数指定距离度量。

# 使用欧氏距离(默认) knn_euclidean = KNeighborsClassifier(n_neighbors=5, metric='euclidean') # 使用曼哈顿距离 knn_manhattan = KNeighborsClassifier(n_neighbors=5, metric='manhattan') # 使用闵可夫斯基距离,p=3 knn_minkowski = KNeighborsClassifier(n_neighbors=5, metric='minkowski', p=3) 

4. 加权投票

在标准的KNN算法中,所有K个邻居的投票权重相同。但是,我们可以根据距离的倒数来加权邻居的投票,使得更近的邻居具有更大的影响力。

# 使用距离权重 knn_weighted = KNeighborsClassifier(n_neighbors=5, weights='distance') 

5. 交叉验证

为了更准确地评估模型的性能,可以使用交叉验证而不是简单的训练-测试分割。

from sklearn.model_selection import cross_val_score # 使用10折交叉验证评估模型 knn = KNeighborsClassifier(n_neighbors=5) scores = cross_val_score(knn, X_scaled, y, cv=10, scoring='accuracy') print(f"Cross-validation accuracy: {scores.mean():.2f} (+/- {scores.std() * 2:.2f})") 

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

基本原理

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

实际案例分析:房价预测

让我们使用scikit-learn中的KNN回归器来解决一个房价预测问题。我们将使用加州房价数据集,这是一个包含房屋特征和其中位数价值的数据集。

# 导入必要的库 import numpy as np import matplotlib.pyplot as plt from sklearn.datasets import fetch_california_housing from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.neighbors import KNeighborsRegressor from sklearn.metrics import mean_squared_error, r2_score, mean_absolute_error # 加载加州房价数据集 housing = fetch_california_housing() X = housing.data y = housing.target # 将数据集分为训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42) # 数据标准化 scaler = StandardScaler() X_train_scaled = scaler.fit_transform(X_train) X_test_scaled = scaler.transform(X_test) # 创建KNN回归器 knn_reg = KNeighborsRegressor(n_neighbors=5) # 训练模型 knn_reg.fit(X_train_scaled, y_train) # 预测测试集 y_pred = knn_reg.predict(X_test_scaled) # 计算评估指标 mse = mean_squared_error(y_test, y_pred) rmse = np.sqrt(mse) mae = mean_absolute_error(y_test, y_pred) r2 = r2_score(y_test, y_pred) print(f"Mean Squared Error: {mse:.2f}") print(f"Root Mean Squared Error: {rmse:.2f}") print(f"Mean Absolute Error: {mae:.2f}") print(f"R² Score: {r2:.2f}") # 绘制预测值与实际值的散点图 plt.figure(figsize=(10, 6)) plt.scatter(y_test, y_pred, alpha=0.5) plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], 'r--', lw=2) plt.xlabel('Actual') plt.ylabel('Predicted') plt.title('Actual vs Predicted Values') plt.show() # 绘制残差图 residuals = y_test - y_pred plt.figure(figsize=(10, 6)) plt.scatter(y_pred, residuals, alpha=0.5) plt.axhline(y=0, color='r', linestyle='--') plt.xlabel('Predicted Values') plt.ylabel('Residuals') plt.title('Residual Plot') plt.show() # 寻找最优的K值 k_range = range(1, 31) k_scores = [] for k in k_range: knn_reg = KNeighborsRegressor(n_neighbors=k) knn_reg.fit(X_train_scaled, y_train) y_pred_k = knn_reg.predict(X_test_scaled) k_scores.append(mean_squared_error(y_test, y_pred_k)) # 绘制K值与均方误差的关系图 plt.figure(figsize=(10, 6)) plt.plot(k_range, k_scores) plt.xlabel('Value of K for KNN') plt.ylabel('Mean Squared Error') plt.title('K Value vs MSE') plt.show() 

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

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

实践技巧

1. 数据标准化

与KNN分类算法一样,KNN回归算法也对特征的尺度敏感,因此需要对数据进行标准化或归一化处理。

from sklearn.preprocessing import StandardScaler # 标准化数据 scaler = StandardScaler() X_train_scaled = scaler.fit_transform(X_train) X_test_scaled = scaler.transform(X_test) 

2. 选择合适的K值

K值的选择对KNN回归算法的性能同样重要。较小的K值可能会导致模型对噪声敏感,而较大的K值可能会导致模型过于平滑。通常,通过交叉验证来选择最优的K值。

from sklearn.model_selection import GridSearchCV # 使用网格搜索选择最优K值 param_grid = {'n_neighbors': range(1, 31)} knn_reg = KNeighborsRegressor() grid_search = GridSearchCV(knn_reg, param_grid, cv=5, scoring='neg_mean_squared_error') grid_search.fit(X_train_scaled, y_train) print(f"Best K value: {grid_search.best_params_['n_neighbors']}") 

3. 距离度量的选择

KNN回归算法也可以使用不同的距离度量,如欧氏距离、曼哈顿距离、闵可夫斯基距离等。

# 使用曼哈顿距离 knn_manhattan = KNeighborsRegressor(n_neighbors=5, metric='manhattan') 

4. 加权平均

在标准的KNN回归算法中,所有K个邻居的贡献相同。但是,我们可以根据距离的倒数来加权邻居的贡献,使得更近的邻居具有更大的影响力。

# 使用距离权重 knn_weighted = KNeighborsRegressor(n_neighbors=5, weights='distance') 

5. 特征选择

对于高维数据,KNN算法可能会受到”维度灾难”的影响。在这种情况下,可以考虑使用特征选择或降维技术,如主成分分析(PCA)。

from sklearn.decomposition import PCA # 使用PCA降维 pca = PCA(n_components=0.95) # 保留95%的方差 X_train_pca = pca.fit_transform(X_train_scaled) X_test_pca = pca.transform(X_test_scaled) # 在降维后的数据上使用KNN knn_pca = KNeighborsRegressor(n_neighbors=5) knn_pca.fit(X_train_pca, y_train) y_pred_pca = knn_pca.predict(X_test_pca) mse_pca = mean_squared_error(y_test, y_pred_pca) print(f"MSE with PCA: {mse_pca:.2f}") 

KNN算法的参数调优

K值的选择

K值是KNN算法中最重要的参数,它决定了用于预测的邻居数量。选择合适的K值对算法的性能至关重要。

from sklearn.model_selection import cross_val_score import matplotlib.pyplot as plt # 创建一个KNN分类器 knn = KNeighborsClassifier() # 尝试不同的K值 k_range = range(1, 31) k_scores = [] for k in k_range: knn.set_params(n_neighbors=k) scores = cross_val_score(knn, X_train_scaled, y_train, cv=10, scoring='accuracy') k_scores.append(scores.mean()) # 绘制K值与交叉验证准确率的关系图 plt.figure(figsize=(10, 6)) plt.plot(k_range, k_scores) plt.xlabel('Value of K for KNN') plt.ylabel('Cross-Validated Accuracy') plt.title('K Value vs Accuracy') plt.show() # 找到最优的K值 best_k = k_range[np.argmax(k_scores)] print(f"Best K value: {best_k}") 

距离度量的选择

KNN算法可以使用不同的距离度量来计算样本之间的距离。常见的距离度量包括欧氏距离、曼哈顿距离、闵可夫斯基距离等。

# 使用欧氏距离(默认) knn_euclidean = KNeighborsClassifier(n_neighbors=5, metric='euclidean') # 使用曼哈顿距离 knn_manhattan = KNeighborsClassifier(n_neighbors=5, metric='manhattan') # 使用闵可夫斯基距离,p=3 knn_minkowski = KNeighborsClassifier(n_neighbors=5, metric='minkowski', p=3) # 使用余弦相似度 knn_cosine = KNeighborsClassifier(n_neighbors=5, metric='cosine') 

权重函数的选择

在标准的KNN算法中,所有K个邻居的投票权重相同。但是,我们可以根据距离的倒数来加权邻居的投票,使得更近的邻居具有更大的影响力。

# 使用均匀权重(默认) knn_uniform = KNeighborsClassifier(n_neighbors=5, weights='uniform') # 使用距离权重 knn_distance = KNeighborsClassifier(n_neighbors=5, weights='distance') 

算法选择

scikit-learn中的KNN算法提供了三种不同的算法来计算最近邻:

# 使用暴力搜索 knn_brute = KNeighborsClassifier(n_neighbors=5, algorithm='brute') # 使用KD树 knn_kd_tree = KNeighborsClassifier(n_neighbors=5, algorithm='kd_tree') # 使用球树 knn_ball_tree = KNeighborsClassifier(n_neighbors=5, algorithm='ball_tree') # 自动选择(默认) knn_auto = KNeighborsClassifier(n_neighbors=5, algorithm='auto') 

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

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

1. 使用KD树或球树

KD树和球树是用于加速最近邻搜索的数据结构。它们通过划分数据空间来减少需要计算距离的样本数量。

# 使用KD树加速 knn_kd_tree = KNeighborsClassifier(n_neighbors=5, algorithm='kd_tree') # 使用球树加速 knn_ball_tree = KNeighborsClassifier(n_neighbors=5, algorithm='ball_tree') 

2. 近似最近邻搜索

对于非常大的数据集,可以考虑使用近似最近邻(Approximate Nearest Neighbor, ANN)算法,如局部敏感哈希(Locality-Sensitive Hashing, LSH)或随机投影树(Random Projection Trees)。

# 使用annoy库进行近似最近邻搜索 from annoy import AnnoyIndex # 创建Annoy索引 f = X_train.shape[1] # 特征数量 t = AnnoyIndex(f, 'euclidean') # 添加训练数据到索引 for i, vector in enumerate(X_train): t.add_item(i, vector) # 构建索引 t.build(10) # 10棵树 # 查询最近邻 indices, distances = t.get_nns_by_vector(X_test[0], 5, include_distances=True) 

3. 降维

对于高维数据,可以考虑使用降维技术,如主成分分析(PCA)或线性判别分析(LDA),来减少特征数量。

from sklearn.decomposition import PCA # 使用PCA降维 pca = PCA(n_components=0.95) # 保留95%的方差 X_train_pca = pca.fit_transform(X_train) X_test_pca = pca.transform(X_test) # 在降维后的数据上使用KNN knn_pca = KNeighborsClassifier(n_neighbors=5) knn_pca.fit(X_train_pca, y_train) accuracy = knn_pca.score(X_test_pca, y_test) print(f"Accuracy with PCA: {accuracy:.2f}") 

4. 特征选择

通过选择最重要的特征,可以减少特征数量,从而提高KNN算法的效率。

from sklearn.feature_selection import SelectKBest, f_classif # 选择最重要的10个特征 selector = SelectKBest(f_classif, k=10) X_train_selected = selector.fit_transform(X_train, y_train) X_test_selected = selector.transform(X_test) # 在选择后的特征上使用KNN knn_selected = KNeighborsClassifier(n_neighbors=5) knn_selected.fit(X_train_selected, y_train) accuracy = knn_selected.score(X_test_selected, y_test) print(f"Accuracy with feature selection: {accuracy:.2f}") 

5. 并行计算

scikit-learn中的KNN算法支持并行计算,可以通过设置n_jobs参数来使用多个CPU核心。

# 使用所有可用的CPU核心 knn_parallel = KNeighborsClassifier(n_neighbors=5, n_jobs=-1) 

6. 数据采样

对于非常大的数据集,可以考虑对数据进行采样,以减少训练集的大小。

from sklearn.utils import resample # 对训练数据进行采样 X_train_sampled, y_train_sampled = resample(X_train, y_train, n_samples=1000, random_state=42) # 在采样后的数据上使用KNN knn_sampled = KNeighborsClassifier(n_neighbors=5) knn_sampled.fit(X_train_sampled, y_train_sampled) accuracy = knn_sampled.score(X_test, y_test) print(f"Accuracy with sampling: {accuracy:.2f}") 

KNN算法与其他算法的比较

KNN vs 决策树

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

KNN vs 随机森林

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

KNN vs SVM

from sklearn.svm import SVC # 比较KNN和SVM在鸢尾花数据集上的性能 # KNN knn = KNeighborsClassifier(n_neighbors=3) knn.fit(X_train_scaled, y_train) knn_accuracy = knn.score(X_test_scaled, y_test) # SVM svm = SVC(random_state=42) svm.fit(X_train_scaled, y_train) # SVM需要数据标准化 svm_accuracy = svm.score(X_test_scaled, y_test) print(f"KNN Accuracy: {knn_accuracy:.2f}") print(f"SVM Accuracy: {svm_accuracy:.2f}") 

实际应用案例

案例1:手写数字识别

手写数字识别是机器学习中的经典问题,我们可以使用KNN算法来解决这个问题。

from sklearn.datasets import load_digits from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.neighbors import KNeighborsClassifier from sklearn.metrics import accuracy_score, classification_report, confusion_matrix import matplotlib.pyplot as plt import seaborn as sns # 加载手写数字数据集 digits = load_digits() X = digits.data y = digits.target # 显示一些数字图像 fig, axes = plt.subplots(2, 5, figsize=(10, 4)) for i, ax in enumerate(axes.ravel()): ax.imshow(digits.images[i], cmap='binary') ax.set_title(f"Label: {digits.target[i]}") ax.axis('off') plt.tight_layout() plt.show() # 将数据集分为训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42) # 数据标准化 scaler = StandardScaler() X_train_scaled = scaler.fit_transform(X_train) X_test_scaled = scaler.transform(X_test) # 创建KNN分类器 knn = KNeighborsClassifier(n_neighbors=3) # 训练模型 knn.fit(X_train_scaled, y_train) # 预测测试集 y_pred = knn.predict(X_test_scaled) # 计算准确率 accuracy = accuracy_score(y_test, y_pred) print(f"Accuracy: {accuracy:.2f}") # 输出分类报告 print("nClassification Report:") print(classification_report(y_test, y_pred)) # 绘制混淆矩阵 cm = confusion_matrix(y_test, y_pred) plt.figure(figsize=(10, 8)) sns.heatmap(cm, annot=True, fmt='d', cmap='Blues') plt.xlabel('Predicted') plt.ylabel('Actual') plt.title('Confusion Matrix') plt.show() # 显示一些预测错误的图像 incorrect_indices = np.where(y_pred != y_test)[0] if len(incorrect_indices) > 0: fig, axes = plt.subplots(2, 5, figsize=(10, 4)) for i, ax in enumerate(axes.ravel()): if i < len(incorrect_indices): idx = incorrect_indices[i] ax.imshow(digits.images[idx + len(X_train)], cmap='binary') ax.set_title(f"True: {y_test[idx]}, Pred: {y_pred[idx]}") ax.axis('off') plt.tight_layout() plt.show() 

案例2:客户流失预测

客户流失预测是商业分析中的重要问题,我们可以使用KNN算法来预测客户是否会流失。

import pandas as pd from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler, LabelEncoder from sklearn.neighbors import KNeighborsClassifier from sklearn.metrics import accuracy_score, classification_report, confusion_matrix, roc_curve, auc import matplotlib.pyplot as plt import seaborn as sns # 假设我们有一个客户数据集 # 这里我们创建一个模拟数据集 np.random.seed(42) n_samples = 1000 # 创建特征 age = np.random.normal(40, 15, n_samples) income = np.random.normal(50000, 15000, n_samples) tenure = np.random.randint(1, 72, n_samples) monthly_charge = np.random.normal(70, 20, n_samples) usage = np.random.normal(20, 10, n_samples) # 创建目标变量(客户是否流失) churn_prob = 1 / (1 + np.exp(-(-5 + 0.01 * age - 0.00002 * income - 0.02 * tenure + 0.03 * monthly_charge - 0.05 * usage))) churn = np.random.binomial(1, churn_prob) # 创建DataFrame data = pd.DataFrame({ 'Age': age, 'Income': income, 'Tenure': tenure, 'MonthlyCharge': monthly_charge, 'Usage': usage, 'Churn': churn }) # 显示数据的前几行 print(data.head()) # 将数据集分为特征和目标 X = data.drop('Churn', axis=1) y = data['Churn'] # 将数据集分为训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42) # 数据标准化 scaler = StandardScaler() X_train_scaled = scaler.fit_transform(X_train) X_test_scaled = scaler.transform(X_test) # 创建KNN分类器 knn = KNeighborsClassifier(n_neighbors=5) # 训练模型 knn.fit(X_train_scaled, y_train) # 预测测试集 y_pred = knn.predict(X_test_scaled) y_pred_proba = knn.predict_proba(X_test_scaled)[:, 1] # 计算准确率 accuracy = accuracy_score(y_test, y_pred) print(f"Accuracy: {accuracy:.2f}") # 输出分类报告 print("nClassification Report:") print(classification_report(y_test, y_pred)) # 绘制混淆矩阵 cm = confusion_matrix(y_test, y_pred) plt.figure(figsize=(8, 6)) sns.heatmap(cm, annot=True, fmt='d', cmap='Blues') plt.xlabel('Predicted') plt.ylabel('Actual') plt.title('Confusion Matrix') plt.show() # 绘制ROC曲线 fpr, tpr, thresholds = roc_curve(y_test, y_pred_proba) roc_auc = auc(fpr, tpr) plt.figure(figsize=(8, 6)) plt.plot(fpr, tpr, color='darkorange', lw=2, label=f'ROC curve (area = {roc_auc:.2f})') plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--') plt.xlim([0.0, 1.0]) plt.ylim([0.0, 1.05]) plt.xlabel('False Positive Rate') plt.ylabel('True Positive Rate') plt.title('Receiver Operating Characteristic (ROC) Curve') plt.legend(loc="lower right") plt.show() # 寻找最优的K值 k_range = range(1, 31) k_scores = [] for k in k_range: knn = KNeighborsClassifier(n_neighbors=k) knn.fit(X_train_scaled, y_train) y_pred_k = knn.predict(X_test_scaled) k_scores.append(accuracy_score(y_test, y_pred_k)) # 绘制K值与准确率的关系图 plt.figure(figsize=(10, 6)) plt.plot(k_range, k_scores) plt.xlabel('Value of K for KNN') plt.ylabel('Testing Accuracy') plt.title('K Value vs Accuracy') plt.show() # 找到最优的K值 best_k = k_range[np.argmax(k_scores)] print(f"Best K value: {best_k}") # 使用最优K值重新训练模型 knn_best = KNeighborsClassifier(n_neighbors=best_k) knn_best.fit(X_train_scaled, y_train) y_pred_best = knn_best.predict(X_test_scaled) accuracy_best = accuracy_score(y_test, y_pred_best) print(f"Accuracy with best K: {accuracy_best:.2f}") 

总结与展望

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

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

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

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

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