Matlab|基于手肘法的kmeans聚类数的精确识别【K-means聚类】

   主要内容   

在电力系统调度研究过程中,由于全年涉及的风、光和负荷曲线较多,为了分析出典型场景,很多时候就用到聚类算法,而K-means聚类就是常用到聚类算法,但是对于K-means聚类算法,需要自行指定分类数,如果没有方法支撑、纯自行确定分类数的话,显得随意性较大,很难令人信服,本次介绍一个方法——手肘法。

方法介绍

手肘法,很形象的命名方式,通过该方法得到的误差曲线类似手肘曲线,就以手肘位置的数作为最佳分类数。下面结合曲线特点来具体分析:

在 K-means 算法聚类过程中,分类数 k 值越大,样本数据被划分得越为精细,各类内样本数据的聚合程度越高,对应得到的误差平方和 SSE 值越小。在 k~SSE折线关系图中,折线的变化情况分为两个阶段:第一阶段,当 k 值小于最优分类数时,随着k值的增长,SSE 值越来越小,变化的幅度比较大,反映到 k~SSE 折线关系图中就是相邻两点之间的连线较陡。第二阶段,当 k 值大于最优分类数后,伴随着 k 值的增长,SSE 值仍是越来越小,但变化的幅度却比较小,反映到折线关系图中就是相邻两点之间的连线较为平缓。因此,随着k值的增长,k值与SSE 值的折线图会呈“手肘形”,而“肘部”对应的k 值即为最优分类数。下图中,最优分类数为肘部部位对应的4 。

SSE为,其计算公式为:

其中,Ci是第i个类,p是Ci类中的所有样本点,mi是Ci类的质心。

程序亮点

  1. 程序内置风电功率和光伏发电功率的拉丁超立方抽样算法,形成了数据集。
  2. 明确了数据更改方式,增加了详尽的修改方法注释,方便上手改成自己的数据。
  3. 可以得到不同聚类场景的概率以及聚类中心数据,程序注释清楚,方便研究使用。
  4. 采用两种方式进行分析,第一种是全年365天实测风力数据,第二种是拉丁超立方抽样方式​。

  部分代码   

clc;clear all
% 基于LHS的可再生能源出力场景生成
ns=1000;
wind_predict = [339,287,449,471,512,530,527,641,634,519,401,634,589,530,512,505,206,85,81,80,83,110,353,523];%风电预测
pv_predict = [0,0,0,0,0,0,99,137,150,178,189,191,176,171,138,104,77,0,0,0,0,0,0,0 ];%光伏预测
wind_equ = 800 * ones(1,24);%风机装机容量
pv_equ = 240 * ones(1,24);%光伏装机容量
wind_sigma = 0.2 * wind_predict + 0.02* wind_equ ;
pv_sigma = 0.2 * pv_predict + 0.02 * pv_equ ; % 预测偏差的标准差
m1=ones(24,1000);%风生成
m2=ones(24,1000);%光生成
m=ones(24,1000);%可再生生成
wind_covariance_matrix = zeros (24,24);
pv_covariance_matrix = zeros (24,24);
for i= 1:24
    wind_covariance_matrix(i,i) = wind_sigma(i)^2;
    pv_covariance_matrix(i,i) = pv_sigma(i)^2;
end
​
for t=1:24
    m1(t,:)=lhsnorm(0,wind_sigma(t),ns);%拉丁超立方采样
    m2(t,:)=lhsnorm(0,pv_sigma(t),ns);
end
mpw=m1+wind_predict.';
mpv=m2+pv_predict.';
%手肘法确定k值
data = mpw';
%修改成自己的数据集的方式如下

  结果一览   

第一种:全年365天实测风力的效果图

第二种:拉丁超立方抽样​

下载链接

### K-means 聚类中使用手肘确定最佳簇数 在 K-means 聚类的应用中,确定合适的簇数量是一个关键问题。如果簇的数量设置不当,则可能导致聚类效果不佳或者无反映数据的真实结构。手肘是一种常用的用于确定最佳簇数的方。 #### 手肘原理 手肘的核心思想是通过计算不同簇数下的误差平方和(Sum of Squared Errors, SSE),并观察其变化趋势来决定最优的簇数。SSE 是指每个点与其所属簇中心之间的距离平方之和。随着簇数 \( k \) 的增加,SSE 会逐渐减小,但在某个特定的 \( k \) 之后,减少的速度显著变慢,形成类似于“手肘”的形状[^1]。 #### 实现过程 以下是实现手肘的具体流程: 1. **定义范围** 首先设定一个可能的簇数范围,通常是从 1 到最大预期簇数之间的一个区间,例如 `[1, 10]` 或者 `[1, 20]`。 2. **计算 SSE** 对于每一个候选的簇数 \( k \),运行 K-means,并记录对应的 SSE 。这一步可以通过多次迭代完成,确保结果稳定。 3. **绘制图表** 将不同的 \( k \) 和相应的 SSE 绘制成折线图。横轴表示簇数 \( k \),纵轴表示 SSE 。 4. **寻找拐点** 在图形上找到“手肘”位置,即 SSE 下降速度明显放缓的那个点。这个点所对应的簇数被认为是最佳簇数[^2]。 #### MATLAB 示例代码 以下是一段基于 MATLAB 编写的示例代码,展示如何利用手肘确定最佳簇数: ```matlab % 加载数据集 data = load('your_dataset.mat'); % 替换为实际的数据文件名 maxClusters = 10; % 设置最大的测试簇数 sseValues = zeros(1, maxClusters); for k = 1:maxClusters [~,~,silhouette] = kmeans(data, k); % 运行K-means sseValues(k) = sum(silhouette.^2); % 计算SSE end % 绘制手肘图 figure; plot(1:maxClusters, sseValues, 'bo--'); xlabel('Number of Clusters (k)'); ylabel('Sum of Squared Errors (SSE)'); title('Elbow Method for Optimal k'); grid on; % 寻找拐点 elbowPoint = find(diff(sseValues) < mean(diff(sseValues)), 1); disp(['Optimal number of clusters: ', num2str(elbowPoint)]); ``` 上述代码实现了从加载数据到绘图以及自动检测拐点的过程。其中 `diff(sseValues)` 表示相邻两个簇数间的 SSE 差异,当差异小于平均差时认为到达了“手肘”。 #### Python 示例代码 对于更广泛的编程环境,Python 提供了一个简洁的方式实现相同功能: ```python import numpy as np from sklearn.cluster import KMeans import matplotlib.pyplot as plt # 数据准备 X = np.array([[...], [...]]) # 替换为实际数据 # 测试多个簇数 sse_values = [] cluster_range = range(1, 11) for k in cluster_range: kmeans = KMeans(n_clusters=k, random_state=42) kmeans.fit(X) sse_values.append(kmeans.inertia_) # inertia_ 即为 SSE # 可视化 plt.plot(cluster_range, sse_values, marker='o') plt.title('Elbow Method For Optimal Number Of Clusters') plt.xlabel('Number of Clusters') plt.ylabel('SSE') plt.grid(True) plt.show() # 自动查找拐点 optimal_k = None differences = [sse_values[i+1] - sse_values[i] for i in range(len(sse_values)-1)] threshold = np.mean(differences) for idx, diff in enumerate(differences): if diff < threshold: optimal_k = idx + 1 break print(f'Optimal number of clusters: {optimal_k}') ``` 此代码片段展示了如何借助 scikit-learn 库快速构建模型,并结合 Matplotlib 展示结果。 --- #### 注意事项 尽管手肘简单直观,在某些情况下可能存在模糊的手肘区域,难以明确判断最佳簇数。此时可以考虑其他指标辅助决策,比如轮廓系数(Silhouette Coefficient)或间隙统计量(Gap Statistic)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值