给一班学生分组
如果老师不了解学生,最开始可能不会直接判断谁成绩好,而是先观察:谁擅长数学,谁表达能力强,谁动手能力强,谁需要更多基础训练。分组的目的不是贴标签,而是更有针对性地教学。
聚类在金融中也是这样。我们先不急着判断谁违约,而是先看客户结构:稳定经营型、季节波动型、快速成长型、低活跃型,之后再设计不同产品和风控策略。
暂时不知道真实风险结果
根据行为和特征形成群体
不同群体采用不同服务和监控方式
第四章
无监督学习、客户画像与隐含结构发现
本章围绕无监督学习的金融价值,介绍相似性度量、KMeans、KMeans++、肘部法则、轮廓系数、高斯混合模型 GMM 和 EM 算法。重点不是记住算法名称,而是理解“硬分群”和“软分群”在数字普惠金融客户画像中的不同含义。
聚类不依赖预先标注的违约、欺诈或流失标签,而是从数据内在结构中发现相似群体。
如果老师不了解学生,最开始可能不会直接判断谁成绩好,而是先观察:谁擅长数学,谁表达能力强,谁动手能力强,谁需要更多基础训练。分组的目的不是贴标签,而是更有针对性地教学。
聚类在金融中也是这样。我们先不急着判断谁违约,而是先看客户结构:稳定经营型、季节波动型、快速成长型、低活跃型,之后再设计不同产品和风控策略。
暂时不知道真实风险结果
根据行为和特征形成群体
不同群体采用不同服务和监控方式
聚类不是为了直接决定谁能贷款,而是帮助我们先看清客户结构。它是“画像工具”,不是“审批按钮”。
同样是小微商户,有人流水稳定但规模小,有人规模大但波动强。聚类可以把这两类客户分开,再设计不同授信策略。
聚类结果出来后,为什么还要用后续违约率或经营表现验证?
不同距离度量对应不同的“相似”定义。度量选择错误会直接导致聚类结果失真。
距离度量决定了模型眼中的“像不像”。选择距离前,先问业务上到底比较规模、结构,还是时间节奏。
两个农户收入总额不同,但一年中的收支季节性非常相似。欧式距离可能认为他们差异大,DTW 或结构比例可能更合适。
如果变量单位不同,例如收入金额和交易次数,为什么必须先标准化?
K-means 通过最小化簇内平方和寻找簇中心,是最经典的聚类方法。
K-means 找的是几个“代表性中心”。它适合快速分群,但不擅长处理形状复杂或异常值很多的数据。
银行可以用 K-means 把小微客户分成稳定经营型、快速成长型、季节波动型和低活跃型,再给出不同服务策略。
如果某个簇只有极少数客户,是新机会,还是异常噪声?如何判断?
聚类没有真实标签时,不能只凭视觉效果判断。需要结合内部指标、稳定性和业务可解释性。
选簇数不是数学题的唯一答案,而是数学指标和业务可解释性的折中。
模型可能建议分成 8 类,但客户经理只能清楚解释 4 类。实际落地时,4 类方案可能更适合培训和执行。
一个聚类方案统计指标很好,但业务人员完全解释不了,是否应该采用?
GMM 把数据视为多个高斯分布的混合,允许样本以概率形式属于多个簇,因此属于软聚类。
GMM 的“软分配”很适合金融客户,因为很多客户并不完全属于某一类,而是处在两类之间。
一个商户既有稳定社区零售特征,又开始出现线上销售增长。GMM 可以给出它属于两类的概率,而不是强行归入一类。
软分类结果如何帮助银行设计过渡型客户服务?
EM 用于含有隐变量的最大似然估计。聚类中的簇标签就是典型隐变量。
EM 可以理解为“先猜隐藏标签,再根据猜测更新参数”,如此反复。它适合标签看不见但结构存在的问题。
客户真实经营类型可能无法直接观察,但交易数据中隐含了类型差异。EM 就是在这些隐藏类型和模型参数之间交替更新。
如果初始猜测很差,EM 会不会得到错误结果?如何缓解?
KMeans 的核心非常朴素:先放几个中心点,让每个客户找离自己最近的中心;再把中心移动到本组客户的平均位置;不断重复,直到中心不再明显移动。
先用一个很小的样本理解算法。假设平台收集了 12 家小微商户的两个标准化特征:经营活跃度和资金流稳定性。数值越接近 1,表示该特征越强。真实业务中当然会有更多变量,例如月流水、交易频率、退款率、线上订单占比、历史逾期次数、行业季节性等;这里先用两个变量,是为了让几何图像足够清楚。
这不是为了训练一个真实模型,而是为了看懂 KMeans 每一步到底在做什么。
| 商户 | 经营活跃度 | 资金流稳定性 | 直观理解 |
|---|---|---|---|
| A01-A04 | 0.22-0.30 | 0.76-0.86 | 规模不大,但资金流稳定,类似社区稳定经营型商户。 |
| B01-B04 | 0.68-0.79 | 0.52-0.64 | 经营较活跃,稳定性中等,可能处于扩张或线上化阶段。 |
| C01-C04 | 0.62-0.83 | 0.18-0.30 | 活跃度不低,但资金流波动较大,需要更谨慎地评估还款节奏。 |
这个目标函数可以翻译成一句话:让每个客户尽量靠近自己所属簇的中心。其中 xᵢ 是第 i 个客户的特征向量,μₖ 是第 k 个簇的中心,Cₖ 是第 k 个簇中所有客户的集合。KMeans 不是直接最大化利润,也不是直接预测违约,而是在做一件更基础的事:把特征相近的客户放到一起。
import pandas as pd
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
df = pd.DataFrame({
"merchant": ["A01","A02","A03","A04","B01","B02","B03","B04","C01","C02","C03","C04"],
"activity": [0.22,0.25,0.30,0.28,0.68,0.74,0.79,0.70,0.62,0.70,0.78,0.83],
"cashflow_stability": [0.86,0.80,0.84,0.76,0.64,0.58,0.62,0.52,0.22,0.25,0.18,0.30],
})
X = df[["activity", "cashflow_stability"]]
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
kmeans = KMeans(n_clusters=3, init="k-means++", n_init="auto", random_state=42)
df["cluster"] = kmeans.fit_predict(X_scaled)
print(df[["merchant", "activity", "cashflow_stability", "cluster"]])
print("inertia =", round(kmeans.inertia_, 4))
merchant activity cashflow_stability cluster
0 A01 0.22 0.86 1
1 A02 0.25 0.80 1
2 A03 0.30 0.84 1
3 A04 0.28 0.76 1
4 B01 0.68 0.64 0
5 B02 0.74 0.58 0
6 B03 0.79 0.62 0
7 B04 0.70 0.52 0
8 C01 0.62 0.22 2
9 C02 0.70 0.25 2
10 C03 0.78 0.18 2
11 C04 0.83 0.30 2
inertia = 0.8997
注意:scikit-learn 的簇编号只是 0、1、2,并没有天然含义。不能写“0 类就是好客户、1 类就是坏客户”。正确做法是先看每一类的均值、违约率、收入增长、授信利用率、复贷率,再给它业务名称。例如:稳定经营型、成长扩张型、高波动经营型。
KMeans 像是在地图上找几个服务站,让每个客户去最近的服务站;然后服务站再搬到自己服务客户的平均位置。
如果某类商户资金流稳定但规模小,可以设计小额循环贷;如果另一类活跃但波动大,可以降低单笔额度、提高动态监测频率。
没有标准化变量时,金额类变量会压倒比例类变量,聚类结果可能只是按“规模大小”分组,而不是按真实经营模式分组。
KMeans 问的是“这个客户离哪个中心最近”;GMM 问的是“这个客户有多大概率来自每一种客户分布”。这就是硬分配与软分配的核心区别。
每个簇围绕一个中心展开,形状接近圆形或球形;客户只归属一个簇。
总体数据由多个高斯分布混合而成;每个分布有自己的均值、协方差和权重。
客户可能同时像“成长型”和“高波动型”,GMM 可以把这种不确定性保留下来。
这条公式的含义是:一个客户的特征不是来自单一规则,而可能来自多个客户群体分布的混合。πₖ 是第 k 个群体在总体中的占比,μₖ 是群体中心,Σₖ 则刻画该群体的形状和变量之间的相关性。KMeans 只关心中心距离,GMM 还关心这个群体是胖是瘦、是圆是椭圆、变量是否一起变化。
γᵢₖ 通常被翻译为 responsibility,即责任度。它回答的是:第 k 个高斯成分对解释第 i 个客户负多大责任。一个边界客户可能不是 100% 属于成长型,也不是 100% 属于高波动型,而是 64% 像成长型、34% 像高波动型、2% 像稳定型。这种信息对金融很重要,因为边界客户往往正是风险管理和产品设计最需要关注的人群。
import pandas as pd
from sklearn.mixture import GaussianMixture
from sklearn.preprocessing import StandardScaler
X = df[["activity", "cashflow_stability"]]
X_scaled = StandardScaler().fit_transform(X)
gmm = GaussianMixture(
n_components=3,
covariance_type="full",
random_state=42
)
gmm.fit(X_scaled)
df["gmm_cluster"] = gmm.predict(X_scaled)
proba = gmm.predict_proba(X_scaled)
print(df[["merchant", "gmm_cluster"]])
print(pd.DataFrame(proba, columns=["component_0", "component_1", "component_2"]).round(3))
merchant gmm_cluster
0 A01 1
1 A02 1
2 A03 1
3 A04 1
4 B01 0
5 B02 0
6 B03 0
7 B04 0
8 C01 2
9 C02 2
10 C03 2
11 C04 2
component_0 component_1 component_2
0 0.000 1.000 0.000
4 0.996 0.004 0.000
8 0.031 0.000 0.969
| 问题 | KMeans | GMM | 对金融业务的影响 |
|---|---|---|---|
| 客户归属 | 硬分配,只能属于一个簇。 | 软分配,可以报告属于各簇的概率。 | 边界客户更适合用 GMM 观察,因为它保留不确定性。 |
| 簇的形状 | 更适合圆形、球形、方差近似相同的簇。 | 可以表达椭圆形簇和不同协方差结构。 | 如果经营活跃度和现金流稳定性之间强相关,GMM 更灵活。 |
| 输出解释 | 中心、标签、簇内平方和。 | 均值、协方差、混合权重、责任度、对数似然。 | GMM 更容易解释“过渡型客户”和“混合型风险”。 |
| 风险 | 对异常值和初始中心敏感。 | 对分布假设、协方差估计和局部最优敏感。 | 两者都不能脱离业务验证;聚类结果必须看后续违约率和经营表现。 |
EM 的难点不在计算,而在理解“看不见的东西”。在聚类中,客户真实属于哪个潜在群体是看不见的,所以只能先估计归属概率,再用这些概率反过来更新模型。
放到数字普惠金融里,隐变量可以是“真实经营类型”“真实风险状态”或“真实资金需求模式”。这些东西不能直接从一张表中读出来,但它们会影响客户的流水、交易频率、还款行为和融资需求。EM 的作用就是在隐藏类型和可观察数据之间搭桥。
| 步骤 | 固定什么 | 计算什么 | 直观理解 |
|---|---|---|---|
| 初始化 | 没有固定值 | 给出初始 μ、Σ、π | 先粗略认为有几类客户,每类大概在哪里、占比多少。 |
| E 步 | 固定当前 μ、Σ、π | 计算每个客户的责任度 γ | 看每个客户更像哪一类,以及像到什么程度。 |
| M 步 | 固定当前责任度 γ | 更新 μ、Σ、π | 把客户按概率加权后,重新估计每类客户的中心、形状和占比。 |
| 收敛检查 | 比较新旧模型 | 看对数似然提升是否足够小 | 如果模型已经很难继续改进,就停止。 |
这两个更新式要用很简单的话解释:如果一个客户对第 k 类的责任度很高,它对第 k 类中心的影响就大;如果责任度很低,它对该类中心的影响就小。也就是说,GMM 的更新不是“把客户硬塞进某一类再求平均”,而是“按像不像这一类来加权求平均”。
边界客户 x = [经营活跃度 0.64, 资金流稳定性 0.48]
根据当前 GMM 参数计算:
稳定经营型责任度 ≈ 0.015
成长扩张型责任度 ≈ 0.641
高波动经营型责任度 ≈ 0.343
解释:
这个客户最像成长扩张型,但同时有明显高波动特征。
授信时不宜简单套用“成长型客户”的额度策略,最好加入现金流波动监测。
案例分析时,不要只说“可以聚类”。要说明分群后如何改变授信、定价、营销、复核或风险监控。
农户分群后,季节波动型客户可以采用还款周期更灵活的产品;稳定经营型客户可以降低审核频率;异常迁移客户进入预警名单。
同一个客户从一个簇迁移到另一个簇,可能意味着什么?