文风相似度算法迭代史
NLST 项目 · 从第一代到第四代的完整迭代记录
记录原则:每个算法写清「动机 → 算法 → 数字 → 判决」;失败与被否证的路线一并保留 ✗(它们与成功同样有价值)。
0. 起点
任务:给定原文 + 一组目标文风范文,让 LLM 改写使文风接近范文、语义不丢。
核心难点:不在生成,而在「文风相似度」这把尺子 —— 它决定目标集合怎么构造、改写效果怎么评价。
最初的直觉(后来被证明过于天真 ✗):用经典计量风格学(Burrows' Delta)就够。
1. 第一代:Burrows Δ(50 维)—— 能测语域,测不了作者
动机
作者归属领域的经典做法:不看内容,看虚词指纹。
算法(含推导)
① 特征映射:设 \(\phi_1(t)\in\mathbb{R}^{50}\) 为手工特征,\(f_j\) 为每千字频率:
② 标准化(对角仿射):
数学意义:仅把每个坐标轴缩放到单位方差,不改变轴间相关性 ✗。
③ L1 距离及其隐式度量:
两个可推导出的病灶 ✗:
- 共线性未处理:真实协方差 \(C\) 远非对角,而 \(\operatorname{diag}\) 假设各维独立 → 距离在相关轴上被重复计算;
- L1 不具旋转不变性:\(\|Rx\|_1 \neq \|x\|_1\) —— 换一组基距离就变,因此只能“恰好对齐”手选的 50 个轴。
结果
| 项 | 数值 |
|---|---|
| 人评 ρ(距离型,负号正确 ✓) | −0.194 ~ −0.209 |
判决 ✗
能测「语域」,测不了「个人风格」:
- 鲁迅 ↔ 知乎 ≈ 鲁迅 ↔ 鲁迅(同量级 ✗)—— 二者同为"现代规范书面语",即语域相同;
- 文献佐证:Burrows 原始要求 MFW 200–500 个,我们只用 50 个 → 太少 ✗。
表注(本节数值定义):
- 人评 ρ:自动指标的值 与 人工评分(五档:不是 / 也许不是 / 都有可能 / 也许是 / 是)之间的 Spearman 秩相关;每人先各自 z 标准化以消除个人打分尺度差异。
- 负号的意义:旧Δ 是距离(越小越像),人评是相似度(越大越像),因此相关理应为负 ✓;则 |ρ| 才是“谁更准”的度量(旧Δ |ρ|=0.202)。
- 参照系:本任务 人-人一致性上界 = +0.363(分半验证)——任何完美指标的 |ρ| 也不能超出这一量级;0.2 已相当于上界的 ~55%。
2. 第二代:Δ_R(残差风格空间)—— 用探针给「成分」定权重
2.1 动机
第一代的失败根因是「题材与文风混在特征里」✗。解决思路:不筛特征,筛 SVD 成分 —— 让数据自己说哪些方向偏文风。
2.2 算法(含推导)
① 特征映射 × 族权(\(W\) 由扰动探针估计:功能层响应 ÷ 内容层响应):
② 标准化:
③ 旋转(旧Δ 缺失的关键一步) —— 对去中心化矩阵做 SVD,使协方差在新坐标系里被对角化:
④ 方向权重(第二次探针) —— 每个方向上的信噪比与软阈值收缩:
⑤ 加权 L2 → 隐式度量矩阵:
结论:\(d_R(a,b)=\sqrt{\Delta Z^{\top} M_R\, \Delta Z}\),其中 \(M_R\) 是低秩(rank 60)、非对角的度量矩阵;\(d_R\) 实测中不可判阈值为 res_floor(残余范数的 10 分位)。
2.3 迭代中的关键事故与修复
| 事故 | 根因 | 修复 |
|---|---|---|
| 鲁迅↔知乎 异常近 | 建空间 seed 83 / 下游重算 seed 37 → z 与 W 错位 ✗ | 统一 seed 37;W 写入 npz 成为唯一真值 ✓ |
| 15 成分时几乎无风格方向 | 风格信号藏在中后段方差 | 成分数扩到 60 ✓ |
表注(本节数值定义):
- 种子(seed):随机数发生器初值。建空间时用种子 83 抽样/打乱语料,下游脚本重建族权时却用 37 —— 两套随机结果不匹配,使逐维标准化参数 \(\mu,\sigma\) 与族权 \(W\) 错位 ✗。
- \(z\) 与 \(W\):\(z\) 是逐维标准化后的特征(减均值除标准差);\(W\) 是 14 个特征族各自的权重(由扰动探针估计,反映“该族多能反映文风”)。两者错位 ⇒ 嵌入扭曲。
- 修复的不变量:\(W\) 写入
style_v2_space.npz后成为唯一真值 ✓,所有下游只读不重算。
2.4 结果与局限
| 项 | 数值 |
|---|---|
| 人评 ρ | −0.218 ~ −0.227(单口径最强之一 ✓) |
| 随机配对不可判率 | 33% ✗ |
| 弱区分簇净值 | 郁达夫 +0.036 / 果戈理 +0.044 ✗(不过线) |
判决 ✗✓:显著优于第一代,但仍是"位置型" —— 测的是语域+位置,个体差异依然分不开。
表注(本节数值定义):
- 不可判率 33%:一对文本若两侧的残差强度(在风格子空间的投影范数)任一低于
res_floor(语料自身残差强度的 10 分位),则返回 NaN 而非强给距离 ✓(诚实机制)。随机配对下大量相似对残差偏弱,故约 1/3 不可判 ✗。 - 弱区分簇:指语域相同、个体不同的三位作者 —— 老舍 / 郁达夫 / 果戈理(鲁迅译)。
- 净值:
自一致度 − 跨相似度,即“同风格的内部一致性”减去“与其它风格的相似度”;≥0.05 才说明该风格构成一个独立方向 ✓(本行两值均未达标 ✗)。
3. 第三代:sim_new(向度模型)—— 从「位置」到「方向」
3.1 用户提出的核心构想
"以内容本身为源,不同文风可以延伸出不同向度。"
即:文风不该是绝对位置 ✗,而应是相对于内容的位移方向 ✓。
3.2 算法(含推导)
① 内容原点(定义性一步):对内容 \(s\) 的 \(K\) 份多文风渲染取条件期望:
② 风格位移(内容扣除 + 居中性):
③ 风格子空间(协方差特征分解):
④ 相似度(余弦):
⑤ 去策略混淆(正交投影):
\((I-P_{\mathrm{strat}})\) 是幂等的正交投影算子:\((I-P)^2=I-P\),把“策略方向”整体扣除。
3.3 迭代中的重大否证(四种原点方案)
| 原点方案 | 判决 | 失败机制 |
|---|---|---|
| ① 语料全局均值 | ✗ | 测出的是语域 |
| ② 位置型空间 | ✗ | 鲁迅↔鲁迅 ≈ 鲁迅↔知乎 |
| ③ LLM 平实化复述(v1/v2) | ✗ | 过程类别不匹配:复述产物 vs 迁移产物,过程差异淹没文风 ✗ |
| ④ 同过程 + 同内容 + 多文风矩阵 | ✓ 唯一存活 | —— |
由此确立原点判据(后续所有工作的基础 ✓):
表注(本节数值定义):
- Q1(投影占比):平实化产物相对源文的位移中,落在风格子空间 \(P_{\mathrm{sty}}\) 的比例(实测 13%)—— 说明大部分位移不属文风方向 ✗。
- Q2(跨内容一致性):不同内容的平实化位移方向之间的余弦中位数(实测 +0.013)—— 近于正交,说明是逐文本噪声而非共享文风 ✗。
- Q3(偏移占比):新原点相对“矩阵质心”的偏移量,除以该空间残余位移尺度(实测 0.24,旧原点为 0.00)—— 小数说明原点居中 ✓,大数说明偏离 ✓✗。
合格原点必须 ① 同族(同生成过程)② 是文风多样族的质心(δ 零均值)。
3.4 结果
| 项 | 数值 |
|---|---|
| E1(仅内容扣除) | 同文风 +0.19 vs 异 −0.02(差 +0.21 ✓) |
| E2(加 P_sty r=5) | 判别差 +0.562(r 越大越差:10→+0.347,30→+0.185 ✗) |
| 策略混淆 | 策略位移 = 文风位移的 0.94 倍 ✗;destrat 后 0.36→0.20(−44% ✓) |
| 人评 ρ | v2: +0.115(p=0.063 边缘) |
表注(本节数值定义):
- E1 / E2:在按内容切分的训练/留出集上测的判别力 —— E1 只做内容质心扣除;E2 再加 \(P_{\mathrm{sty}}\) 投影。指标为「同文风跨内容对的 cos 均值」减「异文风对的 cos 均值」,差值越大越好 ✓。
- 策略混淆的两个数:0.94 = 只换策略造成的位移 ÷ 换文风造成的位移(接近 1 意味着策略与文风一样“大”✗);destrat 后为 0.20 ✓。
- 文风分离度 0.556→0.532:同文风 cos 均值减异文风 cos 均值,投影后仅损失 4% ✓。
- p = 0.063:Spearman 相关的置换检验显著度;>0.05 意味着“边缘显著” ✗✓。
弱区分簇(老舍/郁达夫/果戈理——同语域的个体差异)净值仍 < 0.05。
3.5 遗留问题(回顾)✗
4. 第四代:v3(有监督作者嵌入)—— 唯一有效的扩维
4.1 三次失败在前(扩维三连否 ✗)
| 尝试 | 结果 | 机制 |
|---|---|---|
| 目标集扩维(加萧红/许地山/AI平实) | E2 0.548→0.503 ✗ | 同类成员方差共线,不产生新方向 |
| 裸字符 n-gram 指纹(3 种启发式 + 探针) | 探针 0/2497 通过 ✗ | 裸 n-gram 是题材特征非文风特征 |
| 25 作者扩维(软 max 判别) | E2 反降 ✗ | 噪声>信号,11 类即饱和 |
表注(本节数值定义):
- E2 前后两个数:0.548 = 12 文风矩阵下;0.503 = 加入萧红/许地山/AI平实后(反降 ✗)。
- 探针 0/2497:2497 个候选 n-gram 中,通过“功能层响应比 ≥ 内容层响应比”的个数(0 ✗);探针比值定义见第 7 节。
- 11 类饱和:作者数从 11 增至 25 后各项指标反降,故后续固定为 11 ✓。
4.2 算法(含推导)
① 判别器(TF-IDF + 逻辑回归),以多类交叉熵训练:
留存准确率 0.988(11 类,随机基线 0.09)。
② 风格坐标 = 判别分数(logit):
③ 分块标准化 + 拼接:
(\(\alpha\) 扫描结论见 4.4 节;跨批次统计量必须冻结是本步的硬约束 ✗✓。)② 风格坐标 = 判别分数(logit)**:
③ 分块标准化 + 拼接:
(\(\alpha\) 扫描结论见 4.4 节;跨批次统计量必须冻结是本步的硬约束 ✗✓。)
4.3 部署事故与修复
跨批次标准化 ✗(第 4 次踩同型坑):
题包用自己的统计量算 z → 坐标与矩阵不同源 → 验收失败。
修复:所有 μ/σ 一律冻结在矩阵批次上,题包沿用 ✓。
4.4 结果
| 项 | 数值 |
|---|---|
| E2 判别差 | +0.573(基线 +0.562)✓ |
| 弱区分簇 | 郁达夫 +0.054 / 果戈理 +0.060(双双越过 0.05 ✓✓) |
| 人评留出(430 对) | +0.188(sim_v2 +0.111)—— CI 跨 0,标注为"提示性提升" ✗ |
表注(本节数值定义):
- E2 +0.573:含义同第 3.4 节表注(越高越好);基线是不加监督块的 +0.562。
- 弱区分簇的两个数:净值的具体意义见第 2.4 节表注;+0.054 / +0.060 均越过 0.05 阈值 ✓✓(历史上首次)。
- 人评留出(430 对):人评数据从未参与 v3 的任何训练/调参,故为干净留出集;+0.188 是该集上的 Spearman。
- CI 跨 0:bootstrap 400 次重采样的 95% 置信区间包含 0 —— 意味着“提示性提升”而非“统计显著” ✗✓。
4.5 又一条否证(第 9 条)
近义词组特征(用户提出 ✓,方向正确但):对裸 249 微正(+0.004 ✓),对 v3 有害 ✗(+0.573→+0.501)—— TF-IDF 已覆盖词汇层信息,重复编码 = 弱编码挤掉强编码 ✗。
5. 服务口径:组合指标
分半协议验证(一半标注人拟合、另一半验证 ✓):
| 方向 | 组合 | 最好单口径 | 差 |
|---|---|---|---|
| A 拟合→B 验证 | +0.226 | +0.212 | +0.014 ✓ |
| B 拟合→A 验证 | +0.288 | +0.247 | +0.041 ✓ |
个体差异是设计依据 ✓:逐标注人胜出 组合13 / Δ_R10 / 旧Δ7 / sim_new6 —— 不同人判据不同,单一指标不可能通吃 ✓。
表注(本节数值定义):
- 拟合/验证:把标注人按奇偶拆成 A/B 两半(不共用任何人),在一半上搜索权重、在另一半上验证 —— 两侧结论一致才算可信 ✓。
- 逐标注人胜出次数:对每一位标注人单独算各口径与其评分的 ρ,取最高者为“该人的胜出口径”,再统计 44 位中谁支持谁 —— 这是“不同人判据不同”的直接证据 ✓。
6. 全部否证清单(9 条)
| # | 被否证的路线 | 否证方式 | 附带收获 |
|---|---|---|---|
| 1 | 全局均值作原点 | 测出语域 | 确立"位置型=语域距离" |
| 2 | 位置型空间当文风相似度 | 鲁迅↔鲁迅 ≈ 鲁迅↔知乎 | 催生内容质心方案 |
| 3 | LLM 平实化作原点(v1/v2) | Q1 占比 13% / Q2 cos+0.013 / Q3 偏移 0.24 | 「同族质心」判据成型 |
| 4 | 目标集盲目扩维 | E2 反降 | T1 一致性判据 |
| 5 | 裸 n-gram 作特征 | 探针 0/2497 通过 | 证明其为题材特征 |
| 6 | 25 作者扩维(softmax) | PCA+全 α 扫描均不如 11 类 | 确定 11 类饱和 |
| 7 | 全局质心修正相似度(CSLS) | λ 扫描无增益;分半不一致 | hubness 存在但非人评干扰源 |
| 8 | 大语料重算 W+μ/σ | 人评退步 +0.227→+0.178 | sim 家族对此恒等(被 z 洗掉);Δ_R 不可判率 33%→0% ✓ |
| 9 | 近义词组特征块 | 对 v3 有害 | 词汇信息已被有监督嵌入覆盖 |
7. 判据集(四条,可复用于任何新想法)
| 判据 | 量化标准 | 验证记录 |
|---|---|---|
| 原点判据 | 同族 + 文风多样族的质心;‖E[δ]‖/RMS(δ)≈0 | 四选一,仅矩阵存活 ✓ |
| 方向判据(净值) | 自一致度 − 跨相似度 ≥ 0.05 | 郁达夫 +0.036 ✗ → +0.054 ✓ |
| 特征判据(探针响应比) | R_f/R_c ≥ 1 | 裸 n-gram 0/2497 ✗;249 维风格族通过 ✓ |
| 防过拟合(分半) | 两向均优于基线 | 组合 +0.014/+0.041 ✓ |
8. 关键数字总表
| 指标 | 旧Δ | Δ_R | sim_v2 | v3(现行) |
|---|---|---|---|---|
| 维度/机制 | 50 维手工 | 249+SVD60+探针 | 249+矩阵+P_sty | +11 维有监督 |
| E2 判别差(r=5) | — | +0.548 | +0.562 | +0.573 ✓ |
| 弱簇 郁达夫 | ✗ | +0.036 | +0.045 | +0.054 ✓ |
| 人评 ρ | −0.202 | −0.227 | +0.115 | +0.188 |
| 方差(bootstrap) | — | — | — | E2 ±0.024 / 人评 ±0.047 |
表注(本节数值定义):
- E2 判别差:同文风对与异文风对在 \(P_{\mathrm{sty}}\) 投影空间的余弦差(越高越好);四个数字对应四代方法在同一矩阵(30 内容 × 12 文风)上的值。
- 人评 ρ 与方差:人评 ρ 的符号因指标类型而异(距离型取负 ✓);方差为 bootstrap 重采样的标准差 ——“对内容重采样”得 E2 的 ±0.024,“对(人×题)对重采样”得人评的 ±0.047。它回答“换一批内容 / 换一批标注人,数字会漂多少” ✗✓。
- 弱簇 +0.054(v3):注意其 bootstrap 区间下界恰在 0.05 阈值附近 —— 属“贴线通过”而非稳健突破 ✗✓。
9. 经验教训(刻进流程的规则)
- 任何新特征块的验收基线,必须是"现有完整配置" ✗✓(拿裸特征当基线会虚高)。
- 跨批次统计量必须冻结(踩过 4 次 ✗)。
- "改文件 + 立即运行"有抢跑风险,分步执行 ✓。
- 生成类实验必须 ≥3 轮新采样报均值±SD(单样本 sim 摆动可达 0.67 ✗)。
- bootstrap 粒度匹配结论粒度(E2 按内容、rho 按人×题、生成按轮 ✓)。
- 诚实报告混合信号:宁可写"说不清",不可强行下结论 ✗。
附:四者对照总表(数学视角)
| 方法 | 变换 \(T\) | 距离 \(d\) | 内容消除 | 隐式度量 |
|---|---|---|---|---|
| 旧Δ | 对角缩放 | L1 | 无 ✗ | \(\operatorname{diag}(1/\sigma^2)\) |
| Δ_R | SVD 旋转 + 探针加权 | L2 | 无(部分压制) | \(V_{:60}^{\top}D^2V_{:60}\) |
| sim_new | 质心扣除 + \(P_{\mathrm{sty}}\) | 余弦 | 有(同内容质心) ✓ | 球面(\(I\)) |
| v3 | TF-IDF + 判别器 + 拼接 | 同上(接 sim_new 链) | 有(继承 \(\delta\))✓ | 继承 |
一句话总结:四代演进的数学主线是 ——
从「对角缩放空间量 L1」(假设独立 ✗),
到「旋转后量加权 L2」(去相关 ✓),
再到「先扣除内容质心、再在低维方向空间量余弦」(消除内容 ✓✓),
最后「同一链条上叠加有监督嵌入」(补个体分辨力 ✓✓)。
本文档由 NLST 项目迭代过程整理;数字均为实测,失败路线保留原样。