|
|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
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)的花萼和花瓣的长度和宽度。
- # 导入必要的库
- 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值。
实践技巧
由于KNN算法基于距离度量,特征的尺度会显著影响算法的结果。因此,在使用KNN之前,通常需要对数据进行标准化或归一化处理。scikit-learn中的StandardScaler或MinMaxScaler可以用于此目的。
- 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)
复制代码
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}")
复制代码
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)
复制代码
在标准的KNN算法中,所有K个邻居的投票权重相同。但是,我们可以根据距离的倒数来加权邻居的投票,使得更近的邻居具有更大的影响力。
- # 使用距离权重
- knn_weighted = KNeighborsClassifier(n_neighbors=5, weights='distance')
复制代码
为了更准确地评估模型的性能,可以使用交叉验证而不是简单的训练-测试分割。
- 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值。
实践技巧
与KNN分类算法一样,KNN回归算法也对特征的尺度敏感,因此需要对数据进行标准化或归一化处理。
- from sklearn.preprocessing import StandardScaler
- # 标准化数据
- scaler = StandardScaler()
- X_train_scaled = scaler.fit_transform(X_train)
- X_test_scaled = scaler.transform(X_test)
复制代码
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']}")
复制代码
KNN回归算法也可以使用不同的距离度量,如欧氏距离、曼哈顿距离、闵可夫斯基距离等。
- # 使用曼哈顿距离
- knn_manhattan = KNeighborsRegressor(n_neighbors=5, metric='manhattan')
复制代码
在标准的KNN回归算法中,所有K个邻居的贡献相同。但是,我们可以根据距离的倒数来加权邻居的贡献,使得更近的邻居具有更大的影响力。
- # 使用距离权重
- knn_weighted = KNeighborsRegressor(n_neighbors=5, weights='distance')
复制代码
对于高维数据,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算法通过KNeighborsClassifier和KNeighborsRegressor类实现,提供了丰富的参数和选项,可以满足不同场景的需求。
本文详细介绍了KNN算法在分类和回归问题中的应用,包括基本原理、实际案例分析和实践技巧。我们还讨论了KNN算法的优缺点、参数调优方法、在大数据集上的优化策略,以及与其他算法的比较。
尽管KNN算法有一些缺点,如计算复杂度高和内存需求大,但通过适当的优化策略,如使用KD树或球树、降维、特征选择等,可以在一定程度上克服这些问题。
随着机器学习领域的不断发展,KNN算法也在不断演进。例如,近似最近邻搜索算法的发展使得KNN算法可以应用于更大规模的数据集;深度学习与KNN的结合也产生了一些新的算法,如深度KNN(Deep KNN)等。
总的来说,KNN算法是一种值得掌握的机器学习算法,它在许多实际应用中表现出色,特别是在数据量不大、特征维度不高的情况下。通过理解KNN算法的原理和应用技巧,我们可以更好地利用它来解决实际问题。
版权声明
1、转载或引用本网站内容(探索scikit-learn中KNN算法的广泛应用场景从分类到回归的实际案例分析与实践技巧)须注明原网址及作者(威震华夏关云长),并标明本网站网址(https://www.pixtech.cc/)。
2、对于不当转载或引用本网站内容而引起的民事纷争、行政处理或其他损失,本网站不承担责任。
3、对不遵守本声明或其他违法、恶意使用本网站内容者,本网站保留追究其法律责任的权利。
本文地址: https://www.pixtech.cc/thread-40944-1-1.html
|
|