机器学习1
·
一、KNN 算法与模型评估基础
1.1 KNN 算法原理
K 近邻(K-Nearest Neighbors,KNN)是一种简单直观的监督学习算法,其核心思想可以概括为 "物以类聚":对于未知样本,通过计算它与训练集中所有样本的距离,选取距离最近的 k 个样本(近邻),并以这 k 个样本中出现次数最多的类别作为未知样本的预测类别。
KNN 算法的关键要素:
- 距离度量:常用欧氏距离(适用于连续特征),计算公式为distance(x,y)=∑i=1n(xi−yi)2
- k 值选择:k 过小易受噪声影响(过拟合),k 过大会导致类别边界模糊(欠拟合),通常通过验证集选择最优 k
- 投票机制:多数表决(分类问题)或平均值(回归问题)
1.2 模型评估指标
- 准确率(Accuracy):正确预测的样本数占总样本数的比例,适用于均衡数据集
- 混淆矩阵(Confusion Matrix):直观展示各类别预测结果的分布,行代表真实类别,列代表预测类别,对角线元素表示正确预测数
二、问题引入:约会网站匹配预测
在约会网站场景中,我们需要根据海伦的三个特征预测其对潜在约会对象的喜好程度:
- 飞行里程数(每年的飞行常客里程)
- 游戏时间百分比(每周花在玩视频游戏上的时间百分比)
- 冰淇淋公升数(每周消费的冰淇淋公升数)
目标变量为用户的评价结果,分为三类:
- didntLike(不喜欢)
- smallDoses(有点喜欢)
- largeDoses(很喜欢)
我们将使用 KNN 算法构建分类模型,通过历史数据训练模型,实现对新用户喜好的自动预测。
三、代码算法模块详解
3.1 数据读取与初始化模块
python
def load_data(file_path):
# 读取txt文件并指定列名
columns = ["飞行里程数", "游戏时间百分比", "冰淇淋公升数", "标签"]
data = pd.read_csv(file_path, sep="\t", header=None, names=columns)
# 分离特征与标签
X = data[["飞行里程数", "游戏时间百分比", "冰淇淋公升数"]].values
y = data["标签"].values
# 标签字符串转整数(便于计算)
label_map = {"didntLike": 0, "smallDoses": 1, "largeDoses": 2}
y = np.array([label_map[label] for label in y])
return X, y, label_map
该模块负责:
- 读取 TSV 格式数据集
- 分离特征矩阵(X)和标签向量(y)
- 标签编码(字符串转整数)
3.2 数据预处理模块(归一化)
def normalize_features(X):
min_vals = X.min(axis=0) # 每列最小值
max_vals = X.max(axis=0) # 每列最大值
ranges = max_vals - min_vals # 取值范围
# 归一化到[0,1]区间,处理除零问题
X_norm = (X - min_vals) / np.where(ranges == 0, 1, ranges)
return X_norm, min_vals, max_vals
特征归一化的作用:消除不同特征量纲差异(如飞行里程数远大于冰淇淋消费量),确保各特征在距离计算中权重一致。
3.3 KNN 核心算法模块
def knn_classify(X_train, y_train, X_test, k):
y_pred = []
for test_sample in X_test:
# 1. 计算与所有训练样本的欧氏距离
distances = np.sqrt(np.sum((X_train - test_sample) **2, axis=1))
# 2. 按距离排序,取前k个样本索引
k_indices = np.argsort(distances)[:k]
# 3. 多数表决:取k个近邻中最频繁的标签
k_labels = y_train[k_indices]
pred_label = np.bincount(k_labels).argmax()
y_pred.append(pred_label)
return np.array(y_pred)
核心步骤:
- 计算测试样本与所有训练样本的欧氏距离
- 按距离升序排序,选取前 k 个近邻
- 对 k 个近邻的标签进行投票,取众数作为预测结果
3.4 模型评估与超参数选择模块
# 准确率计算
def calculate_accuracy(y_true, y_pred):
return np.sum(y_true == y_pred) / len(y_true)
# 混淆矩阵构建
def create_confusion_matrix(y_true, y_pred, n_classes):
cm = np.zeros((n_classes, n_classes), dtype=int)
for true, pred in zip(y_true, y_pred):
cm[true][pred] += 1
return cm
# 最优k值选择
def find_best_k(X_train, y_train, X_val, y_val, k_candidates):
best_accuracy = 0.0
best_k = 1
for k in k_candidates:
y_pred = knn_classify(X_train, y_train, X_val, k)
accuracy = calculate_accuracy(y_val, y_pred)
if accuracy > best_accuracy:
best_accuracy = accuracy
best_k = k
return best_k, best_accuracy
通过验证集评估不同 k 值的模型性能,选择准确率最高的 k 作为最优超参数。
3.5 新样本预测接口
def predict_new_sample(new_sample, X_train, y_train, min_vals, max_vals, k, label_map):
# 归一化新样本(使用训练集的归一化参数)
ranges = max_vals - min_vals
new_sample_norm = (new_sample - min_vals) / np.where(ranges == 0, 1, ranges)
# 预测并转换为原始标签
pred_label_code = knn_classify(X_train, y_train, new_sample_norm.reshape(1, -1), k)[0]
inverse_map = {v: k for k, v in label_map.items()}
return inverse_map[pred_label_code]
提供工程化预测接口,支持对新样本的直接预测,包含特征归一化和标签反向映射步骤。
四、结果展示与分析
4.1 最优 k 值选择结果

通过验证集测试,当 k=5 时模型性能最佳,验证集准确率达到 95.71%。
4.2 测试集评估结果

- 测试集准确率为 96.67%,模型泛化能力良好
- 混淆矩阵显示:大多数样本被正确分类,少量 smallDoses 样本被误分为 didntLike 或 largeDoses
4.3 新样本预测结果

对 3 个示例样本的预测结果均与预期一致,验证了模型的实用性。
总结
本文实现了一个基于 KNN 算法的约会网站匹配预测模型,完整覆盖了数据处理、模型构建、超参数选择和性能评估的全流程。通过特征归一化和最优 k 值选择,模型达到了 96.67% 的测试集准确率,能够有效预测用户对约会对象的喜好程度。该实现方案具有良好的可扩展性,可直接应用于类似的分类问题场景。
更多推荐



所有评论(0)