KNN 核心预测函数 _predict_one
的过程,本质上就是在用 PyTorch 的能力,一步步实现欧几里得距离公式 ,并进行多数表决。
核心预测函数 _predict_one
记忆口诀(三步法)
步骤 | 目标 | 核心口诀 (PyTorch 链式操作) | 记忆代码行 (骨架) |
---|---|---|---|
第一步 | 算距离 (L2 范数) | 扩展 → 相减 → 平方 → 求和 → 开方 | torch.sqrt(torch.sum( (X_train - x_new.unsqueeze(0)).pow(2), dim=1)) |
第二步 | 找邻居 | 距离排序 → 取前 K 个索引 | k_indices = torch.argsort(distances)[:self.k] |
第三步 | 定类别 | 标签索引 → 移回 CPU → 多数表决 | Counter(y_train[k_indices].cpu().tolist()).most_common(1)[0][0] |
核心代码精简解读与记忆点
下面是您需要背诵的、最核心的部分,每行都给出了精简的记忆提示:
A. 步骤 1:计算欧几里得距离 (L2 Distance)
代码行 | 目的/功能 | 关键记忆点 |
---|---|---|
x_new_expanded = x_new.unsqueeze(0) |
形状准备 。将 ( N feat , ) (N_{\text{feat}},) (Nfeat,) 变成 ( 1 , N feat ) (1, N_{\text{feat}}) (1,Nfeat), 准备广播。 | unsqueeze(0):加 1 维,激活广播。 |
differences = self.X_train - x_new_expanded |
算差值。利用广播机制,计算新点与所有训练点的差。 | X_train - ...:张量广播相减。 |
squared_differences = differences.pow(2) |
算平方。对所有差值进行平方。 | .pow(2):欧氏距离公式的第一步。 |
sum_squared_diff = torch.sum(squared_differences, dim=1) |
算求和 。沿着特征轴 (dim=1 ) 求和,得到距离平方。 |
torch.sum(..., dim=1):沿着特征维求和。 |
distances = torch.sqrt(sum_squared_diff) |
算开方。最终得到欧几里得距离。 | torch.sqrt(...):距离计算完成。 |
B. 步骤 2:找到 K 个最近邻居
代码行 | 目的/功能 | 关键记忆点 |
---|---|---|
k_indices = torch.argsort(distances)[:self.k] |
找索引 。对所有距离排序,并取出前 K 个最小距离的索引。 | argsort()[:self.k]:排序后取前 K 个。 |
C. 步骤 3:多数表决 (Majority Voting)
代码行 | 目的/功能 | 关键记忆点 |
---|---|---|
k_nearest_labels_torch = self.y_train[k_indices] |
取标签。根据索引从训练标签中取出 K 个邻居的标签。 | y_train[k_indices]:张量索引。 |
k_nearest_labels_cpu = k_nearest_labels_torch.cpu().tolist() |
数据桥接 。将标签张量移回 CPU 并转为 Python 列表,以使用 Counter 。 |
.cpu().tolist():关键的 CPU 转换步骤。 |
most_common = Counter(k_nearest_labels_cpu).most_common(1) |
统计投票。找出出现次数最多的类别。 | Counter().most_common(1):多数表决。 |
return most_common[0][0] |
返回结果。提取出频率最高的类别标签。 | [0][0]:提取最终标签值。 |
掌握这三步法和对应口诀,就能快速重现 _predict_one
的核心逻辑了。