并行粒子群优化

粒子群方法

从算法的角度来看,PSO方法相对简单。其主要思想是在EA交易的输入参数空间中生成一组虚拟“粒子”。然后,粒子移动并根据EA在空间中相应点的交易度量改变其速度。该过程重复多次,直到性能停止改善。该算法的伪代码如下:

编辑切换为居中

添加图片注释,不超过 140 字(可选)

粒子群优化伪码

根据这个代码,每个粒子都有一个当前的位置、速度和过去“最佳”点的记忆。这里,“最佳”点是指达到该粒子目标函数最高值的点(一组EA输入参数)。让我们在类里面描述一下。

 
 

class Particle { public: double position[]; // current point double best[]; // best point known to the particle double velocity[]; // current speed double positionValue; // EA performance in current point double bestValue; // EA performance in the best point int group; Particle(const int params) { ArrayResize(position, params); ArrayResize(best, params); ArrayResize(velocity, params); bestValue = -DBL_MAX; group = -1; } };

所有数组的大小都等于优化空间的维数,因此它等于正在优化的专家顾问参数的数目(传递给构造函数)。默认情况下,目标函数值越大,优化效果越好。因此,用最小可能的 -DBL_MAX 数值来初始化 bestValue 字段。其中一个交易指标通常被用来作为评估EA的标准,如利润、盈利能力、夏普比率等。如果通过较低值被认为更好的参数,例如回撤,来执行优化,则可以进行适当的转换以最大化相反的值。

数组和变量是公有的,以简化访问和它们的重新计算代码。严格遵守OOP原则需要使用“private”修饰符隐藏它们,并描述读取和修改方法。

除了单个粒子外,该算法还处理所谓的“拓扑”或粒子子集。它们可以根据不同的原则来创建。“社会群体拓扑”将用于我们的案例。这样的组存储有关其所有粒子中最佳位置的信息。

 
 

class Group { private: double result; // best EA performance in the group public: double optimum[]; // best known position in the group Group(const int params) { ArrayResize(optimum, params); ArrayInitialize(optimum, 0); result = -DBL_MAX; } void assign(const double x) { result = x; } double getResult() const { return result; } bool isAssigned() { return result != -DBL_MAX; } };

通过在粒子类的“group”字段中指定组名,我们可以指示粒子所属的组(见上文)。

现在,让我们继续对粒子群算法本身进行编码。它将作为一个单独的类实现。让我们从粒子和群的数组开始。

 
 

class Swarm { private: Particle *particles[]; Group *groups[]; int _size; // number of particles int _globals; // number of groups int _params; // number of parameters to optimize

对于每个参数,我们需要指定执行优化的值的范围,以及增量(步长)。

 
 

double highs[]; double lows[]; double steps[];

此外,最佳参数集应该存储在某个地方。

 
 

double solution[];

因为类将有几个不同的构造函数,让我们来描述统一的初始化方法。

 
 

void init(const int size, const int globals, const int params, const double &max[], const double &min[], const double &step[]) { _size = size; _globals = globals; _params = params; ArrayCopy(highs, max); ArrayCopy(lows, min); ArrayCopy(steps, inc); ArrayResize(solution, _params); ArrayResize(particles, _size); for(int i = 0; i < _size; i++) // loop through particles { particles[i] = new Particle(_params); ///do ///{ for(int p = 0; p < _params; p++) // loop through all dimensions { // random placement particles[i].position[p] = (MathRand() * 1.0 / 32767) * (highs[p] - lows[p]) + lows[p]; // adjust it according to step granularity if(steps[p] != 0) { particles[i].position[p] = ((int)MathRound((particles[i].position[p] - lows[p]) / steps[p])) * steps[p] + lows[p]; } // the only position is the best so far particles[i].best[p] = particles[i].position[p]; // random speed particles[i].velocity[p] = (MathRand() * 1.0 / 32767) * 2 * (highs[p] - lows[p]) - (highs[p] - lows[p]); } ///} ///while(index.add(crc64(particles[i].position)) && !IsStopped()); } ArrayResize(groups, _globals); for(int i = 0; i < _globals; i++) { groups[i] = new Group(_params); } for(int i = 0; i < _size; i++) { // random group membership particles[i].group = (_globals > 1) ?(int)MathMin(MathRand() * 1.0 / 32767 * _globals, _globals - 1) : 0; } }

所有的数组都是按照给定的维数分布的,并且被传输的数据填充。粒子的初始位置、速度和群成员是随机确定的。上面的代码中有一些重要的注释。我们稍后再谈这个。

请注意,粒子群算法的经典版本旨在优化连续坐标系中定义的函数。然而,EA参数通常是通过一定的步长来测试的。例如,标准移动平均线的周期不能为11.5。这就是为什么,除了所有维度的一系列可接受值之外,我们还设置了用于舍入粒子位置的步长。这不仅要在初始化阶段进行,而且要在优化过程中的计算中进行。

现在,我们可以使用 init 实现几个构造函数。

 
 

#define AUTO_SIZE_FACTOR 5 public: Swarm(const int params, const double &max[], const double &min[], const double &step[]) { init(params * AUTO_SIZE_FACTOR, (int)MathSqrt(params * AUTO_SIZE_FACTOR), params, max, min, step); } Swarm(const int size, const int globals, const int params, const double &max[], const double &min[], const double &step[]) { init(size, globals, params, max, min, step); }

第一种方法使用一个众所周知的经验法则,根据参数的个数来计算群的大小和群的个数。可以根据需要更改 AUTO_SIZE_FACTOR 常量(默认值为5)。第二个构造函数允许显式地指定所有值。

析构函数释放分配的内存。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值