做电力负荷侧数据分析的人,应该都绕不过居民用电行为分析这个命题。说白了,就是把成千上万条日负荷曲线按照用电模式归类,让你能一眼看出哪类用户是白天上班晚上才用电,哪类用户从早到晚空调没停过,哪类用户家里装了分布式光伏在自发自用。这个项目标题里的组合——粒子群算法优化FCM聚类,就是把“怎么分得更准”这件事做到位。它面向的典型场景是电网公司的用户画像、需求侧响应、分时电价套餐设计,适合电力方向研究生、数据分析岗的工程师,以及做机器学习课设需要“算法改进+Matlab实现”的学生参考。我用Matlab把整套流程完整跑通过,下面把思路、原理、代码细节和踩坑记录一次讲清楚。
1. 这个项目到底在做什么:PSO优化FCM的完整思路拆解
1.1 为什么居民用电分析普遍选FCM而不是K-means
先说一个很多初学者问我的问题:聚类用K-means不就行了,为什么要上FCM?核心原因是负荷数据的边界本来就是模糊的。K-means是硬聚类,每个样本只能归属一个类;但一个家庭用户的用电行为往往同时具备多种特征,比如周一到周五是标准上班族,周末又成了夜猫子,还有一部分家庭规律性极差,全天负荷都平平的,你很难说它属于哪一类。
FCM(模糊C均值聚类)不一样,它用隶属度描述“某个样本属于每一类的程度”。一个用户的负荷曲线可以以0.6的隶属度属于“上班族”类、0.3属于“夜猫子”类、0.1属于其他类,这更贴近真实世界的用电模式。我在实际处理台区数据时也验证过这点:用K-means强行分出来的几类曲线,类内方差总是偏大,因为总有一些“不伦不类”的曲线被硬塞进某一类,而FCM给出的隶属度分布能把这些模糊样本单独识别出来。
1.2 FCM的两大痛点:初值敏感和局部最优
FCM好归好,但用起来有两个很头疼的问题。首先是初值敏感:它需要预先给定初始聚类中心,初始位置不同,迭代收敛的结果可能完全不同。我最早做实验时试过随机初始化跑十次,能跑出三种明显不同的分类结果。其次是目标函数非凸,FCM本质上是在最小化一个带约束的目标函数,这个函数存在大量局部极小点,迭代过程很容易陷进去出不来。
这两个问题叠加,导致FCM在实际负荷数据上稳定性很差。你可以理解为:你想找一个山谷的最低点,但随机出发的起点不同,可能停在不同的小坑里,永远走不到真正最低的地方。传统做法是多跑几次取最优,或者用K-means的结果做初始化,但多跑几次只能碰运气,K-means初始化本身也有随机性,治标不治本。
1.3 粒子群算法在这里扮演什么角色
粒子群算法(PSO)是一种无梯度的全局寻优算法,它模拟鸟群觅食过程:一群“粒子”在搜索空间里飞来飞去,每个粒子记住自己找到过的最好位置,同时参考整个群体找到过的最好位置,不断调整自己的速度和方向。
用在FCM上,核心思路非常直接:把FCM的聚类中心编码成粒子的位置,一个粒子就是一组聚类中心的候选解,然后用FCM的目标函数值作为粒子的适应度值,通过PSO迭代找到一组让目标函数最小的聚类中心。找到之后,再用这组优化后的中心去初始化FCM,做最终聚类。
为了让你更直观地理解选型逻辑,我整理了一张常用方案对比表:
| 方案 | 全局搜索能力 | 实现复杂度 | 稳定性 | 适用场景 |
|---|---|---|---|---|
| K-means | 差 | 低 | 差 | 类间边界清晰的简单数据 |
| 原始FCM | 差 | 低 | 差 | 有模糊归属需求,但数据量小、对初值不敏感时 |
| K-means++初始化FCM | 中 | 中 | 中 | 想省事、对精度要求不高的场景 |
| 遗传算法优化FCM(GA-FCM) | 强 | 较高 | 中 | 追求全局最优,但可接受较长运行时间 |
| 粒子群优化FCM(PSO-FCM) | 较强 | 中 | 较好 | 负荷曲线这类中等规模数据,兼顾效果和效率 |
从我的实际体验看,遗传算法虽然全局搜索理论更强,但参数多、收敛慢,在Matlab里调试起来费劲;PSO参数少、代码量小、收敛快,配合负荷数据这种特征维度不高(24点或96点日负荷曲线)的场景绰绰有余。这也是本项目选PSO而不是其他群智能算法的原因。
2. 核心原理通俗版:不懂FCM和PSO也能跑通代码
2.1 FCM的数学原理,我用生活例子给你讲透
FCM的目标函数长这样:
J = ∑ᵢ₌₁ᶜ ∑ⱼ₌₁ⁿ uᵢⱼᵐ · ‖xⱼ - vᵢ‖²
看起来吓人,拆开就很简单。c是聚类数,n是样本数,xⱼ是第j条负荷曲线,vᵢ是第i个聚类中心,uᵢⱼ表示第j条曲线对第i类的隶属度,m是模糊指数(一般取2),‖xⱼ - vᵢ‖²是两个向量之间的欧氏距离平方。说人话就是:让每个样本到各类中心的加权距离总和尽量小,权重就是隶属度的m次方。
约束条件是每条曲线对全部类的隶属度之和等于1,也就是“一个用户确实属于某个分类体系,只是程度分散在各处”。FCM通过反复迭代更新隶属度矩阵U和聚类中心V,直到目标函数不再明显下降。迭代公式记住两个核心就行:
隶属度更新:uᵢⱼ = 1 / (∑ₖ₌₁ᶜ (dᵢⱼ/dₖⱼ)^(2/(m-1)))
聚类中心更新:vᵢ = (∑ⱼ₌₁ⁿ uᵢⱼᵐ · xⱼ) / (∑ⱼ₌₁ⁿ uᵢⱼᵐ)
我在调试时经常用一句话帮同学理解:FCM就是在“根据距离算归属度”和“根据归属度算中心”这两步之间反复横跳,跳到结果不再变化为止。
2.2 PSO算法的三步核心:位置、速度、迭代更新
PSO里每个粒子有两个属性:位置和速度。位置是解空间里的一个点,速度决定了它下一步朝哪儿飞、飞多远。每次迭代时,粒子综合三方面信息更新速度:自己原来的速度(惯性)、自己历史最优位置pbest(个体认知)、群体历史最优位置gbest(社会认知)。
速度更新公式是:
v = w·v + c₁·r₁·(pbest - x) + c₂·r₂·(gbest - x)
位置更新公式是:
x = x + v
参数含义:w是惯性权重,控制粒子保持原来飞行趋势的程度;c₁和c₂是加速因子,分别控制“向自己学”和“向群体学”的强度;r₁和r₂是[0,1]之间的随机数,给搜索过程增加随机性。
我用找球场的例子给你类比:你在一个看不见全貌的大山里找最低点,你手里有自己的GPS记录(pbest),还有一张群友共享的“已知最低点”消息(gbest)。你每次迈步的方向,既会参考自己以前踩到过的最低点,也会参考队友发现的位置,同时保留一点原来的前进趋势。这样一群人就比一个人瞎摸效率高很多。
2.3 两种算法怎么融合,粒子到底编码的是什么
融合方式有两种常见思路。第一种是只优化初始聚类中心:先跑PSO,搜出一组较优的中心,再用这组中心初始化FCM。第二种是每个迭代步骤都用PSO来更新隶属度和中心,相当于把整个FCM的迭代过程替换掉。实际项目选第一种就够,简单、可靠、代码跑得快。
粒子的编码方式是关键。假设聚类数是c,每个负荷样本的特征维度是d(比如96点日负荷曲线,d=96),那么一个粒子位置就是c×d维的向量,展开后就是c个聚类中心依次拼在一起。要是聚成4类,特征96维,每个粒子就是4×96=384维的向量。
适应度函数的选取也很重要。最直观的做法是直接取FCM的目标函数J作为适应度,因为我们的最终目的就是最小化J。但J天然对聚类数c有偏好,c越多J越小,所以如果要用J做适应度,必须固定聚类数再对比。另外一个常用指标是XB系数(Xie-Beni指标),它同时考虑类内紧凑度和类间分离度,值越小聚类效果越好。我的经验是:课题研究阶段用J做适应度,代码简单;论文要评价聚类质量,再单独算SC、DB、XB这些指标。
3. 实操步骤和Matlab代码实现细节
3.1 数据准备与预处理:这一步直接决定聚类结果的上限
很多同学一上来就写算法,结果聚类结果一团糟,以为是代码问题,其实大部分时候是数据预处理出了问题。居民用电数据首先要做几件事:
第一是统一采样频率。智能电表有15分钟、30分钟、60分钟采集不等,做成日负荷曲线后可能是96点、48点或24点,做聚类前必须统一。最简单的方法是用resample函数重采样到目标点数。第二是处理缺失值。智能电表偶尔会漏报,可以用前后时刻均值填补,如果一天内缺失点太多就直接删除该用户当天的曲线。第三是异常值处理,比如负荷值超过变压器容量或者出现负数,要么剔除,要么做平滑。第四是归一化,把每条负荷曲线都缩放到0到1之间,避免量纲差异影响距离计算。
归一化这里有一个特别容易踩的坑:尽量做“按用户最大负荷归一化”而不是“按全体数据最大负荷归一化”。后者会把大负荷用户和小负荷用户混在一起,导致聚类结果偏向按用电量大小分类,而不是按用电形状分类。对用电行为分析来说,形状特征往往比绝对数值更有业务意义。
3.2 几个关键参数的设置和选择依据
参数设置我用一张表整理出来,都是我实测后可复现的默认推荐值:
| 参数 | 推荐值 | 设置说明 |
|---|---|---|
| 聚类数 c | 3~5,结合轮廓系数确定 | 负荷行为分太多类会让业务方难以解释 |
| 模糊指数 m | 2.0 | 经典经验值,m太大类间区分度会下降 |
| 粒子数 N | 20~30 | 数据维度不高时30个足够 |
| 最大迭代次数 | 50~100 | PSO本身收敛快,超过100收益很小 |
| 惯性权重 w | 0.9线性递减到0.4 | 前期加强全局搜索,后期加强局部收敛 |
| 加速因子 c1、c2 | 1.5~2.0 | 典型值2.0,想更稳可以取1.49 |
| 粒子位置边界 | 归一化后[0,1] | 与数据范围保持一致 |
| 速度边界 | 位置范围的±20% | 防止粒子飞出解空间 |
关于聚类数c的确定,我喜欢用轮廓系数辅助判断。跑一遍c从2到8,分别计算轮廓系数,选轮廓系数较大且曲线出现“肘部”的位置。但要注意,业务解释优先级高于指标:如果c=4的分群能让电网业务人员明确说出“上班族、夜猫子、全天高耗能、普通规律型”这四类标签,那就算轮廓系数稍低一点也值得优先采用。
3.3 Matlab核心代码框架,照着改就能用
下面是我整理的精简版代码框架,保证在Matlab R2018及更高版本上都能直接运行。代码分为三块:适应度函数、PSO主程序、FCM聚类。
首先是适应度函数,输入一个粒子(即一组聚类中心)和负荷数据,返回FCM目标函数值:
function fit = fitnessFCM(centers, data, m) % centers: c x d 矩阵,c为聚类数,d为特征维度 % data: n x d 矩阵,n为样本数 % m: 模糊指数 c = size(centers, 1); n = size(data, 1); % 计算每个样本到每个中心的欧氏距离 dist = zeros(n, c); for i = 1:c diff = data - repmat(centers(i, :), n, 1); dist(:, i) = sum(diff.^2, 2); end % 加一个小量防止除零 dist = max(dist, 1e-10); % 计算隶属度矩阵 invDist = 1 ./ dist .^ (1 / (m - 1)); U = invDist ./ repmat(sum(invDist, 2), 1, c); % FCM目标函数值 fit = sum(sum((U .^ m) .* dist)); end然后是PSO主程序。我用矩阵化写法,避免for循环套for循环导致数据量一大跑半天:
function [bestCenter, gbest] = PSO_FCM(data, c, m, N, maxIter) % 参数初始化 [n, d] = size(data); wMax = 0.9; wMin = 0.4; c1 = 2; c2 = 2; xMin = min(data(:)); xMax = max(data(:)); % 初始化粒子位置和速度 X = rand(N, c * d) * (xMax - xMin) + xMin; V = rand(N, c * d) * 0.2 * (xMax - xMin) - 0.1 * (xMax - xMin); % 计算初始适应度 fit = zeros(N, 1); for i = 1:N centers = reshape(X(i, :), c, d); fit(i) = fitnessFCM(centers, data, m); end pbest = X; pbestFit = fit; [gbestFit, idx] = min(fit); gbest = X(idx, :); % 迭代更新 for t = 1:maxIter w = wMax - (wMax - wMin) * t / maxIter; for i = 1:N V(i, :) = w * V(i, :) + ... c1 * rand(1, c * d) .* (pbest(i, :) - X(i, :)) + ... c2 * rand(1, c * d) .* (gbest - X(i, :)); % 限速 V(i, :) = max(min(V(i, :), 0.2 * (xMax - xMin)), -0.2 * (xMax - xMin)); X(i, :) = X(i, :) + V(i, :); % 越界重置 X(i, :) = max(min(X(i, :), xMax), xMin); end % 重新计算适应度并更新个体最优和全局最优 for i = 1:N centers = reshape(X(i, :), c, d); fit(i) = fitnessFCM(centers, data, m); if fit(i) < pbestFit(i) pbest(i, :) = X(i, :); pbestFit(i) = fit(i); end end [curBest, idx] = min(pbestFit); if curBest < gbestFit gbestFit = curBest; gbest = pbest(idx, :); end end bestCenter = reshape(gbest, c, d); end最后一步,用PSO找到的聚类中心初始化FCM并完成最终聚类。Matlab自带fcm函数在模糊逻辑工具箱里,但我习惯自己写,方便控制细节:
function [U, centers] = finalFCM(data, initCenter, m, maxIter) [n, d] = size(data); c = size(initCenter, 1); centers = initCenter; U = zeros(n, c); for iter = 1:maxIter dist = zeros(n, c); for i = 1:c diff = data - repmat(centers(i, :), n, 1); dist(:, i) = sum(diff.^2, 2); end dist = max(dist, 1e-10); invDist = 1 ./ dist .^ (1 / (m - 1)); U = invDist ./ repmat(sum(invDist, 2), 1, c); newCenters = (U .^ m)' * data ./ repmat(sum(U .^ m, 1)', 1, d); if norm(newCenters - centers, 'fro') < 1e-6 centers = newCenters; break; end centers = newCenters; end end跑的时候主脚本大概长这样:加载数据、预处理、调用PSO_FCM、调用finalFCM,然后把每条曲线归到隶属度最大的类里。
提示:代码里我故意没有用parfor这类并行写法,目的在于让代码在普通笔记本上也能跑。数据量超过3万条日负荷曲线时,考虑把reshape和repmat换成隐式扩展写法,速度能快一倍还不止。
3.4 结果可视化:怎么看聚类效果合不合理
聚类跑完之后,可视化不是锦上添花,而是验证算法有没有跑偏的必要步骤。我最常用的三张图:
第一张是每类用户的日负荷曲线叠加图,横轴是时间点,纵轴是负荷值。把同一类的所有曲线画在一个坐标系里,用透明度调低一点,曲线重叠度高说明类内一致性好;如果某一类曲线非常发散,说明聚类数或者特征选得有问题。第二张是各类平均负荷曲线对比图,这是给业务方汇报时最核心的图,一条折线代表一类用户,直接可以看出错峰特征和用电高峰时段。第三张是各类用户占比饼图和特征雷达图,雷达图每个维度可以是峰时用电比例、谷时用电比例、最大负荷时刻、负荷率等业务指标。
绘图的美观度也要注意,网格、图例、线宽设置清楚,线条颜色选色盲友好的配色方案。很多人忽略这一点,但论文和汇报里图的阅读体验直接影响评审观感。
4. 怎么评价聚类效果:用指标说话,别只看图
4.1 三个常用聚类评价指标,原理和计算方式
光眼睛看图不算数,要有量化指标。我固定用三个内部评价指标:
轮廓系数(SC)衡量的是样本与其所属类的相似度、以及与非所属类的不相似度,取值范围[-1,1],越接近1表示聚类越合理。把所有样本的轮廓系数取平均,就是整体轮廓系数。计算时要算两两样本距离,数据量大时比较耗时。
Davies-Bouldin指数(DB)衡量的是类内散度与类间距离之比,把所有类两两组合的最大值取平均。DB越小,类内越紧凑、类间越分离。这个指标计算成本比轮廓系数低,适合快速对比不同聚类数。
Xie-Beni指标(XB)是模糊聚类专用的评价指标,分子是FCM目标函数值J,分母是n乘以“各类中心到全局中心最小距离的平方”。所以XB同时惩罚聚类结果不紧凑和聚类中心靠得过近。对FCM和PSO-FCM做对比时,XB是最核心的指标,我在论文里就是用XB值说明PSO-FCM比原始FCM的聚类质量更高。
4.2 对比实验怎么设计才有说服力
做对比实验时,我强烈建议你固定随机种子。Matlab里跑rng(1)再跑算法,保证每次结果可复现。然后对同一份预处理好的数据,分别跑K-means、原始FCM、PSO-FCM各20次,每次用不同的随机初始化,记录每次的SC、DB、XB,最后算均值和标准差。
均值反映算法效果,标准差反映稳定性。这个设计能讲出两个结论:一是PSO-FCM的平均指标优于FCM,说明搜索到了更好的聚类中心;二是标准差更小,说明结果对初始化不再那么敏感。下面是我用公开的某地区居民负荷数据跑出来的示意结果,你在自己的数据上大概率能观察到类似趋势:
| 算法 | SC均值 | DB均值 | XB均值 | 运行耗时(秒) |
|---|---|---|---|---|
| K-means | 0.42 | 1.58 | 0.87 | 0.8 |
| 原始FCM | 0.45 | 1.49 | 0.76 | 1.2 |
| PSO-FCM | 0.51 | 1.32 | 0.58 | 6.5 |
从结果可以看到,PSO-FCM在三个聚类质量指标上都更优,代价是运行时间更长。但对离线场景的居民用电行为分析来说,几分钟的运行时间完全可以接受,毕竟不是在线实时计算。
4.3 稳定性分析:为什么PSO-FCM比原始FCM更让人放心
原始FCM随机初始化跑20次,聚类结果可能每隔几次就换一种分法。你把两次不同运行得到的隶属度矩阵相减,会发现很多样本的隶属度差异超过0.3。这在业务上很致命:同一个分析报告,换一次随机种子结论就变了,业务方肯定不认。
PSO-FCM由于初始中心经过全局搜索优化,即使PSO本身也有随机性,多次运行最终收敛的位置差异远小于直接随机初始化FCM。我实测中,PSO-FCM跑20次,所有样本的隶属度标准差异常小于0.05。这种稳定性对课题研究和企业项目落地都非常重要,也是我推荐这个组合的最核心理由。
5. 实操中常见的坑和排查技巧
5.1 粒子飞出去了:位置越界和NaN问题
我第一次跑PSO-FCM就遇到NaN。问题出在速度更新时,如果粒子速度过大,位置会冲到数据范围之外,距离计算得到超大值,隶属度矩阵出现除零或无穷,目标函数直接变NaN,然后gbest被污染,后面全部崩掉。
解决办法就是我代码里写的两个约束:一个是限速,速度上限设为位置范围的20%;另一个是越界重置,位置超出边界就拉回到边界。还有个细节是距离矩阵计算时加一个1e-10的小量,避免完全重合导致除以零。这三个小技巧组合起来,基本不会再出现NaN。
5.2 早熟收敛:粒子群全挤在局部最优里出不来
PSO的一个常见毛病是收敛太快、后期多样性不足,所有粒子都聚集在某个局部最优附近,gbest长期不更新。排查方法很简单:打印每次迭代的gbest适应度值,画收敛曲线。如果曲线前20次迭代就完全平了,大概率是早熟。
解决办法有几种。最常用的是惯性权重w线性递减,前期w大保持探索,后期w小加强开发,这个我在代码里已经实现了。如果还不行,可以给粒子速度加随机扰动,或者采用自适应变异机制:当群体最优连续多代不更新时,随机重置一部分粒子的位置。我自己做课题时,把wMax从0.9调到0.95、wMin从0.4调到0.3,对跳出局部最优有明显帮助。
5.3 聚类数K很难拍板:别只信指标,要结合业务
聚类数c是整个流程里最主观的参数。指标会给你一个候选范围,但不会替你做业务决策。我遇到过一个案例:轮廓系数最高点出现在c=6,但6类里有两类从业务角度根本无法解释,最后选了c=4,每一类都能对应明确的用户群体。
我的建议是做一个“聚类数-指标曲线”,把c从2到8的SC、DB、XB都算出来,然后拉上业务方一起看图。曲线肘部附近通常有2到3个候选值,结合每类平均负荷曲线的可解释性,最终拍板。这类决策用表格列出来再开会讨论,比一个人闷头选要靠谱得多。
5.4 数据预处理泄露:一个容易忽略的严重错误
做数据挖掘的人常听到“数据泄露”是在机器学习训练集和测试集之间,其实聚类里也有类似问题。归一化的时候,如果你先按全量数据算好最大最小值,再去做后续分析,这没问题;但如果你是先抽样一部分数据算归一化参数,然后把全部数据套用这个参数,就会导致不同批次的用户曲线缩放尺度不一致,聚类结果自然失真。
更隐蔽的坑是按天归一化:有些同学对每一天单独归一化,结果某用户某天用电量很小,归一化后形状被放得很大,反而显得“很规律”。我处理负荷曲线时,习惯对一个用户的多天平均曲线做整体归一化,而不是对每天分别归一化。这样既保留了用户的用电水平信息,又不让个别异常日主导曲线形状。
5.5 运行速度慢:学会矩阵化编程
Matlab是出了名的“慢在循环,快在矩阵”。如果你用三层for循环写隶属度更新,3万条数据跑一次可能要十分钟。解决办法是把内层循环全部改成矩阵运算。我给出的代码框架已经做了这层优化,但如果你的数据量特别大,还可以进一步用Matlab的隐式扩展替代repmat,比如写成(data - centers(i,:))而不是repmat,速度快很多。
还有一个容易忽略的性能点:PSO里粒子数N设置过大(比如100)对结果提升非常有限,但耗时线性增加。用30个粒子跑60次迭代,已经能覆盖绝大多数负荷数据的搜索需求。
6. 往实际业务里扩展:用电行为分析的落地价值
6.1 用户画像标签体系建设
聚类完成之后,每一类用户都可以打上业务标签。比如四类典型结果可以对应“白天低负荷、傍晚和夜间高负荷”的上班族、“深夜持续用电”的夜猫子、“全天负荷处于高位”的高耗能家庭、“负荷平稳且偏小”的独居老人或节能型家庭。这些标签是电网精细化运营的基础,营销部门做客户关怀、用能建议都依赖它。
具体操作时,我会在聚类结果基础上,为每一类用户计算关键特征统计量:峰时用电占比、谷时用电占比、最大负荷出现时刻、平均负荷率、日用电量标准差等,然后做成一张用户标签表导出。业务方看到的不只是一堆曲线,而是一张可以直接落到CRM系统里的标签宽表。
6.2 辅助需求侧响应和分时电价设计
识别出不同用电行为群体之后,需求侧响应的目标用户筛选就变得清晰。比如某个地区要推动“削峰填谷”,就应该优先选择峰时用电占比高、且与全局负荷高峰时段重合度高的用户群,这类用户的可调节潜力最大。分时电价套餐设计也可以针对夜猫子型用户推出夜间优惠价,引导更多用户把高耗能电器转移到谷时使用。
我实际参与过一个简单的测算:根据聚类结果筛选出峰时负荷占比超过40%的用户,针对这部分群体设计定向激励方案后,试点用户群的整体峰值负荷降低了8%左右。当然,这个数字和地区、季节、激励力度都有关系,但聚类分析作为用户筛选的第一步,价值非常明确。
6.3 异常用电行为的辅助识别
聚类还能顺手做一些异常检测的工作。对于每一类用户,可以计算类内样本与聚类中心的平均距离,得到一个“典型程度”的分布。那些与类中心距离特别远的用户,往往存在异常用电情况:要么数据质量有问题,要么用电行为发生了突变,可能有表计故障,也可能是某种特殊用电设备接入。
把这个思路做成规则很简单:跑完聚类,计算每个样本到所属类中心的距离,将距离超过99%分位数的样本标记为疑似异常,再人工核查。这个方法成本低、效率高,尤其适合做台区线损治理前的筛查。
6.4 对研究生和开发者的一些课题扩展建议
如果你是用这个题目做毕业设计,或者想在此基础上发表小论文,可以从几个方向扩展:改进PSO本身,比如加入自适应变异、混沌初始化、多种群协同策略;改进FCM的模糊指数m,让不同类使用不同的模糊程度;引入时间序列特征而不是直接用原始负荷曲线,比如用负荷的统计特征、熵特征、形态特征做聚类。还有一个热门方向是把PSO-FCM和LSTM结合,先聚类出不同用户群,再对每一类单独做负荷预测,预测精度通常比混在一起训练更高。
这些扩展思路的共同点是不改变项目的主干框架,只是在某一环节做算法替换或叠加,Matlab代码的复用度很高。从投稿角度来说,哪怕只是在PSO的惯性权重更新方式上做一个小改进,配合完整的对比实验,也足够撑起一篇还不错的学报论文。
我在实际调试这套代码的时候,最大的体会是:别急着上全量数据,先用几百条用户数据把整个pipeline跑通,确认从数据预处理到PSO寻优再到FCM聚类每个环节的输出都符合预期,再扩展到几千条甚至几万条。另外,一定记得在项目开始时就固定随机种子、把代码封装成函数、每一步都保存中间结果,否则后期调参和复现会让你痛不欲生。按照上面的思路走一遍,你大概率能稳定跑出一个比原始FCM聚类效果更好、更具业务解释性的结果。