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中列表、字典、元组、集合数据结构整理
Nov 20 Python
python开发之thread线程基础实例入门
Nov 11 Python
Python 字符串大小写转换的简单实例
Jan 21 Python
使用Python进行目录的对比方法
Nov 01 Python
Python+pyplot绘制带文本标注的柱状图方法
Jul 08 Python
Python自动化导出zabbix数据并发邮件脚本
Aug 16 Python
Python Web框架之Django框架文件上传功能详解
Aug 16 Python
解决Python中回文数和质数的问题
Nov 24 Python
python如何求100以内的素数
May 27 Python
详解Pycharm安装及Django安装配置指南
Sep 15 Python
python实现人性化显示金额数字实例详解
Sep 25 Python
mac系统下安装pycharm、永久激活、中文汉化详细教程
Nov 24 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函数
2006/10/09 PHP
php 字符转义 注意事项
2009/05/27 PHP
PHP 正则判断中文UTF-8或GBK的思路及具体实现
2013/11/26 PHP
十幅图告诉你什么是PHP引用
2015/02/22 PHP
php保存信息到当前Session的方法
2015/03/16 PHP
Zend Framework校验器Zend_Validate用法详解
2016/12/09 PHP
PHP大文件分块上传功能实例详解
2019/07/22 PHP
php设计模式之组合模式实例详解【星际争霸游戏案例】
2020/03/27 PHP
Mootools 1.2教程 Fx.Morph、Fx选项和Fx事件
2009/09/15 Javascript
js showModalDialog 弹出对话框的简单实例(子窗体)
2014/01/07 Javascript
jquery中获取元素里某一特定子元素的代码
2014/12/02 Javascript
JavaScript中Cookies的相关使用教程
2015/06/04 Javascript
Angular.js与node.js项目里用cookie校验账户登录详解
2017/02/22 Javascript
AngularJS实现进度条功能示例
2017/07/05 Javascript
echarts鼠标覆盖高亮显示节点及关系名称详解
2018/03/17 Javascript
Vue中保存数据到磁盘文件的方法
2018/09/06 Javascript
js使用swiper实现层叠轮播效果实例代码
2018/12/12 Javascript
vue 表单验证按钮事件交由父组件触发的方法
2018/12/17 Javascript
微信小程序登录数据解密及状态维持实例详解
2019/05/06 Javascript
详解vuex之store源码简单解析
2019/06/13 Javascript
原生JavaScript实现日历功能代码实例(无引用Jq)
2019/09/23 Javascript
js页面加载后执行的几种方式小结
2020/01/30 Javascript
使用Webpack 搭建 Vue3 开发环境过程详解
2020/07/28 Javascript
python抓取某汽车网数据解析html存入excel示例
2013/12/04 Python
python 寻找优化使成本函数最小的最优解的方法
2017/12/28 Python
python列表推导式操作解析
2019/11/26 Python
Gap中国官网:美式休闲风服饰
2017/02/05 全球购物
CHARLES & KEITH英国官网:新加坡时尚品牌
2018/07/04 全球购物
四川成都导游欢迎词
2014/01/18 职场文书
小学优秀班集体申报材料
2014/05/25 职场文书
水利水电专业自荐信
2014/07/08 职场文书
英文版辞职信
2015/02/28 职场文书
2015年勤工助学工作总结
2015/04/29 职场文书
借钱欠条怎么写
2015/07/03 职场文书
MySQL 发生同步延迟时Seconds_Behind_Master还为0的原因
2021/06/21 MySQL
ROS系统将python包编译为可执行文件的简单步骤
2021/07/25 Python