31 客户购买意愿分析(K近邻算法)
31.1 引言K近邻算法(KNN)
KNN算法:监督学习的分类算法 - 原理: “物以类聚,人以群分” - 决策: 根据K个最近邻居的类别投票 - 金融应用: 客户分类、信用评分
31.2 算法原理
决策规则: 对于样本x,找到其K个最近邻居,这K个邻居中最多数样本所属的类别即为x的预测类别。
距离度量: 常用欧氏距离
\[ d(x,y) = \sqrt{\sum_{i=1}^{n}(x_i - y_i)^2} \]
31.3 社交网络广告案例
# 注:04_Social_Network_Ads.csv数据文件本地没有,但平台已经内置
# ⚠️ 平台原始代码 - 请原样输入至教学平台(注释除外),平台才会判定答案正确
# 导入相关模块
import pandas as pd
import numpy as np # 导入NumPy数值计算库
from sklearn.model_selection import train_test_split # 导入Scikit-learn的train_test_split模块
from sklearn.preprocessing import StandardScaler # 导入Scikit-learn的StandardScaler模块
from sklearn.neighbors import KNeighborsClassifier # 导入Scikit-learn的KNeighborsClassifier模块
from sklearn.model_selection import GridSearchCV # 导入Scikit-learn的GridSearchCV模块
from sklearn.metrics import confusion_matrix # 导入Scikit-learn的confusion_matrix模块
# 导入数据集
data = pd.read_csv("04_Social_Network_Ads.csv")
# 数据集划分
x = data[["Age","EstimatedSalary"]]
y = data["Purchased"] # 提取Purchased列作为y变量
# 划分训练集和测试集
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.30, random_state=0)
# 数据标准化
transfer1 = StandardScaler()
x_train = transfer1.fit_transform(x_train) # 对数据进行变换
x_test = transfer1.transform(x_test) # 对数据进行变换
# 训练模型
estimator = KNeighborsClassifier(algorithm='kd_tree')
# 模型选择与调优——网格搜索和交叉验证
# 准备要调的超参数
param_dict = {"n_neighbors": [1, 3, 5, 7, 9, 11, 13]}
estimator = GridSearchCV(estimator, param_grid=param_dict, cv=4) # 创建网格搜索交叉验证对象,自动寻找最优超参数
estimator.fit(x_train,y_train) # 在数据上训练estimator模型
# 模型评估
y_pre = estimator.predict(x_test)
print("预测结果:\n", y_pre) # 输出预测结果:\n
print("准确率为:\n", estimator.score(x_test, y_test)) # 输出准确率为:\n
# print("对比真实值和预测值:\n", y_test==y_pre)
print("在交叉验证中最好的结果为:\n", estimator.best_score_)
print("使用网格搜索的最好的模型:\n", estimator.best_estimator_) # 输出使用网格搜索的最好的模型:\n31.4 模型训练与调优
# 注:该代码块依赖的数据来自上方平台任务代码块,因其未执行,本块也无法执行
# ==================== 创建KNN分类器 ====================
# KNN通过投票机制分类:K个邻居中多数类作为预测类
knn = KNeighborsClassifier(algorithm='kd_tree') # 使用KD树算法加速最近邻搜索
# ==================== 定义参数网格 ====================
# K值是KNN的超参数,需要通过交叉验证选择最优值
param_grid = {'n_neighbors': [1, 3, 5, 7, 9, 11, 13]} # 测试不同的K值
# ==================== 网格搜索+交叉验证 ====================
# 通过交叉验证找到使准确率最高的K值
grid_search = GridSearchCV(
knn, # 基础模型
param_grid=param_grid, # 参数网格
cv=4, # 4折交叉验证(将训练集分成4份,轮流做验证集)
n_jobs=-1 # 使用所有CPU核心并行计算
)
# ==================== 训练模型 ====================
grid_search.fit(X_train_scaled, y_train) # 在标准化后的训练集上拟合
# ==================== 输出最佳参数 ====================
print(f'最佳K值: {grid_search.best_params_["n_neighbors"]}') # 打印最优K值
print(f'交叉验证最佳准确率: {grid_search.best_score_:.4f}') # 打印交叉验证的最高准确率31.5 模型评估
# 注:该代码块依赖的数据来自上方平台任务代码块,因其未执行,本块也无法执行
# ==================== 预测测试集 ====================
# 使用最优模型对测试集进行预测
y_pred = grid_search.predict(X_test_scaled) # 输出预测类别(0或1)
# ==================== 计算准确率 ====================
accuracy = accuracy_score(y_test, y_pred) # 计算预测准确率
print(f'测试集准确率: {accuracy:.4f}') # 打印准确率,范围[0,1]
# ==================== 生成混淆矩阵 ====================
# 混淆矩阵展示了预测结果与真实情况的对比
cm = confusion_matrix(y_test, y_pred) # 生成2x2混淆矩阵
print(f'\n混淆矩阵:')
print(cm)
# 混淆矩阵格式:
# 预测0 预测1
# 实际0 [TN [FP
# 实际1 [FN [TP
# ==================== 可视化混淆矩阵 ====================
import matplotlib.pyplot as plt # 导入绘图库
import seaborn as sns # 导入统计绘图库
plt.figure(figsize=(8, 6)) # 创建8x6英寸的画布
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues') # 绘制热力图,annot显示数值,fmt整数格式
plt.title('混淆矩阵', fontsize=14) # 设置标题
plt.xlabel('预测类别', fontsize=12) # x轴标签
plt.ylabel('真实类别', fontsize=12) # y轴标签
plt.tight_layout() # 自动调整布局,避免标签重叠
plt.show() # 显示图形
# ==================== 输出最优模型 ====================
print(f'\n最佳模型: {grid_search.best_estimator_}') # 打印最优模型的完整配置31.6 分析结论
- 标准化必要: 年龄和薪资尺度差异大
- K值选择: 通过交叉验证确定
- 模型性能: 达到较高准确率
- 商业应用: 预测用户是否购买