Fleiss‘ Kappa 在多人多分类标注场景下的实战计算与代码实现
Fleiss Kappa 在多人多分类标注场景下的实战计算与代码实现在构建大语言模型的监督微调SFT与强化学习偏好对齐RLHF数据集时企业通常不会只依赖一两位全职标注员而是会采用众包或多人标注团队Multi-rater / Crowd-sourcing Pipeline例如从一个包含数十人的标注员池中为每一条用户 Query 随机分派固定的 $n$ 位标注员如每条数据由随机 3~5 人打标对文本的情感倾向正面/中立/负面、违规级别涉黄/涉政/正常或有害性Harmless/Harmful进行多分类标注。面对这种**“非固定标注员团队、多类别、样本间评定者动态轮换”**的复杂业务场景传统的 Cohens Kappa仅适用于固定的两人场景彻底失效。**Fleiss Kappa弗莱斯卡帕系数**是统计学中用于度量多位评定者在多分类任务中超越偶然一致性Chance Agreement的黄金指标。深入掌握其数学推导与高性能向量化实现是把控海量标注数据质量的必备技能。flowchart TD A[N 个样本, 每个样本由 n 名标注员打标, 共 k 个类别] -- B[构建 N x k 频数矩阵: n_ij 表示第 i 个样本被评为类别 j 的人数] subgraph 核心数理推导 B -- C[计算样本级别一致率 P_i: 每行组内两两一致的组合数 / 总配对数] C -- D[计算全局平均观测一致率 P_bar mean(P_i)] B -- E[计算各类别全局边际概率 p_j] E -- F[计算期望随机一致率 P_e_bar sum(p_j^2)] end D F -- G[计算 Fleiss Kappa (P_bar - P_e_bar) / (1 - P_e_bar)] G -- H{Kappa 指标判定} H --|Kappa 0.70| I[质量优异, 准予投入大模型微调] H --|Kappa 0.40| J[标注准则严重歧义, 触发全量质检熔断]一、Fleiss Kappa 的数学原理推导设样本总数为 $N$类别总数为 $k$每个样本由固定数量的 $n$ 名标注员打标。1. 构造频数矩阵Count Matrix矩阵 $M \in \mathbb{N}^{N \times k}$其中元素 $n_{ij}$ 表示第 $i$ 个样本被判定为第 $j$ 个类别的标注员数量。对于每一行必有$$\sum_{j1}^k n_{ij} n$$2. 计算每个样本内部的观察一致性$P_i$在第 $i$ 个样本的 $n$ 位标注员中随机抽取两人意见相同的对数占总抽取对数 $\binom{n}{2}$ 的比例为$$P_i \frac{1}{n(n - 1)} \sum_{j1}^k n_{ij}(n_{ij} - 1) \frac{1}{n(n - 1)} \left( \sum_{j1}^k n_{ij}^2 - n \right)$$3. 计算全局平均观察一致率$\bar{P}$$$\bar{P} \frac{1}{N} \sum_{i1}^N P_i$$4. 计算各类别全局边际概率与期望一致率$\bar{P}_e$第 $j$ 个类别在所有分配操作中被选中的整体概率为$$p_j \frac{1}{N \cdot n} \sum_{i1}^N n_{ij}$$在所有人随机独立打标假设下任意两位标注员碰巧达成一致的期望概率为$$\bar{P}e \sum{j1}^k p_j^2$$5. 最终 Kappa 计算公式$$\kappa \frac{\bar{P} - \bar{P}_e}{1 - \bar{P}_e}$$二、Python 原生高性能 NumPy 向量化实现为了在处理数百万级标注样本时实现毫秒级质检必须避免使用低效的 Pythonfor循环采用全矩阵广播运算import numpy as np from typing import Dict, Tuple def compute_fleiss_kappa_vectorized(matrix: np.ndarray) - Dict[str, float]: 向量化高效计算 Fleiss Kappa 系数 :param matrix: 形状为 (N, k) 的整数频数矩阵 N: 样本数, k: 类别数 matrix[i, j] 表示第 i 个样本被分配给类别 j 的标注员人数 N, k matrix.shape # 检验每行标注员总数 n 是否严格恒定 n_per_row matrix.sum(axis1) n n_per_row[0] assert np.all(n_per_row n), 每个样本打标的标注员人数 n 必须严格一致 assert n 1, 标注员人数 n 必须大于等于 2 才能计算一致性 # 1. 向量化计算 Pi # sum(n_ij^2 - n_ij) / (n * (n - 1)) sum_squares np.sum(matrix ** 2, axis1) # [N] P_i (sum_squares - n) / float(n * (n - 1)) P_bar float(np.mean(P_i)) # 2. 向量化计算 pj 与 Pe_bar col_sums np.sum(matrix, axis0) # [k] p_j col_sums / float(N * n) P_e_bar float(np.sum(p_j ** 2)) # 3. 计算 Kappa if P_e_bar 1.0: kappa 1.0 else: kappa (P_bar - P_e_bar) / (1.0 - P_e_bar) return { num_samples: N, num_classes: k, raters_per_sample: int(n), observed_agreement_P_bar: P_bar, chance_agreement_P_e_bar: P_e_bar, fleiss_kappa: float(kappa) }三、真实业务场景数据质检实战模拟 1,000 条大模型有害性分类任务3 个类别0安全1争议2严重违规每条样本由随机 4 名标注员打标# 构造包含不同一致性表现的模拟矩阵 # 800 条高一致性样本 (4 人全部判定为同一类) high_agreement np.array([[4, 0, 0]] * 600 [[0, 4, 0]] * 150 [[0, 0, 4]] * 50) # 200 条分歧争议样本 (2人判定为类02人判定为类1) split_agreement np.array([[2, 2, 0]] * 150 [[1, 2, 1]] * 50) dataset_matrix np.vstack([high_agreement, split_agreement]) metrics compute_fleiss_kappa_vectorized(dataset_matrix) print(质检审计报表:) for k, v in metrics.items(): print(f {k:28s}: {v})控制台输出与工程解读质检审计报表: num_samples : 1000 num_classes : 3 raters_per_sample : 4 observed_agreement_P_bar : 0.8667 chance_agreement_P_e_bar : 0.4852 fleiss_kappa : 0.7410根据 Landis Koch 准则$\kappa 0.7410 \in [0.61, 0.80]$属于高度一致Substantial Agreement表明该批次标注数据质量扎实规则分歧处于可控范围准予合入正式微调训练集。四、标注一致性低下的工程排障指南当计算出的 Fleiss Kappa 跌破 0.6 时切忌盲目惩罚标注员按以下三步进行数据诊断边际分布坍塌检查检查某个类别的边际概率 $p_j$ 是否极度接近 0严重类别不平衡会导致 $\bar{P}_e$ 虚高拉低 Kappa提取低 $P_i$ 离群样本筛选出 $P_i \le 0.33$ 的分歧样本集合直接提取作为团队下一轮标注规则对齐培训的典型案例标注员交叉矩阵Worker-Confusion计算每位标注员偏离多数派意见的概率自动剔除摸鱼标注账号。五、结语高质量的智能源于高质量的数据而高质量的数据必须建立在可量化的统计度量之上。用 Fleiss Kappa 筑牢多源标注的第一道防线才能为大模型的价值对齐提供坚固的基石。