我最早接触集群划分这个需求,是在一个城市配电网规划项目里。当时要在一个接近饱和的城区网格里做分布式电源接入方案,最大的问题不是变压器容量,而是把哪些楼宇的负荷和光伏划到同一个“组”里。如果你只按电气联系去分,结果往往是跨楼、跨街区的,现场运维的人第一个不同意。而如果只按物理位置去分,电气上又会出现集群之间功率倒送、线损飙升的怪现象。后来我把“楼宇空间布局”作为一项硬约束放进集群划分模型里,才真正把这两条腿都站住了。
这篇博文就把这个方案的完整思路、数学模型和 Matlab 实现一条条拆开讲清楚。核心目标是:基于楼宇的空间坐标和电气耦合关系,构建一个综合相似度矩阵,用谱聚类方法把配电网节点划分为若干个结构合理、边界清晰、便于运维调度的集群。内容适合正在做主动配电网规划、分布式资源聚合、虚拟电厂内部优化分组的同学,也适合想用 Matlab 做谱聚类与空间约束优化分析的从业者。我会把每个环节为什么这么设计、代码里哪些细节要小心,全部交代清楚。
1. 为什么集群划分要“抬头看楼”——项目背景与核心需求拆解
1.1 传统集群划分的盲区:只看电气距离,不看物理边界
集群划分这个词,听起来像是纯电气领域的事。经典的划分思路也很成熟:根据节点导纳矩阵计算电气距离,然后做聚类。但你真正落到有楼宇分布的城区配电网里,就会发现一个问题——电气距离相似的节点,物理位置可能隔了好几条马路,甚至隔着一条河。划分出来的集群在系统拓扑图上是合理的,画到地图上却是一盘散沙。
这带来的直接后果有三个。第一,运维检修时要跨区域跑,不同集群的设备箱在空间上犬牙交错,抢修定位困难;第二,通信光缆的敷设路径和电气拓扑不一致,自动化终端的组网成本大幅增加;第三,如果后续要做楼宇群的需求响应或虚拟电厂调度,一个“组”里楼栋东一个西一个,实际执行时的通讯时延和控制难度都不可控。
所以,集群划分不能只盯着电气节点,必须把楼宇的空间布局作为一个先验信息拉进来。这是这个项目所有工作的起点,也是它和教材里经典聚类算法最大的区别。所谓“考虑楼宇空间布局”,本质上是让集群的边界既符合电气规律,又贴合真实的城市空间形态。
1.2 楼宇空间布局为什么是必须考虑的关键变量
楼宇空间布局在集群划分中的角色,不只是“距离”两个字那么简单。它背后映射的是三个工程现实。
其一,空间距离决定了线路走廊和损耗。低压馈线从配电变压器出来,顺着楼宇的方向敷设。2 栋楼隔开 200 米和 2 栋楼紧挨着,线路电阻差出的线损是完全不同量级的。集群如果让相距很远的楼宇凑在一起,就相当于默认接受一个高损耗的电气关系,这显然不合理。
其二,楼宇的物理边界通常是产权和管理边界。同一个小区、同一个商业综合体内部的配电房、储能设备、充电桩,往往属于同一个物业或同一个业主。集群划分如果不尊重这个空间边界,后续协调会非常困难。我甚至见过极端情况:一个集群把两栋物业对立的写字楼划到一起,结果需求响应指令根本下不去。
其三,分布式电源的出力特性与楼宇属性强相关。住宅楼的屋顶光伏、办公楼的空调负荷、综合体的充电桩,它们的时序曲线差异很大。空间布局接近的楼宇,在气象和用能行为上往往有强相关性。把这类节点放进同一个集群,本质上是在为后续的集群能量管理铺路。
这个项目要解决的,就是在做集群划分时把这三层空间语义都吸收进来,而不是单纯算一个坐标距离。
1.3 项目适用场景与目标读者定位
这套方案适用的边界条件,我用一句话概括:面向中低压配电网中楼宇级节点的集群划分。典型的场景包括:
- 10kV/380V 混合配电系统内,楼宇屋顶光伏大规模接入后的分区自治规划;
- 城市核心区的虚拟电厂分组,需要把商业楼宇、住宅小区按空间和电气双重属性聚合;
- 低压台区内的储能共享、柔性负荷聚合控制,事先要确定哪些楼宇适合组成一个可控单元。
目标读者里,既有正在做电网规划项目的工程师,也有做算法研究的同学。前者可以直接拿代码去适配自己的节点数据,后者可以用这个思路做改进。代码主体是纯 Matlab,工具包方面只需要基础的矩阵运算和图论函数,不依赖额外硬件,环境门槛很低。
2. 集群划分的核心原理与建模细节
2.1 目标函数怎么设计:兼顾电气耦合与空间邻近
先明确集群划分的输入。电力系统侧,节点对应的是楼宇的接入点。每个楼宇有它的电气属性——所在馈线、变压器、与其他节点的互阻抗关系;同时也有它的空间属性——经纬度坐标或平面坐标。集群划分的任务,就是把这 N 个节点分到 K 个集群里,每个集群内部的节点在电气和空间两个维度上都要尽可能“抱团”。
目标函数我拆成三部分来看:集群内部电气距离要小、集群内部空间距离要小、集群间的功率耦合要弱。前两个用加权相似度矩阵统一起来,第三个体现在聚类算法的后处理校验中。
综合相似度矩阵的构造是这个模型的核心。定义如下:
电气距离矩阵 E:由节点导纳矩阵 Y 计算得到,d_e(i,j) 表示节点 i 和 j 之间的电气距离。常用的做法是取互阻抗模值的归一化,或者用 Y 矩阵求逆后的等效阻抗值。
空间距离矩阵 L:由楼宇坐标计算得到,d_s(i,j) 表示空间欧氏距离。
综合相似度矩阵 S:对电气距离和空间距离分别做标准化后,按加权系数组合:
S(i,j) = a * (1 - d_e_norm(i,j)) + (1 - a) * (1 - d_s_norm(i,j))
其中 a 是电气相似度权重,取值范围 [0,1]。a 越接近 1,模型越偏向纯电气划分;a 越接近 0,越偏向纯空间划分。实际取值通常落在 0.4~0.6 之间,具体要靠敏感性分析来定。
注意这里的标准化非常关键。电气距离的量纲和空间距离完全不同,一个是阻抗概念,一个是米,不能直接加减。我采用的标准化方式是 min-max 归一到 [0,1] 区间,如果有明显的长尾分布,也可以先取对数再做归一化。这一步没做好的话,综合矩阵会直接被量纲大的那项主导,划分结果就废了。
2.2 楼宇归属唯一性约束与集群边界完整性
目标函数确定之后,还有三层约束要压上去:
第一层是硬性分配约束。每个楼宇必须且只能属于一个集群,不能出现一个楼宇同时在两个集群里的情况。谱聚类默认输出的是硬划分,天然满足这个约束,不需要额外处理。
第二层是集群容量均衡约束。每个集群的总接入容量(比如光伏装机容量或负荷峰值)不能超过设定上限。这一步要在聚类后校验,如果某个集群超容,就需要做局部调整。值得一提的是,这个约束不是目标函数的一部分,而是作为后校验和后修正来处理的。
第三层是空间连续约束。集群应该在空间形态上具有连续性,不允许出现“飞地”——即一个集群里有一个孤立楼宇和主体区域遥遥相隔。空间连续性的实现方式,我在代码里用了一个技巧:聚类完成后,检查每个节点与同集群其他节点的平均空间距离是否离群,如果有孤立点,将其重新分配到距离最近的邻接集群。这一条加完之后,划分结果地图上的观感立刻好了很多。
2.3 加权系数 a 的取值逻辑与敏感性分析
加权系数 a 是该模型里最值得花时间的参数。很多同学直接取 0.5,然后发现结果“好像两边都顾到了,但两边都不是最优”。我要说的是:a 不应该靠拍脑袋,应该做敏感性分析找拐点。
具体做法是:在 0.1 到 0.9 之间按步长 0.1 扫描,对每个 a 值跑一次集群划分,然后计算三个指标——集群内部平均电气距离、集群内部平均空间距离、以及集群间功率倒送量。画出曲线之后,你会看到电气距离随 a 增大单调下降,空间距离随 a 增大单调上升,而功率倒送量通常在某个区间会出现一个明显下降后的平台。
选那个“平台起点”对应的 a,而不是机械地取中间值。在我的模拟场景里,a=0.5 时功率倒送还算理想,但 a=0.55 之后空间距离恶化明显,所以最终选了 0.5。不同系统结构下这个值会漂移,必须自己跑一遍。
3. 算法选型与优化流程设计
3.1 为什么用谱聚类而不是 K-means
K-means 是大家最熟悉的聚类算法,但这个场景下它不是首选。原因有三个:
第一,K-means 对原始特征空间的分布形态有要求,擅长处理凸形簇,而配电网节点的电气耦合关系往往是非线性的,空间上也可能是狭长形状的街区,凸形簇假设不成立。
第二,K-means 直接作用于原始坐标,没有利用节点之间的相似度信息。而电气距离矩阵和图结构信息对 K-means 来说是无从下手的,硬用 K-means 就相当于退化成只按空间坐标划分。
第三,谱聚类基于图拉普拉斯矩阵的特征分解,天然适合处理相似度矩阵这种成对关系。它本质上是先做图嵌入降维,再用 K-means 对嵌入空间做最后的划分。两步结合,既保留了图结构信息,又在低维空间里让簇形态更适合 K-means。实测下来,针对本项目的算例,谱聚类的轮廓系数比直接用 K-means 高 20% 以上。
3.2 集群数量 K 的确定:肘部法则与谱间隙
聚类数 K 怎么定,直接影响规划方案的实用性。从工程经验来说,K 不是越大越好。集群越多,每个集群越小,控制粒度细,但管理和通信成本也高。我一般采用“谱间隙 + 肘部法则”交叉验证法。
谱间隙法:计算综合相似度矩阵对应的拉普拉斯矩阵的前 k 个特征值,观察相邻特征值之间的差。差距最大处对应的 k,就是自然簇数。
肘部法则:以 K 为横轴、簇内总距离为纵轴画曲线,找拐点。实际操作中不要机械看图,把两种方法的结果放在一起比,再结合工程上“集群规模不宜过大,但也不宜碎成几十个”的实际需求,最终定 K。
3.3 完整优化流程与迭代修正框架
整个规划策略的运行流程,我在代码里拆成了五个阶段:
- 数据准备:输入节点坐标、楼宇边界、导纳矩阵、容量信息。
- 相似度矩阵构建:计算电气距离矩阵、空间距离矩阵,合成综合相似度矩阵。
- 谱聚类求解:归一化拉普拉斯矩阵、计算特征向量、K-means 划分。
- 约束后处理:检查容量约束和空间连续性,对异常集群做局部调整。
- 指标评估输出:计算模块度、轮廓系数、容量均衡度等指标,输出集群划分结果和可视化图纸。
需要说明的是,第 4 步虽然叫“后处理”,但它不是可有可无的修补环节,而是保障划分结果可工程落地的关键。容量超限和空间飞地如果不在这一步解决,后续连锁反应很大,比如某集群控制指令下发时发现变压器过载,回头又要重新划分,周而复始。
4. Matlab 代码实现全过程解析
4.1 整体代码结构与函数划分
我习惯把代码按功能模块拆成独立的 m 文件,而不是全部堆在脚本里。这套方案的函数框架如下:
cluster_planning_main.m 主脚本,流程控制 build_similarity_matrix.m 构建综合相似度矩阵 spectral_partition.m 谱聚类划分 capacity_check.m 容量约束校验 spatial_refine.m 空间连续性修正 plot_cluster_result.m 结果可视化主脚本只负责调用函数、传递参数,真正干活的是各个子函数。这样做的直接好处是:后续想换电气距离的计算方法,或者把欧氏距离换成路网距离,只需要改对应函数,不用动整个流程。
4.2 输入数据结构设计与参数配置
输入数据我用结构体组织,清晰且不易出错。核心字段如下:
% 节点基础信息 node.id % 节点编号 node.x % 楼宇平面坐标 x node.y % 楼宇平面坐标 y node.capacity % 节点接入容量(kW) % 电气参数 Ybus % 节点导纳矩阵 % 划分参数 param.K % 集群数量 param.alpha % 电气相似度权重 a param.cap_max % 集群容量上限(kW)坐标数据如果初始是经纬度,需要先转成平面坐标。注意:直接用经纬度做欧氏距离在低纬度地区误差尚可,在中高纬度会明显失真。工程上稳妥的做法是采用局部平面坐标系投影,或者直接使用规划图上的相对坐标做归一化。
4.3 综合相似度矩阵的构建与标准化
这段代码是整个方案的心脏,也是容易被写错的地方。
function S = build_similarity_matrix(node, Ybus, alpha) n = length(node); % 1. 计算电气距离矩阵 Z = inv(full(Ybus)); % 阻抗矩阵 d_e = zeros(n); for i = 1:n for j = 1:n d_e(i,j) = abs(Z(i,i) - Z(i,j)) / 2 + abs(Z(j,j) - Z(i,j)) / 2; end end % 2. 计算空间距离矩阵 d_s = zeros(n); for i = 1:n for j = 1:n d_s(i,j) = sqrt((node(i).x - node(j).x)^2 + (node(i).y - node(j).y)^2); end end % 3. 分别归一化到 [0,1] d_e_norm = (d_e - min(d_e(:))) / (max(d_e(:)) - min(d_e(:)) + eps); d_s_norm = (d_s - min(d_s(:))) / (max(d_s(:)) - min(d_s(:)) + eps); % 4. 合成相似度矩阵 S = alpha * (1 - d_e_norm) + (1 - alpha) * (1 - d_s_norm); % 5. 对角线置零,保证聚类时不考虑自环 S(1:n+1:end) = 0; end电气距离用的这个公式需要多说一句。它表示两个节点之间的“电气接近度”,本质是基于戴维南等效阻抗的思路,把节点互阻抗和自阻抗的差值平均。当两个节点电气联系紧密时,互阻抗接近各自自阻抗,d_e 趋近于 0。这个定义比直接用互阻抗更符合工程直觉,因为互阻抗本身就带有很强的相角信息,直接使用会导致符号和尺度混乱。
矩阵对称性很容易被忽略。上面公式算出来的 d_e 天然是对称的,但如果你自己改写公式,一定要验证 S 是否对称。谱聚类基于无向图,相似度矩阵不对称会导致拉普拉斯矩阵非对称,特征分解结果会出错。
4.4 谱聚类核心实现
谱聚类的代码量不大,但每一步都有讲究:
function [cluster_idx, V] = spectral_partition(S, K) n = size(S, 1); % 1. 度矩阵 D = diag(sum(S, 2)); % 2. 归一化拉普拉斯矩阵 L = D^(-0.5) * (D - S) * D^(-0.5); % 3. 计算前 K 个最小特征值对应的特征向量 [V, ~] = eigs(L, K, 'smallestabs'); % 4. 按行归一化特征向量矩阵 V = V ./ sqrt(sum(V.^2, 2) + eps); % 5. 对归一化后的行向量做 K-means cluster_idx = kmeans(V, K, 'Replicates', 20, 'MaxIter', 500); end这里有个容易踩的大坑:eigs 求解归一化拉普拉斯矩阵的“最小”特征值,在 Matlab 里用的是 'smallestabs',而不是 'smallestreal'。因为矩阵可能是半正定的,'smallestreal' 有时会收敛到负的微小特征值,导致特征向量符号抖动。
还有一个更隐蔽的问题:特征向量符号翻转。L 的特征向量乘以 -1 之后还是特征向量,不同次运行 eigs 的结果符号可能不同。但 k-means 对行向量的符号是敏感的,符号一翻转,聚类结果就变了。解决办法就是前面提到的“按行归一化”,它能在很大程度上削弱符号翻转的影响。如果还是不稳定,可以固定随机种子,或者用 'Start' 参数指定多个初始中心点。
4.5 容量约束校验与空间连续性修正
聚类完成后,进入工程约束处理阶段。容量校验的代码逻辑很简单:
function [status, cluster_cap] = capacity_check(node, cluster_idx, param) K = max(cluster_idx); cluster_cap = zeros(K, 1); status = true; for k = 1:K members = find(cluster_idx == k); cluster_cap(k) = sum([node(members).capacity]); if cluster_cap(k) > param.cap_max status = false; end end end如果 status 为 false,有两种处理路径:一是直接调高 cap_max,适合规划初期没有严格限制的场景;二是执行节点重指派。重指派时要注意,不能单纯把超容集群里的节点随机挪到容量最小的集群,那样会破坏空间连续性。我习惯给每个节点算一个“转移代价”,由电气相似度和空间距离共同决定,优先转移代价最小的节点,同时保证转移后目标集群不超容。
空间连续性修正则是对每个集群做一次孤立点扫描。判断标准是:某节点到同集群其他节点的平均空间距离,是否大于全局平均的 2 倍。如果是,则把它合并到空间距离最近的其他集群。这一步在代码量上只占二十行左右,但对最终图纸的观感和运维可行性提升明显。
5. 算例运行与效果分析
5.1 测试场景与参数设置
我用来验证的场景是一个虚构的城市中低压混合配电网,共 24 个楼宇节点,分布在约 800 米乘 600 米的矩形区域内。节点包含三类:住宅楼 14 栋、商业楼 6 栋、混合楼宇 4 栋。屋顶光伏总装机约 1.6MW,接入点分散在各楼宇配电间。设集群数 K=5,集群容量上限取 500kW,加权系数 a=0.5。
这个规模不算大,但已经能把电气耦合和空间布局的矛盾体现得足够清楚。如果节点太多,反而会被边边角角的数据噪声干扰主线逻辑。
5.2 结果对比:考虑楼宇布局前后的差异
为了验证模型的有效性,我做了两组对比实验。
第一组:仅使用电气距离聚类,完全不考虑空间信息。划分结果在拓扑图上模块度很高,0.72,但把结果映射到实际坐标后,集群之间的空间交错严重。其中一个集群包含了两栋相距 460 米的楼宇,中间隔了另外两个集群的区域。
第二组:加入楼宇空间布局,综合相似度矩阵划分。模块度降为 0.65,但集群的空间连续性、容量均衡度都明显提升。更重要的是,集群间的功率倒送量从第一组的 210kW 降到了 95kW,降幅超过一半。
为什么模块度降了,实际效果反而好?因为传统模块度只衡量电气拓扑的社区结构,它天然偏爱电气强耦合的划分。而综合考虑空间布局后,我们主动放弃了部分电气“强抱团”,换取的是空间形态的规整和功率倒送的减少。工程意义上的最优,本来就是多目标的平衡,而不是单指标的最大化。
5.3 关键评价指标与结果呈现
最终输出的指标包括四类,便于后续做多方案横向比较:
| 指标 | 含义 | 理想趋势 |
|---|---|---|
| 模块度 Q | 电气拓扑群落结构强度 | 越高越好,但不过度追求 |
| 轮廓系数 | 聚类内聚度与分离度的综合 | 越高越好 |
| 集群容量均衡度 | 各集群容量方差/均值 | 越小越好 |
| 集群间功率倒送量 | 集群间交换功率总和 | 越小越好 |
在报告或论文里,这套指标可以组合使用,但作为从业者我要提醒一句:指标永远服务于规划需求。如果是做孤岛运行方案,模块度就很重要;如果只是做分区运维,空间连续性和容量均衡度才是硬指标。
可视化我用 plot 函数绘制坐标散点图,不同集群用不同颜色。同时在图上叠加集群凸包边界,方便直接评审。这一步在工程汇报时特别加分,评审专家不会去看矩阵,但一眼就能看出集群划得规不规范。
6. 常见问题与排查技巧实录
6.1 相似度矩阵对角线该为 0 还是该为 1
很多第一次写谱聚类代码的同学会在这里犹豫。原则上,相似度矩阵的对角线在谱聚类里应该置 0,因为图的自环在拉普拉斯矩阵里没有意义,反而会让度矩阵的计算出现偏差。
如果对角线不置 0,且值较大,度矩阵 D 的对角元素会被抬高,归一化拉普拉斯矩阵的特征结构会偏离真实图结构,聚类结果会偏向把每个节点单独归为自己所在的簇。我在初版代码里吃过这个亏,结果轮廓系数异常偏高,一查发现是自环在作怪。
6.2 空间坐标归一化的量纲陷阱
这个问题出现频率极高。电气距离的数值通常在 0.01 到 1 之间,而楼宇坐标是几百米的量级。如果不做归一化,综合相似度矩阵里空间距离项的数值分布会远超电气距离,a 无论取多少都无法平衡两者。
正确做法是分别对矩阵做归一化后再加权,这个在前面代码里已经体现。但要注意 min-max 归一化对离群值敏感。如果有一栋楼离其他楼特别远,它的距离值会把其他节点的归一化结果全部压到很小区间里,这时建议先去掉离群点,或者改用百分位归一化。
6.3 聚类结果每次运行都不一样
这个场景下,结果不稳定的来源通常是两个。第一个来源是 eigs 对特征向量的符号不确定,第二个是 k-means 的初始中心随机选取。前者我已经在前面提过,用行归一化解决;后者可以在主脚本里套一层循环,重复跑 30 次,取轮廓系数最高的一次作为最终结果。
这个方法不算优雅,但实用且稳定。专业点说叫“多起点搜索”,在聚类问题里是常用策略。计算量虽然增加到 30 倍,但 24 个节点的谱聚类几十毫秒就结束了,完全可接受。
6.4 节点规模变大时的性能瓶颈
如果系统规模从几十个节点增长到几百个节点,需要关注两个瓶颈。第一,inv(full(Ybus)) 在节点数过多时会非常慢且内存占用高,建议改用稀疏矩阵的 linsolve 或直接求 Z 的稀疏近似。第二,eigs 求特征向量在小规模矩阵上是秒级,但大规模时收敛慢,可以将 L 改为稀疏存储,并调高 eigs 的容差设置。
如果你手里的系统真的到了上千节点,我建议优先对相似度矩阵做稀疏化处理——只保留每个节点与电气耦合最强的若干个邻居之间的相似度,其余置 0。这样做能在几乎不影响划分质量的前提下,把矩阵规模从 N 乘 N 降到纯稀疏级别,运行时间能快一个数量级以上。
6.5 加权系数 a 的敏感性分析怎么做最省事
我前面建议扫描 a 值画曲线,这里再给一个批量处理的技巧。把 0.1 到 0.9 的扫描写成一个循环,每次运行只输出三个核心指标,最后画一个三线图叠加的汇总图。不用每次迭代都输出可视化图,否则输出文件会把工作目录塞满,而且肉眼比对标图非常费劲。
三线图的拐点通常很明显。如果你的系统结构比较均匀,可能没有明显拐点,这时就结合实际工程约束来定——比如“集群内楼宇之间的平均道路距离不超过 300 米”这种硬指标,反过来推算 a 的取值范围。
6.6 结果图纸中集群颜色太接近怎么办
Matlab 默认的色图在集群数超过 7 个时会变得难以区分。我一般不用默认的 hsv 或 jet,而是直接用 lines 色图,或者手动指定一组对比度高的颜色。在 plot_cluster_result.m 里加一行:
cmap = lines(max(cluster_idx));然后每个点根据聚类标签取对应颜色,同时把集群中心用黑色五角星标出来,中心点之间画连线,表示集群间的功率交互。图纸会比单纯彩色点丰富得多,评审时一眼能看出集群间关系的强弱。
7. 后续还可以扩展的方向
这个方案解决的是集群划分的主干问题,但实际应用里,很多延伸需求已经验证过可以接在这套框架上。
如果承接的是分布式光伏聚合项目,可以把楼宇的典型日照曲线加入相似度矩阵,让时间序列相关性成为划分依据之一。如果做的是电动汽车充电桩集群,则可以把充电需求的空间分布和变压器负载率作为约束条件加进来。如果后续要对接虚拟电厂调度,集群划分的结果可以直接作为优化调度的分区边界,重点是让每个集群的内部调节能力相对均衡,这也可以通过修改容量约束来实现。
我个人的体会是,集群划分这种问题,算法层面的难点并没有想象中高,真正的门槛在数据理解和工程约束的转化。你把楼宇的产权边界、运维习惯、通信路由这些东西翻译成约束条件的水平,直接决定了算法结果能不能落地上墙。这篇博文给出的方案就是一个还算完整的翻译样例,希望能帮正在做类似项目的同行少踩几个坑。最后再分享一个小技巧:无论代码写得多顺手,一定把参数配置和输入数据的说明写进脚本头部注释里。这活儿拖到项目后期再做,往往就没有心情做了。