PySwarms(Python粒子群优化工具包)的使用:GlobalBestPSO例子解析

前段时间需要用到粒子群优化算法来求取全局最优解,这个问题用PySwarms来解决。奈何没有搜索到什么中文文档讲解使用方法,只能抱着英文文档慢慢啃了QAQ。所以这里把个人见解写了下来,希望能和有需求的朋友交流。

Posted in Python onApril 05, 2021

这里将主要解析Inverse Kinematics Problem这个官方例子,以及从中学到如何使用GlobalBestPSO

Inverse Kinematics Problem(运动学逆问题)

问题官网网站如下(此问题所有代码均来自官网):https://pyswarms.readthedocs.io/en/latest/examples/usecases/inverse_kinematics.html

问题背景

逆运动学是机器人技术中最具挑战性的问题之一。IK坐标难以计算且多解,所以特别困难。现在可以为3自由度机械手找到简单的解决方案,但是尝试解决6自由度甚至更多自由度的问题可能会出现富有挑战性的代数问题。

在此例中,我们将使用具有5个旋转关节和1个棱柱关节的6自由度斯坦福机械臂。这些关节的活动范围如下所示:
PySwarms(Python粒子群优化工具包)的使用:GlobalBestPSO例子解析
现在,如果给定了末端位置(在本例中为xyz坐标),则需要找到具有上表约束的最佳参数。这些条件足以将这个问题视为优化问题。我们将参数向量X定义如下:
PySwarms(Python粒子群优化工具包)的使用:GlobalBestPSO例子解析
对于末端位置,我们将目标向量T定义为:
PySwarms(Python粒子群优化工具包)的使用:GlobalBestPSO例子解析
下面就开始解决具体问题吧!

原文后续就开始大致讲解粒子群优化算法的原理,不明白的朋友可以看这篇博客,讲解得很清楚。
最优化算法之粒子群算法(PSO)

有关粒子群优化算法的原理这里就不再赘述了。

准备工作

首先导入相关包:

# Import modules
import numpy as np
# Import PySwarms
import pyswarms as ps

我们以点[−2,2,3]作为目标,希望该点为最佳机械手姿势。首先定义一个函数来获取从当前位置到目标位置的距离(可以看出此距离函数就是求两位置间的欧氏距离):

def distance(query, target):
    x_dist = (target[0] - query[0])**2
    y_dist = (target[1] - query[1])**2
    z_dist = (target[2] - query[2])**2
    dist = np.sqrt(x_dist + y_dist + z_dist)
    return dist

我们将使用此距离函数来计算代价,显然距离越远,距离代价就越高。

下面开始设置算法需要的参数:

swarm_size = 20
dim = 6        # Dimension of X
epsilon = 1.0
options = {'c1': 1.5, 'c2':1.5, 'w':0.5}

constraints = (np.array([-np.pi , -np.pi/2 , 1 , -np.pi , -5*np.pi/36 , -np.pi]),
               np.array([np.pi  ,  np.pi/2 , 3 ,  np.pi ,  5*np.pi/36 ,  np.pi]))

d1 = d2 = d3 = d4 = d5 = d6 = 3

swarm_size为粒子个数;dim为待求参数的维度;epsilon后续也没有用到,我也不太明白放在这里的用意,如有大佬告知,不胜感激;options为重要的参数列表,c1为粒子的个体认知系数,c2为群体系数系数,w为惯性因子;constraints为待求参数取值限制;d1~d6为关节长度,均取3。(有关API参数的含义和注意事项后面会详细介绍

为了获得当前位置,我们需要计算每个关节的旋转和平移矩阵。为此,这里我们使用Denvait-Hartenberg参数。我们定义了一个计算这些矩阵的函数。该函数使用旋转角度和棱柱形关节的延伸量d作为输入(不用担心不明白这是啥参数矩阵,不用明白,只需要知道输入一些参数返回一个矩阵就好):

def getTransformMatrix(theta, d, a, alpha):
    T = np.array([[np.cos(theta) , -np.sin(theta)*np.cos(alpha) ,  np.sin(theta)*np.sin(alpha) , a*np.cos(theta)],
                  [np.sin(theta) ,  np.cos(theta)*np.cos(alpha) , -np.cos(theta)*np.sin(alpha) , a*np.sin(theta)],
                  [0             ,  np.sin(alpha)               ,  np.cos(alpha)               , d              ],
                  [0             ,  0                           ,  0                           , 1              ]
                 ])
    return T

现在我们可以计算变换矩阵以获得末端的位置。为此,我们创建了另一个函数,该函数将向量X与关节变量作为输入(同样不需要知道怎么算的,只需要知道输入和输出是什么就好):

def get_end_tip_position(params):
    # Create the transformation matrices for the respective joints
    t_00 = np.array([[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]])
    t_01 = getTransformMatrix(params[0] , d2        , 0 , -np.pi/2)
    t_12 = getTransformMatrix(params[1] , d2        , 0 , -np.pi/2)
    t_23 = getTransformMatrix(0         , params[2] , 0 , -np.pi/2)
    t_34 = getTransformMatrix(params[3] , d4        , 0 , -np.pi/2)
    t_45 = getTransformMatrix(params[4] , 0         , 0 ,  np.pi/2)
    t_56 = getTransformMatrix(params[5] , d6        ,0  ,  0)

    # Get the overall transformation matrix
    end_tip_m = t_00.dot(t_01).dot(t_12).dot(t_23).dot(t_34).dot(t_45).dot(t_56)

    # The coordinates of the end tip are the 3 upper entries in the 4th column
    pos = np.array([end_tip_m[0,3],end_tip_m[1,3],end_tip_m[2,3]])
    return pos

为了运行算法,我们需要准备的最后一件事就是我们要优化的函数。我们只需要计算每个群体粒子的位置与目标点之间的距离即可(这里就是运用到前面定义的函数get_end_tip_position进行计算X[i]的末端位置,再运用distance函数计算此位置与目标点之间的距离,返回这个距离数组):

def opt_func(X):
    n_particles = X.shape[0]  # number of particles
    target = np.array([-2,2,3])
    dist = [distance(get_end_tip_position(X[i]), target) for i in range(n_particles)]
    return np.array(dist)

运行算法

经过上述准备,我们终于可以开始实现算法了!

# Call an instance of PSO
optimizer = ps.single.GlobalBestPSO(n_particles=swarm_size,
                                    dimensions=dim,
                                    options=options,
                                    bounds=constraints)

# Perform optimization
cost, joint_vars = optimizer.optimize(opt_func, iters=1000)

很简单的样子!?(并没有,自己写待优化函数的时候呢QAQ)代入上面说的参数实例化一个全局最优器对象,再调用其优化方法便可以得到我们上面设定的代价值和待求参数值。

print(get_end_tip_position(joint_vars))

[-2.09012905 2.07694604 3.01641479]

再查看我们求取的参数值计算得到的末端坐标,几乎就是我们的目标坐标值。成功啦!

下面开始最关键的使用部分啦!

GlobalBestPSO的使用

我举上面的官网例子其实也是因为我就是看那个例子学会的。下面就开始介绍GlobalBestPSO的使用方法吧!

参数(这里只讲常用的参数)

  1. n_particles :int,粒子群中的粒子数。一般取 20–40。如果是比较难的问题或者特定类别的问题,粒子数可以取到100 - 200。
  2. dimensions:int,待求取参数的维度。
  3. options:dict,参数c1,c2,w的设置。
    使用带有关键字{‘c1’, ‘c2’, ‘w’}的字典 。这里再重复一遍各关键字的含义:c1为粒子的个体认知系数,c2为群体系数系数,w为惯性因子。
    c1和c2取值通常相等,且常取值为2,当然取值0-4也有。
    w较大时全局搜索能力强,较小时局部搜索能力强。
  4. bounds:numpy.ndarray,待求参数的取值范围。
    两行的ndarray,第一行为待求参数的最小值,第二行为最大值。很重要的一点是,列的大小要和输入的参数维度匹配,并且还要注意每一个参数范围的对齐,不要错位了。
  5. init_pos:numpy.ndarray,初始位置的设置。
    不设置的话,粒子初始位置则是随机的。

方法

其实我认为最重要的是这个方法里待优化方程的写法QAQ。下面就开始了!PySwarms(Python粒子群优化工具包)的使用:GlobalBestPSO例子解析

optimize参数

  1. objective_func :callable,求取最优解的方程。

objective_func怎么写

说实话API文档并没有明确给出这个函数怎么写:)
这里我们以一个简单的二元二次为例,来看这个函数到底怎么写。
PySwarms(Python粒子群优化工具包)的使用:GlobalBestPSO例子解析
显然取全局最优也就是方程取最小值,此时x1=m,x2=n。

最最重要的一点就是待求参数要放在第一个,可以取名x,y等等等等,后面参数放多少都可以(当然夸张了)。其实就是类似于可变参数函数的参数规则。第一个参数是我们现在需要求的参数,所以自然不能传递值。其余参数就必须要有确定的值。

还有一点也是需要特别注意的是:放在第一个位置的参数在多维时,在使用第i个参数时,需要采用 x[: ,i] 这样的形式,否则会出错。

明确完这两点之后就可以开始写函数了:

import pyswarms as ps
swarm_size = 20
dim = 2        # Dimension of paramater vetcor X
options = {'c1': 0.5, 'c2': 0.3, 'w': 0.9}

optimizer = ps.single.GlobalBestPSO(n_particles=swarm_size,
                                    dimensions=dim,
                                    options=options)
def func(x,m=2,n=2):
    f = (x[:,0]-m)**2+(x[:,1]-n)**2
    return f
cost, pos = optimizer.optimize(func,iters=1000,m=3,n=1)

运行结果如下:
PySwarms(Python粒子群优化工具包)的使用:GlobalBestPSO例子解析

  1. iters:int,迭代次数。这个参数可以根据待解决问题的大小来选择。
  2. kwargs :dict,上述方程的输入参数。也可以在后面按参数名传递参数值。

optimize返回值

全局最小代价和全局最优位置。

总结

只要设定了合适的PSO优化算法参数,写好了待优化函数,理论上就能运用GlobalBestPSO求得全局最小代价和全局最优位置。

Python 相关文章推荐
Python中字典(dict)和列表(list)的排序方法实例
Jun 16 Python
Python实现购物系统(示例讲解)
Sep 13 Python
python使用标准库根据进程名如何获取进程的pid详解
Oct 31 Python
实践Vim配置python开发环境
Jul 02 Python
在python中安装basemap的教程
Sep 20 Python
Windows 安装 Anaconda3+PyCharm的方法步骤
Jun 13 Python
Python OpenCV 使用滑动条来调整函数参数的方法
Jul 08 Python
利用 Flask 动态展示 Pyecharts 图表数据方法小结
Sep 04 Python
基于python使用tibco ems代码实例
Dec 20 Python
解决keras backend 越跑越慢问题
Jun 18 Python
python爬虫快速响应服务器的做法
Nov 24 Python
Python实现曲线拟合的最小二乘法
Feb 19 Python
python实现批量提取指定文件夹下同类型文件
Apr 05 #Python
python实现ROA算子边缘检测算法
python实现批量移动文件
Python list去重且保持原顺序不变的方法
Apr 03 #Python
python自动统计zabbix系统监控覆盖率的示例代码
Apr 03 #Python
2021年pycharm的最新安装教程及基本使用图文详解
PyCharm配置KBEngine快速处理代码提示冲突、配置命令问题
You might like
php 代码优化之经典示例
2011/03/24 PHP
PHP设计模式之责任链模式的深入解析
2013/06/13 PHP
php下foreach提示Warning:Invalid argument supplied for foreach()的解决方法
2014/11/11 PHP
ThinkPHP连接数据库的方式汇总
2014/12/05 PHP
javascript不同页面传值的改进版
2008/09/30 Javascript
jQuery Ajax之$.get()方法和$.post()方法
2009/10/12 Javascript
javascript 在网页中的运用(asp.net)
2009/11/23 Javascript
JQuery小知识
2010/10/15 Javascript
js利用事件的阻止冒泡实现点击空白模态框的隐藏
2014/01/24 Javascript
JavaScript数据类型检测代码分享
2015/01/26 Javascript
PHP和NodeJs开发的应用如何共用Session
2015/04/16 NodeJs
Jquery实现$.fn.extend和$.extend函数
2016/04/14 Javascript
通用无限极下拉菜单的实现代码
2016/05/31 Javascript
jQuery实现获取隐藏div高度的方法示例
2017/02/09 Javascript
node操作mysql数据库实例详解
2017/03/17 Javascript
Bootstrap 网格系统布局详解
2017/03/19 Javascript
基于vue-simplemde实现图片拖拽、粘贴功能
2018/04/12 Javascript
详解在网页上通过JS实现文本的语音朗读
2019/03/28 Javascript
微信小程序地图导航功能实现完整源代码附效果图(推荐)
2019/04/28 Javascript
Fetch超时设置与终止请求详解
2019/05/18 Javascript
js blob类型url的视频下载问题的解决
2019/11/29 Javascript
nuxt.js写项目时增加错误提示页面操作
2020/11/05 Javascript
NodeJS配置CORS实现过程详解
2020/12/02 NodeJs
python程序变成软件的实操方法
2019/06/24 Python
Python中三维坐标空间绘制的实现
2020/09/22 Python
用css3写出气球样式的示例代码
2017/09/11 HTML / CSS
浅谈HTML5新增及移除的元素
2016/06/27 HTML / CSS
荷兰皇家航空公司官方网站:KLM Royal Dutch Airlines
2017/12/07 全球购物
你经历的项目中的SCM配置项主要有哪些?什么是配置项?
2013/11/04 面试题
三年级音乐教学反思
2014/01/28 职场文书
电焊工工作岗位职责
2014/02/06 职场文书
讲文明懂礼貌演讲稿
2014/09/11 职场文书
德能勤绩工作总结
2015/08/11 职场文书
mysql批量新增和存储的方法实例
2021/04/07 MySQL
JavaScript控制台的更多功能
2021/04/28 Javascript
sql注入报错之注入原理实例解析
2022/06/10 MySQL