☰
无监督学习实战:无标签数据的预处理、聚类与业务解释
2026/10/2 14:23:18 网站建设 项目流程

我近几年做数据分析时,碰到的项目大概有七成以上,拿到的第一份数据都是没有标签的。所谓的“无标签”,就是每一行数据只有一堆特征,没有“正确答案”告诉你它属于哪一类。早期我对这类数据的态度很粗暴——要么硬套一个有监督模型,效果一塌糊涂;要么就只做做散点图,把聚类当成画图工具用。直到后来做用户行为分析、日志文本归类这些实际项目,我才慢慢意识到,无标签数据不是“没有答案”,而是“答案需要你自己去定义”。这篇文章是我“无标签的数据指南”系列的第一篇,我会先聊清楚一个核心问题:当你拿到一堆没有标签的数据,应该从哪儿下手,有哪些坑是必须提前避开的,以及一条能直接落地的实操流程。适合刚接触数据分析、机器学习,或者被无监督学习搞到头大的朋友。

1. 无标签数据为什么值得被严肃对待

1.1 业务场景比你想的多得多

很多人在学校或者网课里学机器学习,上来就是逻辑回归、决策树、卷积神经网络,数据集全都给你标注好了。但等到真正进入项目,你会发现现实世界的数据几乎都是“散装”的。

举几个常见的场景。

第一个是用户分层。公司后台一条用户记录,包含了注册时长、登录频次、消费金额、商品浏览深度,但没有人告诉你这个用户是高价值还是流失风险户。你需要自己从数据里找到模式,把人群拆成几类,再做差异化运营。

第二个是日志聚类。服务端每天产生几千万条日志,人工看不过来,关键词规则又覆盖不全。这时候你把它变成特征向量,做无监督聚类,异常的那一小簇往往就是事故现场。

第三个是文本归类。公司积累了大量工单、评论、对话记录,没有打标,却需要知道大家都在抱怨什么。关键词硬拆容易漏,预训练模型成本又高,这时候 TF-IDF 加聚类反而是性价比最高的解法。

第四个是异常检测。用户操作行为、机器监控指标、银行流水,它们没有“正常/异常”的标签,但异常模式往往天然就长在数据密度分布里。用无监督方法去建模,可以做到“你不知道要找什么,但能把不对劲的捞出来”。

这还只是最常见的几种。本质上,“没有标签”才是数据的默认状态,有标签反而是稀缺资源。如果你只能处理带标签的数据,你的分析半径会被卡死在一小撮人工标注过的数据上。

1.2 无监督比有监督更需要业务理解

有监督学习里,标签本身就是“标准答案”,模型的任务只是找一条从特征到答案的函数。你的好坏主要由准确率、召回率这些指标来定义,指标定了,方向就定了。

无监督学习不一样。它没有一个可对标的“正确答案”,你选什么特征、用什么距离度量、聚成几类、怎么解释每一类,每一步都是人来做决策。换句话说,无监督学习更像“给数据立规矩”,你立的规矩合不合理,直接决定了结果的可用性。

这也是我见过最多新手翻车的地方。他们拿到数据就标准化、就 KMeans、就画图,中间没有任何业务校验。跑出来的簇看着很“数学”,放到业务里却完全没法解释。所以在这篇文章里,我会反复强调一个观点:无标签数据分析的第一步是定目标,不是跑算法。

1.3 一套通用的处理思路可以先立起来

无标签数据的方法论虽然不像有监督那么“自动”,但它是有完整路径的。我自己跑过很多轮之后,总结下来是五个环节:

  1. 明确业务诉求:你是要做分层、找异常、还是做归类?这个目标决定了后续每一步。
  2. 数据清洗与预处理:没有标签已经很难了,数据里再带着脏值、重复值、缺失值,结果基本不能看。
  3. 特征工程与度量选择:无标签数据没有“帮助模型”的说法,你的特征表达一定要服务于你想发现的结构。
  4. 算法与参数适配:聚类、降维、密度估计,各有各的适用边界,不是无脑 KMeans。
  5. 结果解释与验证:聚类完不是结束,你需要把每一簇拿出来看特征分布,证明这个簇真的“有意义”。

这套思路我会在后面的章节里拆开讲,其中第二和第三步是最容易卡住的,我会多花一点篇幅。

2. 拿到数据之后的预处理,决定了你后面所有的走向

2.1 脏数据是无标签分析的头号杀手

有监督学习里,一个脏样本可能会被模型当成噪声自动忽略掉,但无监督聚类对离群点非常敏感。比如你有一万条用户数据,里面有两条来自爬虫的极端值,KMeans 的聚类中心可能就被这两条硬生生拉偏,你最终得到的簇边界跟真实业务结构差了十万八千里。

我做一个电商用户分层项目时遇到过类似的事。特征里有一项是“历史订单金额”,绝大多数用户在几千元以内,但有几条数据是金额上百万的(后来排查是测试账号),标准化之后这几条一下子成了坐标系里的“孤岛”,KMeans 直接为它们单开了两个簇。原本应该被划到高价值人群的真实用户反而被挤到边缘。

所以预处理阶段至少要干以下几件事:

  • 去重:重复样本在聚类里相当于给某些点加权重,会扭曲密度估计。
  • 去异常:不是所有极端值都要删,但你要先识别出来,再决定是删除、截断还是单独处理。
  • 补缺失:缺失值不能直接丢,因为聚类算法大多不支持空值;也不能盲目填充,因为填充策略会引入主观偏差。
  • 检查量纲:不同特征单位相差太大时,必须做标准化或者归一化,否则欧氏距离会被大数值特征完全主宰。

注意:删除异常值时,务必把删掉的数据单独存一份。我之前因为图省事直接原地清理,结果事后想追踪异常来源,数据已经没了,只能重新跑一遍接口拉数,白白浪费时间。

2.2 标准化不是可有可无,而是必须

在无标签场景里,“距离”是一切的基础。而大部分距离度量对特征的尺度极其敏感。举个例子:一个特征“注册天数”取值范围是 0 到 3650,另一个特征“当月登录次数”取值范围是 0 到 30。如果你不标准化,算欧氏距离时,注册天数的差异会完全掩盖登录次数的差异,聚类结果基本上就是“按注册天数撕成几堆”,跟你的业务预期可能完全不同。

标准化的方式我有几个常用选择:

  • Z-score 标准化:公式是(x - mean) / std。适合数据近似正态分布的情况,也是实践中默认选项。
  • Min-Max 归一化:公式是(x - min) / (max - min)。适合你知道特征上下界、且没有极端离群值的情况。
  • RobustScaler:用中位数和四分位距来缩放。当你的数据里不可避免存在离群值时,这个比 Z-score 稳很多。

从实操角度,我不会推荐一种标准化打天下。如果你后面要做 PCA,Z-score 通常是默认;如果你要做 KMeans,数据分布比较偏态的话,RobustScaler 往往能避免被极端值带偏;如果特征本身是“次数”这种长尾分布,可以考虑先做对数变换再标准化,压缩一下动态范围。

2.3 特征筛选:宁缺毋滥不是一句空话

无标签场景下特征筛选比有监督还棘手。有监督你可以用特征重要性筛选,无监督没有目标列,很难客观判断哪些特征“有用”。

我的经验是分三步走:

先剔除信息量为零的特征。比如某一列全部是同一个值,或者某一列的缺失率超过 80%,这种特征留着只会稀释有效信号。

再剔除高度相关的特征。两个特征相关系数超过 0.9,它们在距离计算中的贡献会被重复放大。比如“消费总金额”和“平均单笔金额×消费笔数”基本上是同一件事,同时放进去等于给某个方向偷偷加了权重。

最后是根据业务直觉做取舍。这一步最重要。你希望聚类发现的“结构”是什么,就保留哪些维度。举个例子,如果你的目标是区分“重度用户”和“轻度用户”,那么“登录次数”“使用时长”这类强度特征是核心;“地域”和“设备型号”如果跟这个目标无关,留着反而会把人群切得更碎,增加解释难度。

我在实际操作中还有一个挺实用的技巧:先跑一次聚类,然后对每个簇看特征均值与全局均值的差异,差异不大的特征说明它对这个簇的区分度很低,可以考虑删掉重新跑一遍。这样循环两轮,特征维度通常会明显收缩,而且聚类结果会更干净。

3. 度量无标签数据的距离,藏在细节里的关键

3.1 距离度量不是默认欧氏距离就完了

很多人一说到距离,潜意识里就是欧氏距离。这个惯性在低维、连续、标准化过的数据里没问题,但一旦数据形态变化,它就可能给出荒谬的结论。

我举一个具体的反例。在文本聚类里,如果用 bag-of-words 生成向量,大部分维度是稀疏的 0/1 值,欧氏距离会把“共现的词多”误判成“含义接近”,但实际上文本里更合理的度量是余弦相似度——它只关心方向、不关心模长。之前我处理客服工单文本时,两种度量跑出来的聚类结构差异巨大,用余弦相似度能稳定分出“退款咨询”“物流投诉”“产品故障”这些主题,欧氏距离几乎是一团浆糊。

所以第一步是确认你的数据形态,再选度量方式。常见的对应关系大概是:

数据形态推荐度量原因
连续数值特征(标准化后)欧氏距离 / 曼哈顿距离几何直观,计算快
高维稀疏向量(文本、one-hot)余弦相似度不受向量长度影响
用户/物品偏好的评分矩阵皮尔逊相关系数能抓住相对偏好
类别型特征汉明距离 / 简单匹配系数直接比较取值是否一致

3.2 类别特征怎么塞进距离计算

无标签数据里经常混着类别型特征,比如“用户等级:普通/会员/超级会员”,“设备类型:iOS/Android”。这类特征不能直接当数值算距离,但你也不想轻易丢掉它们。常用的处理方案有两个:

第一种是 one-hot 编码,把每个类别拆成独立的 0/1 列。缺点很明显:类别多的时候维度爆炸,而且 one-hot 列之间的距离权重很难控制。

第二种是目标编码的变体,用量化替代类别。比如把“用户等级”映射成 0、1、2,但这里有个前提:类别之间确实存在等级递进关系。如果只是无序类别,强行有序化反而会制造虚假的远近关系。

我在经验里比较推荐先区分“有序类别”和“无序类别”。有序类别可以映射成数值,无序类别再用 one-hot。如果你害怕维度爆炸,还有一个折中方案:先单独对这些类别特征做一次相似度哈希,再把哈希特征拼到大特征集里。这个做法我在地域 + 用户属性混合的聚类项目里用过,效果还可以,缺点是解释性变差。

3.3 标准化和度量要配套起来看

这个点经常被忽略。有些人只标准化特征,却不考虑度量是否匹配;另一些人抓着一个余弦相似度不放手,却忘了余弦对数值特征的“长度偏好”并不敏感。

我自己定的配套规则是:

  • 用 Z-score 标准化 + 欧氏距离:默认组合,适合大多数数值型聚类。
  • 用 Min-Max 归一化 + 曼哈顿距离:如果特征之间有稀疏零值,曼哈顿距离对“0 和 小值”的区分更自然。
  • 用词频向量 + 余弦相似度:处理文本、稀疏计数特征时首选。

注意:高维数据里,欧氏距离会趋近于“所有特征都差不多远”,这是维度诅咒的一个表现。如果你觉得聚类结果里簇之间的距离都模模糊糊,先不要怀疑算法,很可能是维度太高了,下一步应该做降维而不是调参数。

4. 核心算法怎么选:从 KMeans 到密度聚类,边界在哪

4.1 KMeans:快,但不是所有数据都适合

KMeans 是绝大多数人的入门算法,也是我实际项目里最常用的“第一枪”。它的核心逻辑很直白:随机选 K 个中心点,迭代分配样本到最近中心,再更新中心位置。理论上它假设簇的形状是“凸的”“匀称的”,而且每个簇的方差不能差太多。

所以它适合的数据是:样本量大、特征维度不高、簇大概呈球形、数据分布比较均匀。比如用户分层、商品分群,这些场景下 KMeans 都能快速给出一版能用的基线结果。

遇到下面这些情况,KMeans 就要让位了:

  • 簇的形状是长条形、嵌套环形,KMeans 会把它们强行拧成几块“饼”;
  • 数据里带着大量离群点,KMeans 对离群点很敏感;
  • 你不想预设簇数,但 KMeans 必须给定 K。

4.2 DBSCAN:能发现任意形状,但参数要命

DBSCAN 是密度聚类的代表,它不关心簇的形状,只关心“密度相连”。核心参数就两个:eps(邻域半径)和min_samples(邻域内至少几个点才算核心点)。

这两个参数我调试过无数次,最大的心得是:eps的值必须结合业务语境来理解。它不是一个纯数学参数,它代表的是“在特征空间里,两步之间走多远还能算作邻居”。如果你的特征都标准化了,eps取 0.5 和取 1.5 的区别很大,前者会把簇切得很碎,后者可能把一片都连成一个簇。

我常用的调法是:先画出 k-距离图,把每个点到第 k 近的点的距离排序,找到曲线中的“拐点”作为eps。这个方法不算严谨,但能很快给你一个起点。然后再根据业务上对“簇粒度”的预期微调。min_samples一般取特征维度数量的两倍到三倍,太小会把噪声点也算成簇,太大会把真实的小众群体直接标成噪声。

DBSCAN 最大的优点是它可以自动标出“不属于任何簇”的点。这个特性在异常检测场景里价值极高。用户行为如果偏离所有已知群体,它不会强行塞进某个簇,而是直接暴露出来,这比 KMeans 硬性分堆合理得多。

4.3 层次聚类:小样本下的可视化之王

层次聚类不常用于大数据集,因为它的复杂度较高,好几万样本跑起来就会明显变慢。但它有个不可替代的优点:生成树状图之后,你可以直观地看到“合并过程”,能帮你在不同粒度下观察簇结构。

我在两类场景下会主动用层次聚类:一是样本量小(几千以内),二是我想探索数据到底应该分几类。它不像 KMeans 那样必须预先指定 K,你可以先看树状图,再决定在哪一层切几刀。

心得:层次聚类时,距离度量可以选 ward(离差平方和),它倾向于合并出大小更均衡的簇,效果在多数场景下比“最长距离”这种稳定。

4.4 降维不是必选项,但常常是救命项

很多人把 PCA、t-SNE、UMAP 当成“可视化专用工具”,其实它们在无标签数据分析里的价值远不止画图。当特征维度到了几十上百,几乎所有聚类算法的距离质量都会退化。降维的核心价值是:把你真正关心的结构压缩到少量维度里,再做聚类和解释。

PCA 是最稳定、最保守的降维方式,适合维度较高且特征间存在线性相关的数据。t-SNE 擅长把高维流形展开,但参数(perplexity)很敏感,且结果不能反推,只适合看局部结构。UMAP 是我目前体验下来在“速度 + 保持结构”之间平衡最好的,但同样有超参数需要调。

实际工作中我的做法是:先上 PCA 看方差累计解释度,如果前 20 个主成分能解释 80% 以上方差,就直接在主成分上聚类;如果数据里存在明显的非线性结构,再考虑 UMAP 投影到二维/三维后聚类。需要注意,UMAP 投影后再聚类,得到的结果会有一定随机性,至少要固定随机种子,最好多次运行取一致结论。

5. 一套能落地的实操流程:以用户行为聚类为例

5.1 案例背景与目标定义

为了把前面的方法串起来,我拿一个简化但真实感很强的案例来演示:某 App 运营团队给了你一张表,里面是 3 万条用户的行为汇总,特征包括注册天数、近 30 天登录天数、近 30 天总时长、近 30 天登录次数、近 30 天加购次数、近 30 天支付金额。没有用户标签,但运营想知道人群能不能分成几类,各自有什么特征。

第一步不要急着建模,先把业务目标翻译成技术口径。这里的目标是“用户分层”,隐含的期望是每一层用户的行为画像都能被运营看懂,并且层级之间有可操作的差异。所以后面的特征、算法、结果解释都要围绕“可解释”来做。

5.2 预处理与特征工程实操

拿到表之后依次执行:

  1. 检查缺失率。支付金额为空的行,如果占比不大(比如 5% 以内),用中位数填充;如果占比很高,说明支付金额这个特征对大批用户无效,需要单独建模,不能直接填充混淆结构。

  2. 检查重复项。通过用户 ID 去重,保留首次出现的记录。

  3. 处理异常值。对支付金额、登录次数这些长尾特征做分位数检查,超过 99.5% 分位的样本我们先看具体值,能确认是刷单或者测试账号就直接剔除,确认不了做截断处理。

  4. 特征变换。登录次数、总时长、支付金额都偏态严重,我先做 log1p 变换(取 log(1+x)),压一压长尾,再做 Z-score 标准化,让每个特征在同一尺度上被距离计算公平对待。

实操心得:log1p 变换对“含 0 的次数类特征”几乎是必备操作。直接 log(0) 是负无穷,但 log1p(0) = 0,可以保留“从未发生”的语义。

5.3 降维与聚类参数选择

特征只有 6 个,维度不高,这个规模下 PCA 不是必须的,但我还是先看了相关矩阵,发现“近 30 天登录天数”和“近 30 天登录次数”相关性接近 0.9,属于重复信息。我选择删掉登录次数,保留登录天数(业务上更好解释),再跑 PCA 看一眼前三个主成分的累计贡献。

聚类选择 KMeans 作为基线,但 K 需要定。我先试了手肘法:对 K=2 到 10 分别跑聚类,记录簇内误差平方和(SSE)。绘制曲线后能看到 K=4 附近下降速度明显放缓,轮廓系数在 K=4 时也达到一个局部高点,最终选定 K=4。

这里要强调:手肘法只是找“数学上的拐点”,业务上的 K 还要看可解释性。我很多次做出来数学最优的 K 值,在业务上却有一类簇的特征组合完全说不通,最终还是结合业务预期做取舍。

5.4 聚类结果与人群画像

跑完 KMeans 之后,我对每个簇做了特征均值和全局均值的对比,刻画的逻辑很简单:“这个簇在哪些特征上显著高/低”。

假设结果是:

  • 簇 A:注册天数长、近 30 天登录天数和时长都很高、支付金额高,占比 12%,可以解释为“忠实高价值用户”。
  • 簇 B:注册天数中等、登录次数较高、加购高但支付金额不高,占比 18%,这类是“活跃但犹豫”的用户,运营可以主推优惠券转化。
  • 簇 C:注册天数长、登录天数低、时长低、支付低,占比 30%,是明显“沉默流失”的人群。
  • 簇 D:注册天数短、各行为指标都偏低,占比 40%,属于“新用户阶段”,需要引导激活。

这四类人能直接映射到运营动作,说明聚类是有效的。如果某个簇的画像“什么都平均、不突出”,通常意味着这个聚类结果太粗糙,需要加特征或者调 K。

5.5 验证稳定性和可复现性

无监督聚类的结果很容易受随机种子影响。KMeans 初始中心是随机选的,我习惯固定随机种子跑多次,然后检查样本归属的稳定性。更严谨一点的做法是:把 3 万样本切两份,各跑一次聚类,然后用某些指标对比两个子集上簇中心的距离,越接近说明结构越稳。

稳定性验证是很多人跳过的一步,但它在真实项目里非常重要。决策层不会关心你的算法多花哨,只会问“这个分类结果是不是可信”。你如果能拿两组独立样本跑出来聚类质心分布一致,说服力会大很多。

6. 常见问题与排查技巧实录

6.1 K=3 还是 K=6?参数选择的纠结几乎人人都会遇到

K 值选择是聚类项目里被问得最多的问题,没有之一。我的经验是不要迷信任何一个指标,手肘法给你候选范围,轮廓系数帮你排除明显离谱的值,但最终要回到业务口径:“如果分 3 类,每一类你都能说出运营动作吗?如果分 6 类,有没有哪一类你根本不知道拿它怎么办?”后者往往是关键信号。

另外你要区分两个场景:如果是探索性分析(我就想看看数据大致什么样),K 小一点更稳妥;如果是生产级分群(后续运营策略要基于此落地),宁可 K 大一点去细分,也不要 K 太小把不同诉求的人群混在一个组里。前者错了可以重来,后者错了影响的是后续几个月的策略。

6.2 特征越加越多,聚类结果反而越乱

这是个典型的“维度诅咒”问题。特征加到一定程度后,样本间的距离差异会变得不明显,聚类结构会被稀释掉。我自己的经验阈值是:几十个特征的规模下,如果聚类结果没有清晰的簇间界限,先做特征筛选,而不是继续堆特征。

排查思路分三步:先看是否有高度相关特征,删同一组里的冗余项;再看每个特征取值的区分度,如果某一列在簇间均值几乎没有差异,直接删;最后重新跑聚类,看轮廓系数有没有提升。维度减半但轮廓系数上升的情况,我遇到太多次了。

6.3 DBSCAN 调参时全是噪声,一个簇都跑不出来

这是密度聚类新人最容易崩溃的场景。每个样本都是噪声点,通常说明eps设得太低,或者数据标准化后分布太分散。我的排查顺序是:

  1. 先看数据的 k-距离图,确定一个基本的eps区间。
  2. 把eps调大到能出现簇为止,再慢慢往下收缩。
  3. 如果怎么调都只能得到一个超级大簇加一堆噪声,大概率是数据里没有明显密度差异的 ASH 结构,这时换 KMeans 或者层次聚类可能更合适。

DBSCAN 对参数不敏感是对的,但对参数的选择却非常敏感。所以不是所有数据都值得用密度聚类,先确认你的数据里是否存在“密集区被稀疏区分开”的结构,再上 DBSCAN。

6.4 聚类结果无法解释怎么办

说明某一个簇的样本在每条特征上都和全局均值差不多,或者簇之间特征分布交错、没有清晰边界。这类情况我之前也苦恼过,后来总结了一个顺序排查清单:

  1. 回看预处理:标准化方式是否合适?离群点是否清理干净?缺失值填充是否引入了虚假模式?
  2. 回看特征工程:是不是选了一些和业务目标无关的“垃圾特征”?要不要删掉一部分再跑?
  3. 回看距离度量:连续特征和类别特征混在一起时,one-hot 列的权重是不是被放大了?
  4. 降低聚类数:簇太多时,某些簇天然就是“残余垃圾堆”,样本来自多个小众群体。减小 K 往往能改善。

如果这四步都试了还是解释不了,那有可能是当前数据本身就不存在明显的群组结构,硬聚类是挖不出东西的。这时候不要死磕算法,改用异常检测思路可能更契合数据本质。

6.5 标准化前后的聚类结果差一个世界

我早期踩过最冤的坑就是这个。同一个数据集,标准化前跑 KMeans,得到“金额高就是第一簇”;标准化后跑 KMeans,得到“高频低额用户独立成簇”。两者对应的运营策略完全不同。并不是后者一定对,但后者通常更合理,因为它不再被大数值特征绑架。

所以我建议大家在做任何聚类之前,都先建立一个习惯:跑两版,一版标准化,一版不标准化,对比特征画像。如果差异巨大,往往说明你的特征量纲在替你“做决定”,这不是你想要的。

7. 下一步:从聚类到可用的落地产物

无标签数据分析做到聚类结果之后,后面还有不少路要走,比如用标签传播或者其他方法把聚类结果转成监督学习的候选标签,把聚类的簇标签迁移到新数据上做实时预测,以及在每次更新数据后重新评估簇的漂移情况。这些内容我打算在系列后面的文章里展开讲。

现在如果只让你记住这几件事,我觉得就够了:

第一,拿到无标签数据不要直接套算法,先定义“你想要什么样的结构”。第二,预处理和特征工程的权重,大于算法调参的权重。第三,任何聚类结果都要经过“业务可解释性”的检验,否则它只是一个数学玩具。

我自己的习惯,是在项目文件夹里放一个prep.py,把所有清洗、标准化、特征变换的逻辑固化成脚本,每次数据更新直接重跑,保证不同批次之间的处理口径一致。这个小习惯帮我避免了无数次“这个版本和上版本数据可比吗”的尴尬。

希望这篇对你有用。下一篇我计划专门拆解无标签文本数据的处理流程,这也是评论区有不少人在问的方向,到时候见。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询