Day 15:KMeans聚类与股票风格分类

Day 15:KMeans聚类与股票风格分类

📋 目录

  1. 聚类分析概述
  2. KMeans算法原理
  3. K值选择方法(肘部法则、轮廓系数)
  4. 初始化问题与KMeans++
  5. 数据预处理与标准化
  6. 聚类的评估与解释

第一部分:聚类分析概述

1.1 什么是聚类?

聚类(Clustering) 是一种无监督学习 方法,将数据分成若干个组(簇),使得组内相似度高,组间相似度低

与分类的区别

对比项 分类 聚类
学习类型 监督学习 无监督学习
标签 有标签 无标签
目标 预测新样本类别 发现数据内在结构
评估 准确率、混淆矩阵 轮廓系数、内部指标

1.2 量化交易中的应用场景

应用场景 说明
股票风格分类 根据基本面因子划分价值/成长/动量等风格
市场状态识别 识别牛/熊/震荡市
风险分群 识别相似风险特征的股票
行业轮动 聚类发现行业轮动规律
异常检测 识别偏离正常模式的异常行为

1.3 常用聚类算法对比

算法 原理 优点 缺点
KMeans 基于质心 快速、简单 需要指定K,对异常值敏感
层次聚类 树状结构 不需要K,可解释 计算量大
DBSCAN 基于密度 发现任意形状,处理异常值 参数敏感
GMM 概率分布 软聚类,可处理椭圆形状 计算复杂

第二部分:KMeans算法原理

2.1 算法核心思想

目标 :将 nnn 个数据点分成 KKK 个簇,使得簇内平方和(Inertia)最小

簇内平方和公式
Inertia=∑i=1nmin⁡μj∈C∥xi−μj∥2=∑j=1K∑xi∈Cj∥xi−μj∥2 \text{Inertia} = \sum_{i=1}^n \min_{\mu_j \in C} \|x_i - \mu_j \|^2 = \sum_{j=1}^K \sum_{x_i \in C_j} \|x_i - \mu_j \|^2 Inertia=i=1∑nμj∈Cmin∥xi−μj∥2=j=1∑Kxi∈Cj∑∥xi−μj∥2

其中 μj\mu_jμj 是第 jjj 个簇的质心(中心点)。

2.2 算法步骤

输入 :数据集 XXX,簇数 KKK,最大迭代次数 max_iters
输出:簇分配结果

  1. 随机初始化 KKK 个质心 μ1,μ2,⋯ ,μK\mu_1, \mu_2, \cdots, \mu_Kμ1,μ2,⋯,μK

  2. 重复直到收敛或达到最大迭代次数:

    2.1 分配步骤:将每个样本分配到最近的质心
    c(i)=arg⁡min⁡j∥xi−μj∥2c(i) = \arg\min_j \|x_i - \mu_j\|^2c(i)=argminj∥xi−μj∥2

    2.2 更新步骤:重新计算每个簇的质心
    μj=1∣Cj∣∑i∈Cjxi\mu_j = \cfrac{1}{|C_j|}\sum_{i \in C_j} x_iμj=∣Cj∣1∑i∈Cjxi

  3. 返回簇分配结果

2.3 收敛性

KMeans算法保证在有限步内收敛,但可能收敛到局部最优解而非全局最优。

影响因素

  • 初始质心选择
  • 数据分布
  • K值选择

2.4 距离度量

KMeans通常使用欧氏距离
d(x,y)=∑i=1p(xi−yi)2 d(x,y) = \sqrt{\sum_{i=1}^p(x_i-y_i)^2} d(x,y)=i=1∑p(xi−yi)2
重要 :使用欧氏距离前必须对特征进行标准化,否则量纲大的特征会主导距离计算。


第三部分:K值选择方法

3.1 肘部法则(Elbow Method)

原理:随着 K 增加,Inertia(簇内平方和)会下降。找到 Inertia 下降速度变缓的"肘点"。

python 复制代码
# 肘部法则示例
inertias = []
for k in range(1, 11):
    kmeans = KMeans(n_clusters=k, random_state=42)
    kmeans.fit(X_scaled)
    inertias.append(kmeans.inertia_)

plt.plot(range(1, 11), inertias, 'bo-')
plt.xlabel('K值')
plt.ylabel('Inertia')
plt.title('肘部法则选择K值')

特点

  • 简单直观
  • 肘点有时不明显(需要主观判断)

3.2 轮廓系数(Silhouette Coefficient)

原理 :结合簇内凝聚度和簇间分离度,取值范围 [−1,1][-1, 1][−1,1]。

单个样本的轮廓系数
s(i)=b(i)−a(i)max⁡(a(i),b(i)) s(i) = \cfrac{b(i) - a(i)}{\max(a(i), b(i))} s(i)=max(a(i),b(i))b(i)−a(i)

其中:

  • a(i)a(i)a(i):样本到同簇其他样本的平均距离(簇内不相似度)
  • b(i)b(i)b(i):样本到其他簇的最小平均距离(簇间不相似度)

整体轮廓系数:所有样本轮廓系数的平均值

解读

轮廓系数 含义
s>0.5s > 0.5s>0.5 聚类效果好
0.2<s<0.50.2 < s < 0.50.2<s<0.5 聚类效果一般
s<0.2s < 0.2s<0.2 聚类效果差
s≈0s \approx 0s≈0 簇之间重叠
s<0s < 0s<0 样本可能被错误分配
python 复制代码
from sklearn.metrics import silhouette_score

silhouette_scores = []
for k in range(2, 11):
    kmeans = KMeans(n_clusters=k, random_state=42)
    labels = kmeans.fit_predict(X_scaled)
    score = silhouette_score(X_scaled, labels)
    silhouette_scores.append(score)

3.3 轮廓系数可视化

python 复制代码
from sklearn.metrics import silhouette_samples

# 绘制单个K值的轮廓图
silhouette_vals = silhouette_samples(X_scaled, labels)
y_lower = 10
for i in range(k):
    cluster_vals = silhouette_vals[labels == i]
    cluster_vals.sort()
    y_upper = y_lower + len(cluster_vals)
    plt.fill_betweenx(np.arange(y_lower, y_upper), 0, cluster_vals)
    y_lower = y_upper + 10

3.4 K值选择方法对比

方法 原理 优点 缺点
肘部法则 Inertia下降拐点 简单直观 肘点主观
轮廓系数 聚合/分离度 客观数值 计算量大
Gap统计量 与随机数据对比 统计严谨 计算复杂
Calinski-Harabasz 簇间/簇内方差比 快速 偏向凸簇

第四部分:初始化问题与KMeans++

4.1 随机初始化的陷阱

问题:不同的初始质心可能导致不同的聚类结果(局部最优)。

python 复制代码
# 运行多次,结果可能不同
kmeans1 = KMeans(n_clusters=3, random_state=0)
kmeans2 = KMeans(n_clusters=3, random_state=42)
# 可能得到不同的簇分配

4.2 KMeans++ 初始化

KMeans++ 是一种智能初始化方法,能有效提高收敛到全局最优的概率。

算法步骤

  1. 随机选择第一个质心
  2. 对于每个未选点,计算到最近已有质心的距离 D(x)D(x)D(x)
  3. 以概率 D(x)2∑D(x)2\frac{D(x)^2}{\sum D(x)^2}∑D(x)2D(x)2 选择下一个质心
  4. 重复直到选满 KKK 个质心

sklearn 中的实现

python 复制代码
from sklearn.cluster import KMeans

# KMeans++ 是默认初始化方法
kmeans = KMeans(n_clusters=5, init='k-means++', random_state=42)

# 也可以使用随机初始化
kmeans = KMeans(n_clusters=5, init='random', random_state=42)

4.3 多次运行取最优

python 复制代码
best_inertia = float('inf')
best_kmeans = None

for i in range(10):
    kmeans = KMeans(n_clusters=5, random_state=i)
    kmeans.fit(X_scaled)
    if kmeans.inertia_ < best_inertia:
        best_inertia = kmeans.inertia_
        best_kmeans = kmeans

第五部分:数据预处理与标准化

5.1 为什么需要标准化?

问题:不同特征的量纲差异会影响距离计算。

示例

  • 市盈率(PE):5-50
  • 换手率:1%-20%
  • ROE:-30% - 30%

若不标准化,PE 的数值会主导距离计算。

5.2 标准化方法

方法 公式 适用场景
StandardScaler (x−μ)/σ(x - \mu)/\sigma(x−μ)/σ 特征分布近似正态
MinMaxScaler (x−min⁡)/(max⁡−min⁡)(x - \min)/(\max - \min)(x−min)/(max−min) 需要落在[0,1]
RobustScaler (x−median)/IQR(x - \text{median})/IQR(x−median)/IQR 有异常值
python 复制代码
from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

5.3 处理异常值

python 复制代码
# 使用分位数去除极端值
lower = df['pe'].quantile(0.01)
upper = df['pe'].quantile(0.99)
df = df[(df['pe'] > lower) & (df['pe'] < upper)]

第六部分:聚类的评估与解释

6.1 内部评估指标

指标 公式 说明
Inertia $\sum x - \mu
轮廓系数 (b−a)/max⁡(a,b)(b-a)/\max(a,b)(b−a)/max(a,b) 越接近1越好
Davies-Bouldin 簇间/簇内距离比 越小越好
Calinski-Harabasz 簇间方差/簇内方差 越大越好

6.2 聚类结果的可视化

PCA降维可视化

python 复制代码
from sklearn.decomposition import PCA

pca = PCA(n_components=2)
X_pca = pca.fit_transform(X_scaled)

plt.scatter(X_pca[:, 0], X_pca[:, 1], c=labels, cmap='viridis')
plt.xlabel('PC1')
plt.ylabel('PC2')
plt.title('聚类结果可视化(PCA降维)')

6.3 簇特征分析

python 复制代码
# 计算每个簇的特征均值
cluster_means = pd.DataFrame(X_scaled, columns=feature_names)
cluster_means['cluster'] = labels
cluster_profile = cluster_means.groupby('cluster').mean()

# 找出每个簇的最显著特征
for cluster in cluster_profile.index:
    top_features = cluster_profile.loc[cluster].abs().sort_values(ascending=False).head(5)
    print(f"簇 {cluster} 的特征: {top_features.index.tolist()}")
相关推荐
Resistance丶未来2 小时前
DeepSeek-V4 新手快速上手指南
数据结构·python·gpt·算法·机器学习·claude·claude 4.6
落羽的落羽2 小时前
【Linux系统】总结线程:死锁问题、实现带有日志模块的线程池类
linux·运维·服务器·c++·人工智能·机器学习
lwf00616411 小时前
导数学习日记
学习·算法·机器学习
code_li17 小时前
自动驾驶的调度开源软件
人工智能·机器学习·自动驾驶
wayz1117 小时前
Day 13 编程实战:朴素贝叶斯与极端涨跌预警
人工智能·算法·机器学习
我是发哥哈19 小时前
主流AI视频生成方案商用化能力横向评测
大数据·人工智能·学习·机器学习·chatgpt·音视频
攻防_SRC20 小时前
面向分组密码差分故障分析的属性推导与验证平台
人工智能·算法·机器学习
小鱼~~20 小时前
最小二乘&均方误差MSE&平均绝对误差MAE
python·算法·机器学习
MediaTea20 小时前
AI 术语通俗词典:召回率(分类)
人工智能·算法·机器学习·分类·数据挖掘