我最早接触集群划分这个需求是在一个城市配电网规划项目里。当时要在一个接近饱和的城区网格里做分布式电源接入方案最大的问题不是变压器容量而是把哪些楼宇的负荷和光伏划到同一个“组”里。如果你只按电气联系去分结果往往是跨楼、跨街区的现场运维的人第一个不同意。而如果只按物理位置去分电气上又会出现集群之间功率倒送、线损飙升的怪现象。后来我把“楼宇空间布局”作为一项硬约束放进集群划分模型里才真正把这两条腿都站住了。这篇博文就把这个方案的完整思路、数学模型和 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而不是机械地取中间值。在我的模拟场景里a0.5 时功率倒送还算理想但 a0.55 之后空间距离恶化明显所以最终选了 0.5。不同系统结构下这个值会漂移必须自己跑一遍。3. 算法选型与优化流程设计3.1 为什么用谱聚类而不是 K-meansK-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:n1: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接入点分散在各楼宇配电间。设集群数 K5集群容量上限取 500kW加权系数 a0.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. 后续还可以扩展的方向这个方案解决的是集群划分的主干问题但实际应用里很多延伸需求已经验证过可以接在这套框架上。如果承接的是分布式光伏聚合项目可以把楼宇的典型日照曲线加入相似度矩阵让时间序列相关性成为划分依据之一。如果做的是电动汽车充电桩集群则可以把充电需求的空间分布和变压器负载率作为约束条件加进来。如果后续要对接虚拟电厂调度集群划分的结果可以直接作为优化调度的分区边界重点是让每个集群的内部调节能力相对均衡这也可以通过修改容量约束来实现。我个人的体会是集群划分这种问题算法层面的难点并没有想象中高真正的门槛在数据理解和工程约束的转化。你把楼宇的产权边界、运维习惯、通信路由这些东西翻译成约束条件的水平直接决定了算法结果能不能落地上墙。这篇博文给出的方案就是一个还算完整的翻译样例希望能帮正在做类似项目的同行少踩几个坑。最后再分享一个小技巧无论代码写得多顺手一定把参数配置和输入数据的说明写进脚本头部注释里。这活儿拖到项目后期再做往往就没有心情做了。
阅读完成 · 觉得有帮助?