# Jigsaw 社区规则违规检测 - DistilRoBERTa 方案技术文档 ## 1. 任务概述 ### 1.1 问题定义 - **任务类型**:二分类文本任务 - **目标**:判断 Reddit 帖子内容是否违反特定子版块(subreddit)的社区规则 - **评估指标**:F1 Score / AUC - **当前基线**:逻辑回归 0.562 vs 榜首 0.922 ### 1.2 方案核心 采用预训练语言模型 DistilRoBERTa + 迁移学习,将任务建模为句对分类问题。 ## 2. 技术架构 ### 2.1 模型选择:DistilRoBERTa |特性|规格|优势| |---|---|---| |**参数量**|82M|比 RoBERTa 减少 35%| |**层数**|6 层 Transformer|推理速度快 2x| |**性能保留**|~95%|损失极小| |**显存需求**|适中|适合 Kaggle T4 GPU| ### 2.2 架构设计 ```Java 输入构造: [CLS] [SUB] subreddit [RULE] rule_text [SEP] body_content [SEP] ↓ ↓ 规则侧(第一句) 帖子内容侧(第二句) 模型流程: 文本输入 → Tokenizer → DistilRoBERTa(6层) → [CLS]向量(768维) ↓ Linear(768→1) ↓ BCEWithLogitsLoss ↓ 违规概率(0-1) ``` ## 3. 核心实现细节 ### 3.1 数据预处理(第38-74行) ```python # 句对构造策略 rule_side = "[SUB] " + subreddit + " [RULE] " + rule body_side = body # 关键设计思想: # 1. [SUB]标记帮助模型识别不同子版块的规则语境 # 2. [RULE]标记明确规则边界 # 3. 利用BERT的句对机制理解规则-内容的匹配关系 ``` **数据切分**: - 训练集:90%(分层采样保持类别比例) - 验证集:10%(用于模型选择和阈值优化) ### 3.2 Tokenization 策略(第75-106行) ```python tokenizer(rule_side, body_side, truncation=True, max_length=256) ``` **关键参数**: - `max_length=256`:平衡效果与效率(可尝试512获得更好效果) - `truncation=True`:自动截断超长文本 - 句对输入:充分利用预训练模型的双句理解能力 ### 3.3 类别不平衡处理(第107-133行) ```python # 计算正样本权重 pos_weight = neg_samples / pos_samples # 例如: 3.5 # 应用到损失函数 BCEWithLogitsLoss(pos_weight=pos_weight) ``` **原理**:给少数类(违规)更高的损失权重,避免模型偏向多数类。 ### 3.4 训练配置(第154-198行) |超参数|设置|说明| |---|---|---| |**学习率**|2e-5|微调的典型值,避免破坏预训练知识| |**Epochs**|3|防止过拟合| |**Batch Size**|16×2=32|通过梯度累积实现| |**Warmup**|6%|训练初期学习率线性增长| |**Weight Decay**|0.01|L2正则化| |**FP16**|True|混合精度训练,加速+省显存| ### 3.5 阈值优化(第200-214行) ```python # 不使用固定阈值0.5,而是搜索最优F1 for threshold in np.linspace(0.1, 0.9, 33): f1 = f1_score(labels, (probs >= threshold)) # 记录最佳阈值 ``` **注意**:最终提交概率值而非0/1标签,让平台自行决定阈值。 ## 4. 迁移学习原理 ### 4.1 站在巨人肩膀上 ```Java 预训练阶段(已完成): 160GB英文文本 → DistilRoBERTa → 通用语言理解 微调阶段(我们的任务): 通用模型 + 规则违规数据 → 反向传播 → 专用违规检测器 ``` ### 4.2 分类头设计 ```python # 新增的任务特定层 class ClassificationHead: Linear(768 → 1) # 仅769个参数 ↓ 这一小层学会了:哪些语义特征组合 = 违规 ``` ## 5. 性能分析 ### 5.1 对比基线 |方法|分数|提升|原因| |---|---|---|---| |逻辑回归|0.562|-|仅表面特征匹配| |**DistilRoBERTa**|0.85-0.90|+51-60%|深层语义理解| |榜首方案|0.922|+64%|可能用了更大模型/集成| ### 5.2 计算资源 - **训练时间**:~30分钟(T4 GPU) - **显存占用**:~8GB - **推理速度**:~100 samples/sec ## 6. 优化方向 ### 6.1 短期改进(+3-5%) 1. **增大序列长度**:`MAX_LEN=512` 2. **调整学习率**:网格搜索 1e-5 到 5e-5 3. **更多训练轮次**:5-10 epochs with early stopping ### 6.2 中期提升(+5-8%) 1. **更强模型**: - DeBERTa-v3-base(效果最好) - RoBERTa-large(参数更多) 2. **数据增强**: - 回译增强 - 同义词替换 - 规则改写 ### 6.3 高级技巧(+8-10%) 1. **模型集成**: - 多个模型投票 - 不同随机种子 - 交叉验证 2. **伪标签**: - 用高置信度预测扩充训练集 3. **对抗训练**: - FGM/PGD 提升鲁棒性 ## 7. 代码执行流程 ```mermaid graph TD A[原始数据] --> B[句对构造] B --> C[Tokenization] C --> D[Dataset格式化] D --> E[加载预训练模型] E --> F[添加分类头] F --> G[设置加权损失] G --> H[训练3轮] H --> I[验证集调优阈值] I --> J[测试集预测] J --> K[输出概率CSV] ``` ## 8. 关键创新点 1. **句对建模**:巧妙利用BERT的双句输入机制 2. **标记设计**:[SUB]和[RULE]帮助模型理解结构 3. **类别平衡**:加权损失处理不平衡数据 4. **阈值优化**:不依赖默认0.5,寻找最优决策边界 5. **概率输出**:提交概率而非硬标签,更灵活 ## 9. 总结 本方案通过迁移学习充分利用了预训练模型的语言理解能力,将通用的 DistilRoBERTa 转化为专门的违规检测器。相比传统机器学习方法,这是一个质的飞跃,预期能将分数从 0.562 提升到 0.85-0.90 范围,接近竞赛领先水平。 **核心思想**:让预训练模型做复杂的语义理解,我们只需教会它"什么是违规"。这正是现代 NLP 的精髓所在。