代码之家  ›  专栏  ›  技术社区  ›  wfgeo

pyswarms中的粒子位置未正确参数化

  •  0
  • wfgeo  · 技术社区  · 6 年前

    我很难为pyswarms设计一个适应度函数,它实际上会遍历粒子。我的设计基于这个(工作)示例代码:

    # import modules
    import numpy as np
    
    # create a parameterized version of the classic Rosenbrock unconstrained optimzation function
    def rosenbrock_with_args(x, a, b, c=0):
        f = (a - x[:, 0]) ** 2 + b * (x[:, 1] - x[:, 0] ** 2) ** 2 + c
        return f
    
    from pyswarms.single.global_best import GlobalBestPSO
    
    # instatiate the optimizer
    x_max = 10 * np.ones(2)
    x_min = -1 * x_max
    bounds = (x_min, x_max)
    options = {'c1': 0.5, 'c2': 0.3, 'w': 0.9}
    optimizer = GlobalBestPSO(n_particles=10, dimensions=2, options=options, bounds=bounds)
    
    # now run the optimization, pass a=1 and b=100 as a tuple assigned to args
    
    cost, pos = optimizer.optimize(rosenbrock_with_args, 1000, a=1, b=100, c=0)
    
    kwargs={"a": 1.0, "b": 100.0, 'c':0}
    

    似乎通过写作 x[:, 0] x[:, 1] ,以某种方式为优化函数参数化粒子位置矩阵。例如,执行 x[:,0] 在调试器中返回:

    array([ 9.19955426, -5.31471451, -2.28507312, -2.53652044, -6.29916204, -8.44170591, 7.80464884, -6.42048159, 9.77440842, -9.06991295])

    现在,跳到我的代码(一个片段),我有:

    def optimize_eps_and_mp(x):
    
        clusterer = DBSCAN(eps=x[:, 0], min_samples=x[:, 1], metric="precomputed")
        clusterer.fit(distance_matrix)
        clusters = pd.DataFrame.from_dict({index_to_gid[i[0]]: [i[1]] for i in enumerate(clusterer.labels_)},
                                          orient="index", columns=["cluster"])
        settlements_clustered = settlements.join(clusters)
        cluster_pops = settlements_clustered.loc[settlements_clustered["cluster"] >= 0].groupby(["cluster"]).sum()["pop_sum"].to_list()
        print()
    
        return 1
    
    
    options = {'c1': 0.5, 'c2': 0.3, 'w':0.9}
    max_bound = [1000, 10]
    min_bound = [1, 2]
    bounds = (min_bound, max_bound)
    n_particles = 10
    
    optimizer = ps.single.GlobalBestPSO(n_particles=n_particles, dimensions=2, options=options, bounds=bounds)
    cost, pos = optimizer.optimize(optimize_eps_and_mp, iters=1000)
    

    (变量 distance_matrix settlements 在代码的前面定义的,但是在这行中它失败了 clusterer = DBSCAN(eps=x[:, 0], min_samples=x[:, 1], metric="precomputed") 所以它们并不相关。而且,我知道它总是回来 1 ,我只是想让它在完成函数之前运行而不出错)

    x[:,0] 在调试器中,它返回:

    array([-4.54925788, 3.94338766, 0.97085618, 9.44128746, -2.1932764 , 9.24640763, 9.18286758, -8.91052863, 0.637599 , -2.28228841])

    因此,在结构上与工作示例相同。但它失败了 因为它传递了 x[:,0] DBSCAN 函数,而不是像工作示例中那样参数化它。

    这些例子之间有什么区别,我只是没有看到?

    我还试着从工作示例中粘贴fitness函数( rosenbrock_with_args )在我的代码和优化,而不是,以消除任何可能性,我有我的实现设置是不正确的。然后,解会像正常情况一样收敛,所以我完全不知道为什么它不适用于我的函数( optimize_eps_and_mp )

    我得到的确切stacktrace是指dbscan算法中的一个错误,我假设是由于它以某种方式传递了整个粒子群值集,而不是单个值:

    pyswarms.single.global_best:   0%|          |0/1000Traceback (most recent call last):
      File "C:/FILES/boates/work_local/_code/warping-pso-dbscan/optimize_eps_and_mp.py", line 63, in <module>
        cost, pos = optimizer.optimize(optimize_eps_and_mp, iters=1000)
      File "C:\FILES\boates\Anaconda\envs\warping_pso_dbscan\lib\site-packages\pyswarms\single\global_best.py", line 184, in optimize
        self.swarm.current_cost = compute_objective_function(self.swarm, objective_func, pool=pool, **kwargs)
      File "C:\FILES\boates\Anaconda\envs\warping_pso_dbscan\lib\site-packages\pyswarms\backend\operators.py", line 239, in compute_objective_function
        return objective_func(swarm.position, **kwargs)
      File "C:/FILES/boates/work_local/_code/warping-pso-dbscan/optimize_eps_and_mp.py", line 38, in optimize_eps_and_mp
        clusterer.fit(distance_matrix)
      File "C:\FILES\boates\Anaconda\envs\warping_pso_dbscan\lib\site-packages\sklearn\cluster\dbscan_.py", line 351, in fit
        **self.get_params())
      File "C:\FILES\boates\Anaconda\envs\warping_pso_dbscan\lib\site-packages\sklearn\cluster\dbscan_.py", line 139, in dbscan
        if not eps > 0.0:
    ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
    pyswarms.single.global_best:   0%|          |0/1000
    
    0 回复  |  直到 6 年前
        1
  •  2
  •   AlexisBRENON    6 年前

    TL;博士

    粒子群优化使用批处理。

    错误消息解释

    下面是错误消息的有趣部分:

      [...]
      File "C:\FILES\boates\Anaconda\envs\warping_pso_dbscan\lib\site-packages\sklearn\cluster\dbscan_.py", line 139, in dbscan
        if not eps > 0.0:
    ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
    

    当您尝试将数组用作条件时,将显示此消息。 正如信息所解释的,什么是 truth value 像这样的阵列 [True, False] . 你必须使用如下函数 all() any() 将数组转换为单个布尔值。

    为什么会这样? eps 不是一个数组 .

    DBSCAN class , 参数 min_samples 你把数组传给他们。

    clusterer = DBSCAN(eps=x[:, 0], min_samples=x[:, 1], metric="precomputed")
    

    实例比较

    你问为什么你的代码和 rosenbrock_with_args 功能。 这是因为它执行的操作能够很好地处理数组。 你给它一个二维数组 x (一批颗粒)形状 [10, 2] (10个尺寸为2的微粒)和 a, b, c 鳞片。 [10] ,这是每个粒子的成本值。

    你的新 optimize_eps_and_mp 但是,函数尝试对不受支持的数组执行某些操作。 特别是,使用数组的一维作为 每股收益 数据库扫描 它需要一个标量。

    为了让它工作,你应该自己处理批处理,引用许多 物体:

    for row in x:
      clusterer = DBSCAN(eps=row[0], min_value=row[1], [...])
    

    分布式执行

    You said

    这个 pyswarms 库应该独立运行它(目标函数)多次(针对群中的每个粒子)并评估它们的结果,它通过将函数同时分配给多组输入来实现。

    pyswarm 实际上可以将你的群执行与 n_processes 的论点 optimize 功能。 在这种情况下,您的函数在不同的进程中被多次调用,但仍然使用数组作为输入。 在你的例子中,有10个微粒,2个维度和 作为 None (默认值),您的 输入是有形状的 . 如果你设置 n_过程 输入将具有形状 [5, 2] . 最后如果你确定 n_过程 到10,你的 输入将具有形状 [1, 2] . 无论哪种情况,你都必须“取消滚动”你的粒子群 数据库扫描 实例。

    import pyswarms as ps
    
    
    def foo(x):
        print(x.shape)
        return x[:,0]
    
    
    if __name__ == "__main__":
        options = {'c1': 0.5, 'c2': 0.3, 'w': 0.9}
        max_bound = [1000, 10]
        min_bound = [1, 2]
        bounds = (min_bound, max_bound)
        n_particles = 10
    
        optimizer = ps.single.GlobalBestPSO(n_particles=n_particles, dimensions=2, options=options, bounds=bounds)
        for n_processes in [None, 1, 2, 10]:
            print("\nParallelizing on {} processes.".format(n_processes))
            optimizer.optimize(foo, iters=1, n_processes=n_processes)
    
    Parallelizing on None processes.
    (10, 2)
    
    Parallelizing on 1 processes.
    (10, 2)
    
    Parallelizing on 2 processes.
    (5, 2)
    (5, 2)
    
    Parallelizing on 10 processes.
    (1, 2)
    (1, 2)
    (1, 2)
    (1, 2)
    (1, 2)
    (1, 2)
    (1, 2)
    (1, 2)
    (1, 2)
    (1, 2)
    

    下面是一个完整的例子 数据库扫描 对你来说。

    def optimize_eps_and_mp(x):
        num_particles = x.shape[0]
        costs = np.zeros([num_particles])
        print("Particles swarm", x)
    
        for idx, particle in enumerate(x):
            print("Particle", particle)
            clusterer = DBSCAN(eps=x[0], min_samples=x[1], metric="precomputed")
            clusterer.fit(distance_matrix)
            clusters = pd.DataFrame.from_dict({index_to_gid[i[0]]: [i[1]] for i in enumerate(clusterer.labels_)},
                                          orient="index", columns=["cluster"])
            settlements_clustered = settlements.join(clusters)
            cluster_pops = settlements_clustered.loc[settlements_clustered["cluster"] >= 0].groupby(["cluster"]).sum()["pop_sum"].to_list()
    
            cost = 1  # Update this to compute cost value of the current particle
            costs[idx] = cost
    
        return costs