Day 15:KMeans聚类与股票风格分类
Day 15KMeans聚类与股票风格分类 目录聚类分析概述KMeans算法原理K值选择方法肘部法则、轮廓系数初始化问题与KMeans数据预处理与标准化聚类的评估与解释第一部分聚类分析概述1.1 什么是聚类聚类Clustering是一种无监督学习方法将数据分成若干个组簇使得组内相似度高组间相似度低。与分类的区别对比项分类聚类学习类型监督学习无监督学习标签有标签无标签目标预测新样本类别发现数据内在结构评估准确率、混淆矩阵轮廓系数、内部指标1.2 量化交易中的应用场景应用场景说明股票风格分类根据基本面因子划分价值/成长/动量等风格市场状态识别识别牛/熊/震荡市风险分群识别相似风险特征的股票行业轮动聚类发现行业轮动规律异常检测识别偏离正常模式的异常行为1.3 常用聚类算法对比算法原理优点缺点KMeans基于质心快速、简单需要指定K对异常值敏感层次聚类树状结构不需要K可解释计算量大DBSCAN基于密度发现任意形状处理异常值参数敏感GMM概率分布软聚类可处理椭圆形状计算复杂第二部分KMeans算法原理2.1 算法核心思想目标将nnn个数据点分成KKK个簇使得簇内平方和Inertia最小。簇内平方和公式Inertia∑i1nminμj∈C∥xi−μj∥2∑j1K∑xi∈Cj∥xi−μj∥2 \text{Inertia} \sum_{i1}^n \min_{\mu_j \in C} \|x_i - \mu_j \|^2 \sum_{j1}^K \sum_{x_i \in C_j} \|x_i - \mu_j \|^2Inertiai1∑nμj∈Cmin∥xi−μj∥2j1∑Kxi∈Cj∑∥xi−μj∥2其中μj\mu_jμj是第jjj个簇的质心中心点。2.2 算法步骤输入数据集XXX簇数KKK最大迭代次数 max_iters输出簇分配结果随机初始化KKK个质心μ1,μ2,⋯ ,μK\mu_1, \mu_2, \cdots, \mu_Kμ1,μ2,⋯,μK重复直到收敛或达到最大迭代次数2.1 分配步骤将每个样本分配到最近的质心c(i)argminj∥xi−μj∥2c(i) \arg\min_j \|x_i - \mu_j\|^2c(i)argminj∥xi−μj∥22.2 更新步骤重新计算每个簇的质心μj1∣Cj∣∑i∈Cjxi\mu_j \cfrac{1}{|C_j|}\sum_{i \in C_j} x_iμj∣Cj∣1∑i∈Cjxi返回簇分配结果2.3 收敛性KMeans算法保证在有限步内收敛但可能收敛到局部最优解而非全局最优。影响因素初始质心选择数据分布K值选择2.4 距离度量KMeans通常使用欧氏距离d(x,y)∑i1p(xi−yi)2 d(x,y) \sqrt{\sum_{i1}^p(x_i-y_i)^2}d(x,y)i1∑p(xi−yi)2重要使用欧氏距离前必须对特征进行标准化否则量纲大的特征会主导距离计算。第三部分K值选择方法3.1 肘部法则Elbow Method原理随着 K 增加Inertia簇内平方和会下降。找到 Inertia 下降速度变缓的肘点。# 肘部法则示例inertias[]forkinrange(1,11):kmeansKMeans(n_clustersk,random_state42)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)样本到其他簇的最小平均距离簇间不相似度整体轮廓系数所有样本轮廓系数的平均值解读轮廓系数含义s0.5s 0.5s0.5聚类效果好0.2s0.50.2 s 0.50.2s0.5聚类效果一般s0.2s 0.2s0.2聚类效果差s≈0s \approx 0s≈0簇之间重叠s0s 0s0样本可能被错误分配fromsklearn.metricsimportsilhouette_score silhouette_scores[]forkinrange(2,11):kmeansKMeans(n_clustersk,random_state42)labelskmeans.fit_predict(X_scaled)scoresilhouette_score(X_scaled,labels)silhouette_scores.append(score)3.3 轮廓系数可视化fromsklearn.metricsimportsilhouette_samples# 绘制单个K值的轮廓图silhouette_valssilhouette_samples(X_scaled,labels)y_lower10foriinrange(k):cluster_valssilhouette_vals[labelsi]cluster_vals.sort()y_uppery_lowerlen(cluster_vals)plt.fill_betweenx(np.arange(y_lower,y_upper),0,cluster_vals)y_lowery_upper103.4 K值选择方法对比方法原理优点缺点肘部法则Inertia下降拐点简单直观肘点主观轮廓系数聚合/分离度客观数值计算量大Gap统计量与随机数据对比统计严谨计算复杂Calinski-Harabasz簇间/簇内方差比快速偏向凸簇第四部分初始化问题与KMeans4.1 随机初始化的陷阱问题不同的初始质心可能导致不同的聚类结果局部最优。# 运行多次结果可能不同kmeans1KMeans(n_clusters3,random_state0)kmeans2KMeans(n_clusters3,random_state42)# 可能得到不同的簇分配4.2 KMeans 初始化KMeans是一种智能初始化方法能有效提高收敛到全局最优的概率。算法步骤随机选择第一个质心对于每个未选点计算到最近已有质心的距离D(x)D(x)D(x)以概率D(x)2∑D(x)2\frac{D(x)^2}{\sum D(x)^2}∑D(x)2D(x)2选择下一个质心重复直到选满KKK个质心sklearn 中的实现fromsklearn.clusterimportKMeans# KMeans 是默认初始化方法kmeansKMeans(n_clusters5,initk-means,random_state42)# 也可以使用随机初始化kmeansKMeans(n_clusters5,initrandom,random_state42)4.3 多次运行取最优best_inertiafloat(inf)best_kmeansNoneforiinrange(10):kmeansKMeans(n_clusters5,random_statei)kmeans.fit(X_scaled)ifkmeans.inertia_best_inertia:best_inertiakmeans.inertia_ best_kmeanskmeans第五部分数据预处理与标准化5.1 为什么需要标准化问题不同特征的量纲差异会影响距离计算。示例市盈率PE5-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有异常值fromsklearn.preprocessingimportStandardScaler scalerStandardScaler()X_scaledscaler.fit_transform(X)5.3 处理异常值# 使用分位数去除极端值lowerdf[pe].quantile(0.01)upperdf[pe].quantile(0.99)dfdf[(df[pe]lower)(df[pe]upper)]第六部分聚类的评估与解释6.1 内部评估指标指标公式说明Inertia$\sumx - \mu轮廓系数(b−a)/max(a,b)(b-a)/\max(a,b)(b−a)/max(a,b)越接近1越好Davies-Bouldin簇间/簇内距离比越小越好Calinski-Harabasz簇间方差/簇内方差越大越好6.2 聚类结果的可视化PCA降维可视化fromsklearn.decompositionimportPCA pcaPCA(n_components2)X_pcapca.fit_transform(X_scaled)plt.scatter(X_pca[:,0],X_pca[:,1],clabels,cmapviridis)plt.xlabel(PC1)plt.ylabel(PC2)plt.title(聚类结果可视化PCA降维)6.3 簇特征分析# 计算每个簇的特征均值cluster_meanspd.DataFrame(X_scaled,columnsfeature_names)cluster_means[cluster]labels cluster_profilecluster_means.groupby(cluster).mean()# 找出每个簇的最显著特征forclusterincluster_profile.index:top_featurescluster_profile.loc[cluster].abs().sort_values(ascendingFalse).head(5)print(f簇{cluster}的特征:{top_features.index.tolist()})