2. 标签传播算法基础原理:半监督学习、图结构、标签传播的直觉与迭代过程
这一章,我们来聊聊标签传播算法的根基。说白了,就是搞清楚它凭什么能在数据治理里发挥作用。我接触这个算法好几年了,每次用它处理那些“半死不活”的脏数据,都觉得它挺神奇的。
你可能会问:什么是半监督学习?图结构又是什么鬼?标签传播到底是怎么“传染”的?别急,我们一个一个来拆。
2.1 从“半监督”说起
传统的机器学习,要么是有监督(全靠标注数据),要么是无监督(全靠自己聚类)。但在实际的数据治理场景里,我们遇到的情况往往是:少量标注 + 大量未标注。为什么?因为标注数据太贵了。我早年间在一个客户数据清洗项目里,光标注几千条“是否同一人”就花了一周时间。
这就是半监督学习的用武之地。它利用少量已知标签,去推测大量未知标签。你想想看,这像不像一个班级里,老师只教了几个尖子生,然后让他们去带动全班同学?
核心思想:假设数据中存在内在的聚类结构或流形结构。相似的样本应该拥有相似的标签。
| 学习范式 | 数据标注情况 | 典型应用 |
|---|---|---|
| 有监督学习 | 全部标注 | 需要大量人工,成本高 |
| 无监督学习 | 全部未标注 | 聚类分析,不依赖标签 |
| 半监督学习 | 少量标注 + 大量未标注 | 标签传播、自训练等,适合数据治理 |
我个人习惯把半监督学习想象成一个“纠错机制”。标注数据是铁证,未标注数据是嫌疑人。算法通过它们之间的关联,把铁证慢慢地“传染”给嫌疑人。
2.2 图结构:数据关系的“地图”
标签传播算法依赖一个关键的东西——图。图是由节点和边组成的。每个数据点就是一个节点,节点之间的相似度就是边。
举个例子。假设我们有1000条客户记录,一部分有“是否重复”的标签。我们把这1000条记录当成1000个节点。名字相似、地址相近的两条记录之间,我们就连一条边,边的粗细代表相似度高低。
嗯,这里要注意:图的质量直接决定了传播效果。我在项目里见过有人直接用皮尔逊相关系数算相似度,结果图里全是弱连接,传播到一半就断了。
我的经验:建图时,我通常会用K近邻(KNN)或ε-半径图。KNN保证每个节点都有固定数量的邻居,不容易产生孤立节点。ε-半径图则更适合密度均匀的数据。
图结构有几个重要参数:
- 节点数:就是样本总数。
- 边与权重:用高斯核函数计算:
w_ij = exp(-||x_i - x_j||² / σ²)。σ控制着相似度的衰减速度。 - 邻接矩阵:一个N×N的矩阵,记录了节点间的连接关系。
你想想看,有了这个“地图”,标签传播就有了路径。
避坑指南:我曾经在一个高噪声数据集上直接建全连接图,结果计算量爆炸,而且密集的边让标签传播“糊”成了一片。后来我改用稀疏图,效果好了很多。
2.3 标签传播的直觉:病毒式扩散
直觉上,标签传播就是让已知标签沿着图的边“流”向未知节点。就像一滴墨水落在一张纸上,慢慢洇开。
算法的核心假设是:两个节点越相似,它们的标签越可能相同。这看似简单,但非常强大。
我们可以把传播过程想象成一场“投票”:
- 每个未标记节点,统计它的邻居节点都有哪些标签。
- 邻居节点的权重越高,投票权重越大。
- 得票最多的标签,成为该节点的新标签。
- 重复这个过程,直到标签不再变化。
说得再直白点,就是“跟你的朋友保持一致”。你身边的朋友都是博士,你大概率也是;你邻居都是做清洁的,你大概率也是。
2.4 迭代过程:从模糊到清晰
刚接触这个算法时,我总觉得一次传播就够了。后来发现,一次传播只能影响直接邻居,真正的“远距离”传染,需要多轮迭代。
标准的迭代过程如下:
# 伪代码演示
while not converged:
for each unlabeled node u:
# 统计邻居的标签分布
scores = {}
for each neighbor v of u:
label_v = labels[v]
weight_uv = weight[u][v]
scores[label_v] += weight_uv
# 更新为得分最高的标签
new_label = argmax(scores)
labels[u] = new_label
# 检查是否收敛
if labels unchanged:
break
关键点:每次迭代后,标签会沿着图结构“流动”得更远。一般来说,收敛速度取决于图的直径和权重分布。我见过最快的迭代3轮就稳定了,最慢的跑了100轮。
这里有个细节:已标记节点在迭代中要不要更新?我的习惯是不更新。把它们当做“锚点”,永远不能改变。一旦你让锚点动了,整个传播就会跑偏。
| 迭代要素 | 说明 | 我的建议 |
|---|---|---|
| 初始化 | 已标记节点固定标签,未标记节点随机或统一 | 统一设置为-1,避免干扰 |
| 同步更新 | 所有节点同时用上一轮邻居结果更新 | 保证传播方向一致 |
| 收敛判断 | 本轮标签变化量小于阈值或达到最大轮次 | 阈值设为0,因为离散标签变化就是1 |
为什么迭代会收敛?因为图结构固定,每次更新都是“减少局部能量”,最终会稳定在一个局部最优解。说白了,就是所有节点都找到了一个“舒服”的标签。
来,我们看一张流程图,把整个逻辑串起来。
这张图已经把算法的血肉榨干了。你看,输入是图结构和少数标注,输出是全量标签。中间的无非就是初始化、迭代更新、收敛判断。说得难听点,哪怕你只懂一点点图论,也能跑通一个简化版。
不过,真正应用到数据治理中,我们要考虑的事情远不止这些。比如:图建多大?权重怎么调?遇到标签震荡怎么办?这些坑,我后面会一点点填。