# results 目录结果说明

## 一、目录里有什么

| 文件 | 含义 |
|------|------|
| **metrics_baseline.json** | 基线方法（仅向量相似度）的完整指标 |
| **metrics_contrastive.json** | 对比学习方法（Triplet 训练）的完整指标 |
| **metrics_preference_weighted.json** | 偏好加权方法（2025 风格）的完整指标 |
| **accuracy_*.json** | 各方法每轮准确率列表（与 metrics 中 accuracy 一致，便于单独绘图） |
| **learning_curve.png** | 准确率随轮次变化曲线（Baseline vs Contrastive） |
| **all_metrics_three.png** | 四张子图：Accuracy / Precision / Recall / F1，可含三种方法 |

---

## 二、metrics_*.json 的结构

每个文件大致为：

```json
{
  "accuracy":  [ 0.72, 0.77, ... ],   // 第1轮、第2轮、…、第10轮的准确率
  "precision": [ 0.36, 0.48, ... ],   // 每轮的精确率
  "recall":    [ 0.33, 0.48, ... ],   // 每轮的召回率
  "f1":        [ 0.35, 0.48, ... ],   // 每轮的 F1
  "pre_interaction": {                 // 未做任何反馈前的单次评估（Round 0）
    "accuracy": 0.73,
    "precision": 0.38,
    "recall": 0.33,
    "f1": 0.35,
    "threshold": 0.7
  }
}
```

- **accuracy / precision / recall / f1**：列表长度 = 交互轮数（如 10）。每一轮先用当前用户向量（或训练后的模型）对所有模式打分，再按**阈值**转成 0/1 预测，与**真实标签（ground truth）**比较，得到该轮四个指标。
- **pre_interaction**：在**第 0 轮**（还没有用户反馈）时，仅用 LLM 意图向量对所有模式打一次分，算一次准确率/精确率/召回率/F1 和使用的阈值，用于看「冷启动」效果。

---

## 三、Precision 是怎么算的

### 1. 标签与预测从哪来

- **真实标签（y_true）**：由 `UserSimulator` 根据「喜欢/不喜欢特征」生成。
  - 若模式**至少包含一个喜欢特征**且**不包含不喜欢特征** → 标签 **1**（喜欢）
  - 否则 → 标签 **0**（不喜欢/不感兴趣）
- **预测（y_pred）**：对每个模式有一个**连续分数** `score`（相似度或模型输出），用**阈值**转成 0/1：
  - `score >= threshold` → 预测 **1**
  - `score < threshold` → 预测 **0**  
  当前代码里阈值是**固定 0.7**（在 `experiment/metrics.py` 的 `compute_threshold` 中）。

### 2. Precision 的定义与实现

在二分类里（正类 = 用户喜欢，负类 = 不喜欢）：

- **Precision = TP / (TP + FP)**  
  - TP：预测为 1 且真实为 1 的个数  
  - FP：预测为 1 但真实为 0 的个数  
  即：**「被你预测成喜欢的模式里，真正喜欢的比例」**。

代码里直接用 sklearn：

```python
from sklearn.metrics import precision_score
precision_score(true_labels, pred_labels, zero_division=0.0)
```

当没有任何预测为正（TP+FP=0）时，`zero_division=0.0` 会使 precision 为 0，避免除零。

### 3. 和 Recall、F1 的关系

- **Recall = TP / (TP + FN)**：真实喜欢的模式里，被预测成喜欢的比例。
- **F1 = 2 × (Precision × Recall) / (Precision + Recall)**：精确率和召回率的调和平均。

---

## 四、你当前三组结果简要解读

（数字以你当前 JSON 为例，仅作理解用。）

- **Baseline**  
  - 最终轮：accuracy ≈ 0.85，precision ≈ 0.66，recall ≈ 0.70。  
  - 仅用向量相似度，不训练模型，随轮次反馈融合后指标逐步升。

- **Contrastive**  
  - 前几轮 precision/recall 为 0：分数可能普遍低于 0.7，几乎没预测为正，所以 precision=0（zero_division）；后面轮次分数上来，precision/recall 明显升高。  
  - 最终轮：accuracy ≈ 0.94，precision ≈ 0.79，recall = 1.0。  
  - 对比学习学出更区分性的表示，后期「预测为喜欢」里正确比例（precision）和「真实喜欢被召回的比例」（recall）都较高。

- **Preference-Weighted**  
  - 最终轮：accuracy ≈ 0.84，precision ≈ 0.63，recall ≈ 0.63。  
  - 在相似度上乘了特征级偏好权重，介于 Baseline 和 Contrastive 之间，没有额外训练模型。

整体上：**Precision 高**表示「系统推成喜欢的模式里，用户真喜欢的多」；**Recall 高**表示「用户真喜欢的模式里，被系统推出来的多」。阈值固定为 0.7 时，分数分布若偏小会导致前期预测正很少、precision 为 0；若希望更平滑，可改为用分数中位数等动态阈值（当前 `compute_threshold` 里中位数那行被注释掉了）。
