本文目录导读:

我来为你详细介绍如何使用Scikit-learn实现KNN(K-Nearest Neighbors)分类,包含多个实际案例。
基础KNN分类示例(鸢尾花数据集)
# 导入必要的库
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import classification_report, confusion_matrix, accuracy_score
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# 加载数据
iris = load_iris()
X, y = iris.data, iris.target
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=42
)
# 创建KNN分类器(k=3)
knn = KNeighborsClassifier(n_neighbors=3)
# 训练模型
knn.fit(X_train, y_train)
# 预测
y_pred = knn.predict(X_test)
# 评估模型
accuracy = accuracy_score(y_test, y_pred)
print(f"准确率: {accuracy:.2f}")
# 详细分类报告
print("\n分类报告:")
print(classification_report(y_test, y_pred, target_names=iris.target_names))
# 混淆矩阵
cm = confusion_matrix(y_test, y_pred)
print("混淆矩阵:")
print(cm)
# 可视化混淆矩阵
plt.figure(figsize=(8, 6))
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues',
xticklabels=iris.target_names,
yticklabels=iris.target_names)'混淆矩阵 - KNN分类')
plt.ylabel('真实标签')
plt.xlabel('预测标签')
plt.show()
K值选择与评估
from sklearn.model_selection import cross_val_score
# 测试不同的K值
k_range = range(1, 31)
k_scores = []
k_scores_std = []
for k in k_range:
knn = KNeighborsClassifier(n_neighbors=k)
# 使用交叉验证评估
scores = cross_val_score(knn, X, y, cv=10, scoring='accuracy')
k_scores.append(scores.mean())
k_scores_std.append(scores.std())
# 找到最优K值
optimal_k = k_range[np.argmax(k_scores)]
optimal_score = max(k_scores)
print(f"最优K值: {optimal_k}")
print(f"最优准确率: {optimal_score:.4f}")
# 可视化K值与准确率的关系
plt.figure(figsize=(10, 6))
plt.errorbar(k_range, k_scores, yerr=k_scores_std, marker='o')
plt.xlabel('K值')
plt.ylabel('交叉验证准确率')'K值对KNN分类性能的影响')
plt.grid(True, alpha=0.3)
plt.show()
数据标准化与KNN
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
# 创建包含标准化的Pipeline
knn_pipeline = Pipeline([
('scaler', StandardScaler()),
('knn', KNeighborsClassifier(n_neighbors=5))
])
# 训练和评估
knn_pipeline.fit(X_train, y_train)
y_pred_scaled = knn_pipeline.predict(X_test)
accuracy_scaled = accuracy_score(y_test, y_pred_scaled)
print(f"标准化后的准确率: {accuracy_scaled:.4f}")
# 对比有无标准化的效果
# 未标准化
knn_no_scale = KNeighborsClassifier(n_neighbors=5)
knn_no_scale.fit(X_train, y_train)
y_pred_no_scale = knn_no_scale.predict(X_test)
accuracy_no_scale = accuracy_score(y_test, y_pred_no_scale)
print(f"未标准化的准确率: {accuracy_no_scale:.4f}")
距离度量方式比较
# 测试不同的距离度量方式
distance_metrics = ['euclidean', 'manhattan', 'chebyshev', 'minkowski']
results = {}
for metric in distance_metrics:
knn = KNeighborsClassifier(n_neighbors=5, metric=metric)
if metric == 'minkowski':
# Minkowski距离需要指定p参数
for p in [1, 2, 3]:
knn = KNeighborsClassifier(n_neighbors=5, metric='minkowski', p=p)
scores = cross_val_score(knn, X, y, cv=5, scoring='accuracy')
results[f'{metric}(p={p})'] = scores.mean()
else:
scores = cross_val_score(knn, X, y, cv=5, scoring='accuracy')
results[metric] = scores.mean()
print("不同距离度量的性能比较:")
for metric, score in results.items():
print(f"{metric}: {score:.4f}")
权重策略比较
# 测试不同的权重策略
weight_strategies = ['uniform', 'distance']
weight_results = {}
for weight in weight_strategies:
knn = KNeighborsClassifier(n_neighbors=5, weights=weight)
scores = cross_val_score(knn, X, y, cv=5, scoring='accuracy')
weight_results[weight] = scores.mean()
print(f"权重策略 '{weight}' 的平均准确率: {scores.mean():.4f}")
# 可视化比较
plt.figure(figsize=(8, 5))
plt.bar(weight_results.keys(), weight_results.values())
plt.ylabel('准确率')'不同权重策略的性能比较')
plt.show()
实战:手写数字识别
from sklearn.datasets import load_digits
from sklearn.decomposition import PCA
# 加载手写数字数据集
digits = load_digits()
X_digits, y_digits = digits.data, digits.target
# 数据集信息
print(f"数据集大小: {X_digits.shape}")
print(f"类别数量: {len(np.unique(y_digits))}")
# 划分数据集
X_train_d, X_test_d, y_train_d, y_test_d = train_test_split(
X_digits, y_digits, test_size=0.2, random_state=42
)
# 使用PCA降维(可选)
pca = PCA(n_components=30)
X_train_pca = pca.fit_transform(X_train_d)
X_test_pca = pca.transform(X_test_d)
# 训练KNN模型
knn_digits = KNeighborsClassifier(n_neighbors=3, weights='distance')
knn_digits.fit(X_train_pca, y_train_d)
# 预测
y_pred_digits = knn_digits.predict(X_test_pca)
accuracy_digits = accuracy_score(y_test_d, y_pred_digits)
print(f"手写数字识别准确率: {accuracy_digits:.4f}")
# 显示一些预测结果
fig, axes = plt.subplots(2, 5, figsize=(12, 6))
axes = axes.ravel()
for i in range(10):
axes[i].imshow(X_test_d[i].reshape(8, 8), cmap='gray')
axes[i].set_title(f'真实: {y_test_d[i]}\n预测: {y_pred_digits[i]}')
axes[i].axis('off')
plt.tight_layout()
plt.show()
网格搜索调参
from sklearn.model_selection import GridSearchCV
# 定义参数网格
param_grid = {
'n_neighbors': [3, 5, 7, 9, 11],
'weights': ['uniform', 'distance'],
'metric': ['euclidean', 'manhattan', 'minkowski'],
'p': [1, 2, 3] # Minkowski距离的参数
}
# 创建KNN分类器
knn_grid = KNeighborsClassifier()
# 网格搜索
grid_search = GridSearchCV(
knn_grid,
param_grid,
cv=5,
scoring='accuracy',
n_jobs=-1,
verbose=1
)
# 执行搜索
grid_search.fit(X_train, y_train)
# 输出最佳参数
print("最佳参数组合:")
for param, value in grid_search.best_params_.items():
print(f"{param}: {value}")
print(f"\n最佳交叉验证准确率: {grid_search.best_score_:.4f}")
# 使用最佳模型预测
best_knn = grid_search.best_estimator_
y_pred_best = best_knn.predict(X_test)
accuracy_best = accuracy_score(y_test, y_pred_best)
print(f"测试集准确率: {accuracy_best:.4f}")
决策边界可视化
# 使用前两个特征进行可视化(为了方便展示)
X_vis = X[:, :2]
X_train_vis, X_test_vis, y_train_vis, y_test_vis = train_test_split(
X_vis, y, test_size=0.3, random_state=42
)
# 训练KNN
knn_vis = KNeighborsClassifier(n_neighbors=5)
knn_vis.fit(X_train_vis, y_train_vis)
# 创建网格
x_min, x_max = X_vis[:, 0].min() - 1, X_vis[:, 0].max() + 1
y_min, y_max = X_vis[:, 1].min() - 1, X_vis[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02),
np.arange(y_min, y_max, 0.02))
# 预测网格点
Z = knn_vis.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
# 可视化
plt.figure(figsize=(12, 5))
# 决策边界
plt.subplot(1, 2, 1)
plt.contourf(xx, yy, Z, alpha=0.4, cmap=plt.cm.RdYlBu)
plt.scatter(X_train_vis[:, 0], X_train_vis[:, 1],
c=y_train_vis, cmap=plt.cm.RdYlBu,
edgecolor='black', s=50)
plt.xlabel('特征1')
plt.ylabel('特征2')'KNN决策边界(训练集)')
# 测试集结果
plt.subplot(1, 2, 2)
plt.contourf(xx, yy, Z, alpha=0.4, cmap=plt.cm.RdYlBu)
plt.scatter(X_test_vis[:, 0], X_test_vis[:, 1],
c=y_test_vis, cmap=plt.cm.RdYlBu,
edgecolor='black', s=50)
plt.xlabel('特征1')
plt.ylabel('特征2')'KNN决策边界(测试集)')
plt.tight_layout()
plt.show()
- K值选择:使用交叉验证找到最优K值
- 数据标准化:KNN对特征尺度敏感,需要标准化
- 距离度量:根据数据特点选择合适的距离度量
- 权重策略:考虑使用距离权重提高预测准确性
- 超参数调优:使用GridSearchCV找到最佳参数组合
这些案例涵盖了KNN分类的主要应用场景和调优技巧,可以根据实际需求选择合适的方法。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播