机器学习练手(二):基于KMeans的股票分类
创始人
2024-11-06 01:06:49
0

总结:本文为和鲸python 机器学习原理与实践·闯关训练营资料整理而来,加入了自己的理解(by GPT4o)

原活动链接

在前一关我们学习了逻辑回归,学会如何训练模型、数据基础性分析、如何处理空值等操作,下面我们开始新的一关 KMeans

目录

      • KMeans
      • 基于 `KMeans` 的股票分类
        • 引入依赖
        • 加载数据
        • 确定分类个数
        • 查看分类结果
        • 总结
      • 闯关题
        • STEP1:请根据要求完成题目

KMeans

KMeans 是我们最常用的基于欧式距离的聚类算法,其认为两个目标的距离越近,相似度越大。

KMeans 算法的思想很简单,对于给定的样本集,按照样本之间的距离大小,将样本集划分为 K 个簇,其目的是让簇内的点尽量紧密的连在一起,而让簇间的距离尽量的大。

基于 KMeans 的股票分类

以往的量化投资中对于股票的划分分类,通常取决于行业、市值、地域等等指标划分,而这些分类指标并不能很好的区分公司的好坏。而现在可以通过每日的交易行情实时划分分类,通过计算当日前一个月的分类从而确定该股票分类,更好的降低投资风险,提供风险对冲。该数据集有 2024-05-06 的全部上市公司股票交易行情信息,其中包含日期、开盘价、收盘价、最高价、最低价、成交量、成交额等特征信息,另外该模型使用的数据为真实数据,可以在实际操作中使用。

股市有风险,入市需谨慎!

引入依赖
import pandas as pd import numpy as np import matplotlib.pyplot as plt  from sklearn.cluster import KMeans from sklearn.metrics import accuracy_score, silhouette_score 
加载数据
# 1. 加载数据  stock = pd.read_csv('./data/stocks-2.csv', index_col='Unnamed: 0') stock.head() 
symbolcodenametradepricechangechangepercentbuysellsettlementopenhighlowvolumeamountticktimeperpbmktcapnmcturnoverratio
0sz0000011平安银行10.890.100.92710.8810.8910.7910.9611.1110.84178410057195381749315:00:004.8400.5082.113304e+072.113264e+070.91938
1sz0000022万 科A7.460.050.6757.457.467.417.637.887.44524493788399692170315:00:007.2430.3558.900309e+067.248834e+065.39773
2sz0000044国华网安10.440.232.25310.4310.4410.219.9910.469.97988544010205984215:00:00-8.8217.4781.382050e+051.318448e+057.82769
3sz0000066深振业A3.870.000.0003.873.883.873.964.013.86231871869134876515:00:00-6.5090.7525.224481e+055.224451e+051.71759
4sz0000077*ST全新4.09-0.15-3.5384.094.104.244.264.264.0424405501002858915:00:0039.40311.2121.416972e+051.263597e+050.78995
stock.info() 
 Index: 5360 entries, 0 to 5359 Data columns (total 20 columns):  #   Column         Non-Null Count  Dtype   ---  ------         --------------  -----    0   symbol         5360 non-null   object   1   code           5360 non-null   int64    2   name           5360 non-null   object   3   trade          5360 non-null   float64  4   pricechange    5360 non-null   float64  5   changepercent  5360 non-null   float64  6   buy            5360 non-null   float64  7   sell           5360 non-null   float64  8   settlement     5360 non-null   float64  9   open           5360 non-null   float64  10  high           5360 non-null   float64  11  low            5360 non-null   float64  12  volume         5360 non-null   int64    13  amount         5360 non-null   int64    14  ticktime       5360 non-null   object   15  per            5360 non-null   float64  16  pb             5360 non-null   float64  17  mktcap         5360 non-null   float64  18  nmc            5360 non-null   float64  19  turnoverratio  5360 non-null   float64 dtypes: float64(14), int64(3), object(3) memory usage: 879.4+ KB 
# 2. 删除与分类数无关的特征列  new_stock = stock.drop(['symbol', 'code', 'name', 'ticktime'], axis=1) new_stock.head() 
tradepricechangechangepercentbuysellsettlementopenhighlowvolumeamountperpbmktcapnmcturnoverratio
010.890.100.92710.8810.8910.7910.9611.1110.8417841005719538174934.8400.5082.113304e+072.113264e+070.91938
17.460.050.6757.457.467.417.637.887.4452449378839969217037.2430.3558.900309e+067.248834e+065.39773
210.440.232.25310.4310.4410.219.9910.469.979885440102059842-8.8217.4781.382050e+051.318448e+057.82769
33.870.000.0003.873.883.873.964.013.862318718691348765-6.5090.7525.224481e+055.224451e+051.71759
44.09-0.15-3.5384.094.104.244.264.264.0424405501002858939.40311.2121.416972e+051.263597e+050.78995
确定分类个数
# 3. 利用肘部法则确定分类数  inertia = [] silhouette_scores = [] i_range = range(2, 11) for i in i_range:     kmeans = KMeans(n_clusters=i, random_state=10).fit(new_stock)     inertia.append(kmeans.inertia_)     silhouette_scores.append(silhouette_score(new_stock, kmeans.labels_))  inertia, silhouette_scores 
([4.1450149552461185e+20,   2.189263003520667e+20,   1.6730094412041477e+20,   9.618885942140525e+19,   6.943786093529641e+19,   5.561627387942571e+19,   4.014992267655058e+19,   3.2416675726264095e+19,   2.4597061039181627e+19],  [0.8944521948807374,   0.8260147612056037,   0.7907694574915884,   0.7490320699906337,   0.6649888612149094,   0.6339363805356698,   0.6338265053972817,   0.6300107391392652,   0.6195255140687659]) 

这段代码使用肘部法则和轮廓分数(silhouette score)来确定数据集的最佳分类数(簇数)。下面是对代码的详细解析:

导入必要的库

from sklearn.cluster import KMeans   from sklearn.metrics import silhouette_score   

初始化变量

inertia = []   silhouette_scores = []   i_range = range(2, 11)   
  • inertia:用来存储不同簇数下的簇内误差平方和(SSE)。
  • silhouette_scores:用来存储不同簇数下的轮廓分数。
  • i_range:簇数的范围,从2到10(包括2和10)。

迭代不同的簇数

for i in i_range:       kmeans = KMeans(n_clusters=i, random_state=10).fit(new_stock)       inertia.append(kmeans.inertia_)       silhouette_scores.append(silhouette_score(new_stock, kmeans.labels_))   
  • for i in i_range:遍历簇数范围,从2到10。
  • kmeans = KMeans(n_clusters=i, random_state=10).fit(new_stock):为每个簇数创建并训练一个KMeans模型。
    • n_clusters=i:设置当前簇数。
    • random_state=10:设置随机种子,以确保结果可复现。
    • fit(new_stock):对数据集 new_stock 进行聚类训练。
  • inertia.append(kmeans.inertia_):将当前簇数下的簇内误差平方和(SSE)添加到 inertia 列表中。
  • silhouette_scores.append(silhouette_score(new_stock, kmeans.labels_)):计算当前簇数下的轮廓分数,并添加到 silhouette_scores 列表中。

输出结果

inertia, silhouette_scores   
  • 这将输出不同簇数下的簇内误差平方和(SSE)和轮廓分数。

肘部法则
肘部法则(Elbow Method)通过绘制簇数与SSE的关系图来帮助确定最佳簇数。最佳簇数通常是在SSE曲线开始明显变平的位置,即肘部位置。

轮廓分数
轮廓分数(Silhouette Score)用于评估聚类的质量,其值在-1到1之间。值越高表示聚类效果越好。通过比较不同簇数下的轮廓分数,可以选择分数最高的簇数作为最佳簇数。

总结
这段代码的目的是通过计算不同簇数下的簇内误差平方和(SSE)和轮廓分数,帮助选择数据集的最佳分类数。结合肘部法则和轮廓分数可以更全面地评估聚类效果,从而确定最合适的簇数。

# 4. 确定分类数 plt.figure(figsize=(15,5))  plt.subplot(1, 2, 1) plt.plot(i_range, inertia, marker='o')  plt.subplot(1, 2, 2) plt.plot(i_range, silhouette_scores, marker='o')  plt.tight_layout() plt.show()  # 左图在 2 到 5 的时候,曲线下降速率明显下降。 # 右图在 2,3,4,5 时,轮廓系数比较高。 # 结合两图,选择 3 作为聚类数。 


外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

# 5. 分类  kmeans_final = KMeans(n_clusters=3, random_state=10).fit(new_stock)  labels = kmeans_final.labels_ new_stock['cluster'] = labels 
new_stock.head() 
tradepricechangechangepercentbuysellsettlementopenhighlowvolumeamountperpbmktcapnmcturnoverratiocluster
010.890.100.92710.8810.8910.7910.9611.1110.8417841005719538174934.8400.5082.113304e+072.113264e+070.919382
17.460.050.6757.457.467.417.637.887.4452449378839969217037.2430.3558.900309e+067.248834e+065.397731
210.440.232.25310.4310.4410.219.9910.469.979885440102059842-8.8217.4781.382050e+051.318448e+057.827690
33.870.000.0003.873.883.873.964.013.862318718691348765-6.5090.7525.224481e+055.224451e+051.717590
44.09-0.15-3.5384.094.104.244.264.264.0424405501002858939.40311.2121.416972e+051.263597e+050.789950
查看分类结果
# 6. 查看分类情况  new_stock['cluster'].value_counts() 
cluster 0    4998 2     332 1      30 Name: count, dtype: int64 
总结

KMeans 在确定分类个数计算时,无法使用 object 类型的数据,应当提前删除或对特征进行 one-hot 处理。

闯关题

STEP1:请根据要求完成题目

Q1. KMeans 中某个参数的含义是正确的?
A. n_clusters 分类个数
B. inertia_ 轮廓系数
C. silhouette_scores 曲线下降速率

Q2. 修改KMeans的划分集群个数为 4个,那么 002829 股票的分类是哪个?
A. 0
B. 1
C. 2
D. 3

kmeans_final2 = KMeans(n_clusters=4, random_state=10).fit(new_stock)  labels = kmeans_final2.labels_ stock['cluster'] = labels stock[stock['symbol'] == 'sz002829']['cluster'] 
1304    0 Name: cluster, dtype: int32 

Q3. 前300个股票数据集划分集群的最优个数是多少?
A. 1
B. 3
C. 5
D. 10

new_stock = new_stock[0:300]  inertia = [] silhouette_scores = [] i_range = range(2, 11) for i in i_range:     # 计算分类并保存指标     kmeans = KMeans(n_clusters=i, random_state=10).fit(new_stock)     inertia.append(kmeans.inertia_)     silhouette_scores.append(silhouette_score(new_stock, kmeans.labels_)) inertia, silhouette_scores 
([2.5308780913486823e+19,   1.3473879858220839e+19,   7.413489715471633e+18,   6.109726555261718e+18,   3.463054550988757e+18,   2.604280833562603e+18,   2.0732638975060705e+18,   1.6982759851707302e+18,   1.5100566906400458e+18],  [0.8998406279029784,   0.7527373456851054,   0.692685627034619,   0.6892926502877917,   0.6522651603158817,   0.6047949381607308,   0.5696962854320331,   0.5676513528559564,   0.5655907482205398]) 
plt.figure(figsize=(15,5))  plt.subplot(1, 2, 1) plt.plot(i_range, inertia, marker='o')  plt.subplot(1, 2, 2) plt.plot(i_range, silhouette_scores, marker='o')  plt.tight_layout() plt.show() 


外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#填入你的答案并运行,注意大小写 a1 = 'A'  # 如 a1= 'A' a2 = 'A'  # 如 a2= 'A' a3 = 'B'  # 如 a3= 'A' 

相关内容

热门资讯

揭秘几款"智星菠萝有... 揭秘几款"智星菠萝有挂!wepokerh5破解(其实真的是有挂)申智星菠萝有挂是一款一款智星菠萝有挂...
透视软件"德普之星私... 透视软件"德普之星私人局辅助器!wepoker插件下载(原来真的有挂);德普之星私人局辅助器是一款德...
避坑细节"wepok... 避坑细节"wepoker底牌透视!wepoker私人定制透视(其实真的是有挂);wepoker私人定...
必赢教程(wpk德州)外挂透明... 必赢教程(wpk德州)外挂透明挂辅助黑科技(德州wepower有外挂)的确是有挂的(有挂代打)1、德...
玩家必备攻略"wpk... 玩家必备攻略"wpk作弊是真的!wpk作弊(原来真的有挂);wpk作弊是真的是一种具有地方特色的,要...
五分钟私人房!菠萝德州app有... 五分钟私人房!菠萝德州app有挂,德扑之星专业代打,攻略教程(有挂长期)1、德扑之星专业代打ai辅助...
必赢方法(德州app)外挂透明... 必赢方法(德州app)外挂透明挂辅助器(德扑软件高端)果真真的有挂(有挂自建房)1、德州appai辅...
透明了解"wepok... 透明了解"wepoker新号好一点!拱趴大菠萝人水作弊(原来确实是有挂);拱趴大菠萝人水作弊是一种具...
八分钟安卓版!德扑之星操作,a... 八分钟安卓版!德扑之星操作,aa扑克能用模拟器,细节揭秘(有挂靠谱)aa扑克能用模拟器辅助器中分为三...
黑科技教程(咪咪扑克)外挂透明... 黑科技教程(咪咪扑克)外挂透明挂辅助黑科技(德扑之星可以操作)总是真的有挂(有挂线上)所有人都在同一...