文风相似度算法迭代史

NLST 项目 · 从第一代到第四代的完整迭代记录
记录原则:每个算法写清「动机 → 算法 → 数字 → 判决」;失败与被否证的路线一并保留 ✗(它们与成功同样有价值)。

0. 起点

任务:给定原文 + 一组目标文风范文,让 LLM 改写使文风接近范文、语义不丢。

核心难点:不在生成,而在「文风相似度」这把尺子 —— 它决定目标集合怎么构造、改写效果怎么评价。

最初的直觉(后来被证明过于天真 ✗):用经典计量风格学(Burrows' Delta)就够。


1. 第一代:Burrows Δ(50 维)—— 能测语域,测不了作者

动机

作者归属领域的经典做法:不看内容,看虚词指纹。

算法(含推导)

① 特征映射:设 \(\phi_1(t)\in\mathbb{R}^{50}\) 为手工特征,\(f_j\) 为每千字频率:

\[ \phi_1(t)=\big(f_1(t),\dots,f_{50}(t)\big),\qquad f_j(t)=1000\cdot\frac{c_j(t)}{N(t)} \]

② 标准化(对角仿射):

\[ z_j(t)=\frac{f_j(t)-\mu_j}{\sigma_j},\qquad z(t)=\underbrace{\operatorname{diag}(\sigma)^{-1}}_{A}\big(\phi_1(t)-\mu\big) \]

数学意义:仅把每个坐标轴缩放到单位方差,不改变轴间相关性 ✗。

③ L1 距离及其隐式度量:

\[ d_\Delta(a,b)=\frac{1}{50}\sum_{j=1}^{50}|z_j(a)-z_j(b)|=\frac{1}{50}\bigl\|A(\phi_1(a)-\phi_1(b))\bigr\|_1 \;\Longleftrightarrow\; M_\Delta=\operatorname{diag}(1/\sigma_j^2) \]

两个可推导出的病灶 ✗:

  1. 共线性未处理:真实协方差 \(C\) 远非对角,而 \(\operatorname{diag}\) 假设各维独立 → 距离在相关轴上被重复计算;
  2. L1 不具旋转不变性:\(\|Rx\|_1 \neq \|x\|_1\) —— 换一组基距离就变,因此只能“恰好对齐”手选的 50 个轴。

结果

项数值
人评 ρ(距离型,负号正确 ✓)−0.194 ~ −0.209

判决 ✗

能测「语域」,测不了「个人风格」:

表注(本节数值定义):


2. 第二代:Δ_R(残差风格空间)—— 用探针给「成分」定权重

2.1 动机

第一代的失败根因是「题材与文风混在特征里」✗。解决思路:不筛特征,筛 SVD 成分 —— 让数据自己说哪些方向偏文风。

2.2 算法(含推导)

① 特征映射 × 族权(\(W\) 由扰动探针估计:功能层响应 ÷ 内容层响应):

\[ X(t)=\phi_2(t)\odot W,\qquad W_j=\sqrt{\frac{\mathrm{ratio}_{f(j)}}{\max_{f'}\mathrm{ratio}_{f'}}},\quad \mathrm{ratio}_f=\frac{R^{\mathrm{func}}_f}{R^{\mathrm{content}}_f} \]

② 标准化:

\[ Z(t)=\frac{X(t)-\mu}{\sigma} \]

③ 旋转(旧Δ 缺失的关键一步) —— 对去中心化矩阵做 SVD,使协方差在新坐标系里被对角化:

\[ Z_c=Z-\bar Z=U\Sigma V^{\top},\qquad C=\frac{1}{n-1}Z_c^{\top}Z_c=V\operatorname{diag}(\lambda_1,\dots)V^{\top},\quad \lambda_1\ge\lambda_2\ge\cdots \]
\[ \pi(t)=V_{:60}^{\top}Z(t)\in\mathbb{R}^{60},\qquad V_{:60}^{\top}C\,V_{:60}=\operatorname{diag}(\lambda_1,\dots,\lambda_{60}) \]

④ 方向权重(第二次探针) —— 每个方向上的信噪比与软阈值收缩:

\[ r_j=\frac{\mathbb{E}\bigl[|(z_f-z)V_j^\top|\,/\,\|z_f-z\|\bigr]} {\mathbb{E}\bigl[|(z_c-z)V_j^\top|\,/\,\|z_c-z\|\bigr]},\qquad w_j=\frac{\operatorname{clip}(r_j-1,0,\infty)}{\max_k\operatorname{clip}(r_k-1,0,\infty)} \]

⑤ 加权 L2 → 隐式度量矩阵:

\[ v(t)=\bigl(Z(t)V_{:60}^{\top}\bigr)\odot w,\qquad d_R(a,b)=\|v(a)-v(b)\|_2 \]
\[ d_R(a,b)^2=\bigl\|D V_{:60}^{\top}\bigl(Z(a)-Z(b)\bigr)\bigr\|_2^2 =\Delta Z^{\top}\underbrace{\Bigl(V_{:60}^{\top}D^{2}V_{:60}\Bigr)}_{M_R}\Delta Z, \qquad D=\operatorname{diag}(w) \]

结论:\(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 ✓

表注(本节数值定义):

2.4 结果与局限

项数值
人评 ρ−0.218 ~ −0.227(单口径最强之一 ✓)
随机配对不可判率33% ✗
弱区分簇净值郁达夫 +0.036 / 果戈理 +0.044 ✗(不过线)

判决 ✗✓:显著优于第一代,但仍是"位置型" —— 测的是语域+位置,个体差异依然分不开。

表注(本节数值定义):


3. 第三代:sim_new(向度模型)—— 从「位置」到「方向」

3.1 用户提出的核心构想

"以内容本身为源,不同文风可以延伸出不同向度。"

即:文风不该是绝对位置 ✗,而应是相对于内容的位移方向 ✓。

3.2 算法(含推导)

① 内容原点(定义性一步):对内容 \(s\) 的 \(K\) 份多文风渲染取条件期望:

\[ c(s)=\frac{1}{K}\sum_{i=1}^{K}\phi(t_i^{(s)})\approx \mathbb{E}\bigl[\phi\,\big|\,\text{content}=s\bigr] \]

② 风格位移(内容扣除 + 居中性):

\[ \delta(t)=\phi(t)-c\bigl(s(t)\bigr),\qquad \mathbb{E}_{t\in s}\bigl[\delta(t)\bigr]=0 \]

③ 风格子空间(协方差特征分解):

\[ C_{\mathrm{sty}}=\frac{1}{N-1}\sum_i \delta_i\delta_i^{\top}=Q\Lambda Q^{\top},\qquad P_{\mathrm{sty}}=Q_{:r}^{\top}\in\mathbb{R}^{r\times 249}\ (r=5) \]

④ 相似度(余弦):

\[ \mathrm{sim}(a,b)=\frac{(P_{\mathrm{sty}}z_a)\cdot(P_{\mathrm{sty}}z_b)}{\|P_{\mathrm{sty}}z_a\|\,\|P_{\mathrm{sty}}z_b\|} =\cos\angle\bigl(P_{\mathrm{sty}}z_a,\ P_{\mathrm{sty}}z_b\bigr) \]

⑤ 去策略混淆(正交投影):

\[ C_{\mathrm{strat}}=\mathrm{Cov}\bigl(\text{cross-strategy shifts at fixed content\&target}\bigr), \qquad P_{\mathrm{strat}}=(Q^{\mathrm{strat}})_{:3}^{\top} \]
\[ \mathrm{sim}^{*}(a,b)=\cos\Bigl(P_{\mathrm{sty}}(I-P_{\mathrm{strat}})z_a,\ P_{\mathrm{sty}}(I-P_{\mathrm{strat}})z_b\Bigr) \]

\((I-P_{\mathrm{strat}})\) 是幂等的正交投影算子:\((I-P)^2=I-P\),把“策略方向”整体扣除。

3.3 迭代中的重大否证(四种原点方案)

原点方案判决失败机制
① 语料全局均值✗测出的是语域
② 位置型空间✗鲁迅↔鲁迅 ≈ 鲁迅↔知乎
③ LLM 平实化复述(v1/v2)✗过程类别不匹配:复述产物 vs 迁移产物,过程差异淹没文风 ✗
④ 同过程 + 同内容 + 多文风矩阵✓ 唯一存活——

由此确立原点判据(后续所有工作的基础 ✓):

表注(本节数值定义):

合格原点必须 ① 同族(同生成过程)② 是文风多样族的质心(δ 零均值)。

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 边缘)

表注(本节数值定义):

弱区分簇(老舍/郁达夫/果戈理——同语域的个体差异)净值仍 < 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 类即饱和

表注(本节数值定义):

4.2 算法(含推导)

① 判别器(TF-IDF + 逻辑回归),以多类交叉熵训练:

\[ \mathrm{tf}(g,t)=\bigl(1+\log \mathrm{cnt}(g,t)\bigr)\cdot\log\frac{N}{\mathrm{df}(g)},\qquad g\in\{\text{char }2\sim 4\text{-gram}\} \]
\[ \hat p(t)=\mathrm{softmax}\bigl(W v(t)+b\bigr),\qquad \mathcal{L}=-\sum_{c=1}^{11} y_c \log \hat p_c(t) \]

留存准确率 0.988(11 类,随机基线 0.09)。

② 风格坐标 = 判别分数(logit):

\[ s(t)=\mathrm{decision\_function}\bigl(W v(t)+b\bigr)\in\mathbb{R}^{11} \]

③ 分块标准化 + 拼接:

\[ \tilde s(t)=\frac{s(t)-\bar s}{\mathrm{std}(s)},\qquad \tilde z_{249}(t)=\frac{z_{249}(t)-\overline{z_{249}}}{\mathrm{std}(z_{249})} \]
\[ \boxed{\ \phi_{v3}(t)=\Bigl[\ \tilde z_{249}(t)\ \big|\ \alpha\cdot\tilde s(t)\ \Bigr],\qquad \alpha=3\ } \]

(\(\alpha\) 扫描结论见 4.4 节;跨批次统计量必须冻结是本步的硬约束 ✗✓。)② 风格坐标 = 判别分数(logit)**:

\[ s(t)=\mathrm{decision\_function}\bigl(W v(t)+b\bigr)\in\mathbb{R}^{11} \]

③ 分块标准化 + 拼接:

\[ \tilde s(t)=\frac{s(t)-\bar s}{\mathrm{std}(s)},\qquad \tilde z_{249}(t)=\frac{z_{249}(t)-\overline{z_{249}}}{\mathrm{std}(z_{249})} \]
\[ \boxed{\ \phi_{v3}(t)=\Bigl[\ \tilde z_{249}(t)\ \big|\ \alpha\cdot\tilde s(t)\ \Bigr],\qquad \alpha=3\ } \]

(\(\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,标注为"提示性提升" ✗

表注(本节数值定义):

4.5 又一条否证(第 9 条)

近义词组特征(用户提出 ✓,方向正确但):对裸 249 微正(+0.004 ✓),对 v3 有害 ✗(+0.573→+0.501)—— TF-IDF 已覆盖词汇层信息,重复编码 = 弱编码挤掉强编码 ✗。


5. 服务口径:组合指标

\[ \mathrm{sim\_served}=0.1\,z(\mathrm{sim}_{v3})+0.4\,z(-\Delta_R)+0.5\,z(-\Delta_{\text{old}}), \qquad z\ \text{estimated on the 150-item kit} \]

分半协议验证(一半标注人拟合、另一半验证 ✓):

方向组合最好单口径差
A 拟合→B 验证+0.226+0.212+0.014 ✓
B 拟合→A 验证+0.288+0.247+0.041 ✓

个体差异是设计依据 ✓:逐标注人胜出 组合13 / Δ_R10 / 旧Δ7 / sim_new6 —— 不同人判据不同,单一指标不可能通吃 ✓。

表注(本节数值定义):


6. 全部否证清单(9 条)

#被否证的路线否证方式附带收获
1全局均值作原点测出语域确立"位置型=语域距离"
2位置型空间当文风相似度鲁迅↔鲁迅 ≈ 鲁迅↔知乎催生内容质心方案
3LLM 平实化作原点(v1/v2)Q1 占比 13% / Q2 cos+0.013 / Q3 偏移 0.24「同族质心」判据成型
4目标集盲目扩维E2 反降T1 一致性判据
5裸 n-gram 作特征探针 0/2497 通过证明其为题材特征
625 作者扩维(softmax)PCA+全 α 扫描均不如 11 类确定 11 类饱和
7全局质心修正相似度(CSLS)λ 扫描无增益;分半不一致hubness 存在但非人评干扰源
8大语料重算 W+μ/σ人评退步 +0.227→+0.178sim 家族对此恒等(被 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. 关键数字总表

指标旧ΔΔ_Rsim_v2v3(现行)
维度/机制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

表注(本节数值定义):


9. 经验教训(刻进流程的规则)

  1. 任何新特征块的验收基线,必须是"现有完整配置" ✗✓(拿裸特征当基线会虚高)。
  2. 跨批次统计量必须冻结(踩过 4 次 ✗)。
  3. "改文件 + 立即运行"有抢跑风险,分步执行 ✓。
  4. 生成类实验必须 ≥3 轮新采样报均值±SD(单样本 sim 摆动可达 0.67 ✗)。
  5. bootstrap 粒度匹配结论粒度(E2 按内容、rho 按人×题、生成按轮 ✓)。
  6. 诚实报告混合信号:宁可写"说不清",不可强行下结论 ✗。

附:四者对照总表(数学视角)

方法变换 \(T\)距离 \(d\)内容消除隐式度量
旧Δ对角缩放L1无 ✗\(\operatorname{diag}(1/\sigma^2)\)
Δ_RSVD 旋转 + 探针加权L2无(部分压制)\(V_{:60}^{\top}D^2V_{:60}\)
sim_new质心扣除 + \(P_{\mathrm{sty}}\)余弦有(同内容质心) ✓球面(\(I\))
v3TF-IDF + 判别器 + 拼接同上(接 sim_new 链)有(继承 \(\delta\))✓继承

一句话总结:四代演进的数学主线是 ——

从「对角缩放空间量 L1」(假设独立 ✗),

到「旋转后量加权 L2」(去相关 ✓),

再到「先扣除内容质心、再在低维方向空间量余弦」(消除内容 ✓✓),

最后「同一链条上叠加有监督嵌入」(补个体分辨力 ✓✓)。


本文档由 NLST 项目迭代过程整理;数字均为实测,失败路线保留原样。