使用 Pytorch 加速 PSO 算法?



我已经使用PyTorch实现了PSO算法,torch.cuda.FloatTensor。 我设法加快了 2 倍,但我期待的不止于此。 它认为检查限制的步骤(line 41-55)参数更新(line 58-72)是原因。有"GPU"这样做吗?

这是我的代码:

import torch
import numpy as np
import matplotlib.pyplot as plt
dtype = torch.cuda.FloatTensor
def fitness(x,y):
return -torch.abs(torch.sin(x)*torch.cos(y)*torch.exp(torch.abs(1-(torch.sqrt(x**2+y**2))/(3.1415))))
def velocity(v, gxbest, pxbest, pybest, x, pop, w, c1, c2):
return w*torch.rand(pop).type(dtype)*v + 
c1*torch.rand(pop).type(dtype)*(pxbest - x) + 
c2*torch.rand(pop).type(dtype)*(gxbest.expand(x.size(0)) - x)
def PSO(pop, xmax, xmin, niter, wmax, wmin, c1, c2):
vx                 = torch.rand(pop).type(dtype)
vy                 = torch.rand(pop).type(dtype)
best               = np.zeros(niter)
x                 = (xmax -  xmin)*torch.rand(pop).type(dtype) + xmin
y                 = (xmax -  xmin)*torch.rand(pop).type(dtype) + xmin
z                 = fitness(x,y)
[minz, indexminz] = z.min(0)
gxbest            = x[indexminz] 
gybest            = y[indexminz] 
pxbest            = x
pybest            = y
pzbest            = z
for K in range(niter):
w      = wmax - ((wmax - wmin) / niter) * (K)
vnextx = velocity(vx, gxbest, pxbest, pybest, x, pop, w, c1, c2)
xnext  = x + vnextx
vnexty = velocity(vy, gxbest, pxbest, pybest, y, pop, w, c1, c2)
ynext  = y + vnexty
**(41)** xnext = xnext.cpu()
ynext = ynext.cpu()
idxmax        = (xnext > xmax) # elements that are bigger that upper limit
idxmim        = (xnext < xmin)  # elements that are smaller that upper limit
xnext[idxmax] = xmax
xnext[idxmim] = xmin
idymax        = (ynext > xmax) # elements that are bigger that upper limit
idymim        = (ynext < xmin)  # elements that are smaller that upper limit
ynext[idymax] = xmax
ynext[idymim] = xmin
xnext = xnext.cuda() 
**(55)** ynext = ynext.cuda() 
znext = fitness(xnext,ynext)
**(58)**[minznext, indexminznext]  = znext.min(0)
if (minznext[0] < minz[0]):
minz   = minznext
gxbest = xnext[indexminznext]
gybest = ynext[indexminznext]
indexpbest         = (znext < pzbest)
pxbest[indexpbest] = xnext[indexpbest]
pybest[indexpbest] = ynext[indexpbest]
pzbest[indexpbest] = znext[indexpbest]
x                  = xnext
y                  = ynext
vx                 = vnextx
**(72)** vy                 = vnexty
best[K] = minz.cpu().numpy()
return gxbest, gybest , minz, best
def main():
pop, xmax, xmin, niter = 10000, 10, -10, 10
wmax = 0.9
wmin = 0.4
c1   = 2.05
c2   = 2.05
xbest, ybest, fitbest, best = PSO(pop, xmax, xmin, niter, wmax, wmin, c1, c2)
print(xbest)
print(ybest)
print(fitbest)
t = np.linspace(0,niter,niter)
plt.plot(t, best, 'k.-')
plt.show()
main()

非常感谢您的帮助。

好吧;它通过使用 GPU 为我工作!

8.0557 [Torch.cuda.FloatTensor of size 1 (GPU 0)]

9.6666 [Torch.cuda.FloatTensor of size 1 (GPU 0)]

-19.2107 [Torch.cuda.FloatTensor of size 1 (GPU 0)]

除了加速 PSO 之外,性能在很大程度上取决于初始化以及您使用的 PSO 变体。

对于初始化,我只在值范围内随机设置粒子位置,并将初始速度设置为零,因为它们将在第一次和后续迭代期间更新。

大多数人现在至少使用Clerc版本的受限PSO。 看来,既然您有wminwmax值,那就是原始的 PSO。

原始 PSO 使用:

w = wmax - (wmax - wmin) * (iter / numIterations)
v(j, part) = w * v(j, part) + c1 * random1 * (b(j, part) - p(j, part)) + c2 * random2 * (bg(j) - p(j, part))
If v(j, part) < vmin Then v(j, part) = vmin
If v(j, part) > vmax Then v(j, part) = vmax

其中j是维度之一,part是当前粒子,v(j, part)是速度,p(j, part)是粒子位置,c1c2是社会参数,random1random2是随机均匀数,bg(j)是维度j的最佳全局位置,vminvmax是0.1和-0.1, 分别。 但是,您可以根据每个要素值的范围更改vminvmax

受限的PSO用途:

c1 = 2.05
c2 = 2.05
varphi = c1 + c2
kappa = 2 / Math.Abs(2 - varphi - Math.Sqrt(varphi * varphi - 4 * varphi))
v(j, part) = kappa * (p(j, part) + c1 * random1 * (p(j, part) - p(j, part)) + c2 * random2 * (bg(j) - p(j, part)))
If v(j, part) < vmin Then v(j, part) = vmin
If v(j, part) > vmax Then v(j, part) = vmax

最新更新