スポンサーリンク

群強化学習を実装してみる(PSO,ABCアルゴリズム) 後編

スポンサーリンク
スポンサーリンク
さて、後編です今回はいよいよPSO,ABCのアルゴリズムを実装してみたいと思います。 ちょっと先に言い訳しておくと、課題の締め切りに追われて半ばやけくそで実装したところもあるのであまり信用しすぎないでください。
スポンサーリンク

PSOアルゴリズム

PSOアルゴリズムというのは魚群や鳥群をモデルにしておりまして、端的にいうと沢山の粒子を適当な範囲にバラまいて、自分の位置を((自分のベスト位置)-(現在地))×定数×乱数+((群れのベスト位置)-(自分の現在地)) ×定数×乱数 でupdateするものです。 こちらに関してはQiitaにいい記事があったので参考にさせて頂きました。
#python

# -*- coding: utf-8 -*-
"""
Created on Mon Jan 14 05:24:15 2019

@author: pub
"""

import numpy as np
import random
import matplotlib.pyplot as plt

#初期位置、初期速度
def vector_init(N,dim,a,b):
    #dimは次元、Nは粒子数,aは初期値の下限、bは上限
    posi = (b-a)*np.random.rand(N,dim)+a
    vel =  (b-a)*np.random.rand(N,dim)+a
    return posi,vel
#位置情報の書き換え
def position_update(x_i,v_i):
    #x_iは個体の位置ベクトル
    new_x_i = x_i + v_i
    return new_x_i
#速度の書き換え
def vel_update(v_i,x_i,local_best_posi_i,glo_best_posi):
    w = 0.03
    c_1 =0.02
    c_2 =0.02
    rand1 = random.uniform(0,1)
    rand2 = random.uniform(0,1)
    new_v_i = w * v_i + c_1 * rand1 * (local_best_posi_i - x_i) + c_2 * rand2 * (glo_best_posi - x_i)
    return new_v_i

def best_init(dim,posi,N):
    local_best_score = []#各々の粒子のベストスコアを格納
    local_best_score.append(function(dim,posi[0]))
    local_best_posi = []
    local_best_posi.append(posi[0])
    glo_best_posi = posi[0]
    glo_best = function(dim,posi[0])
    for i in range(1,N):
        local_best_posi.append(posi[i])
        local_best_score.append(function(dim,posi[i]))
        if glo_best > local_best_score[i]:
            glo_best = local_best_score[i]
            glo_best_posi = posi[i]
    local_best_score = np.array(local_best_score)
    local_best_posi = np.array(local_best_posi)
    return local_best_score,glo_best,glo_best_posi,local_best_posi

#この辺適当ですけど多分mapとかでしたほうがいいです。 
def all_updater(dim,N,posi,vel,glo_best_posi,glo_best,local_best_score,local_best_posi):
    for i in range(N):
        posi[i]=position_update(posi[i],vel[i])
        vel[i]=vel_update(vel[i],posi[i],local_best_posi[i],glo_best_posi)
        new_score = function(dim,posi[i])
        if new_score < local_best_score[i]:
            local_best_score[i] = new_score
            local_best_posi[i] = posi[i]
            if new_score < glo_best:
                glo_best = new_score
                glo_best_posi = posi[i]
    return posi,vel,glo_best,local_best_score,glo_best_posi,local_best_posi
#評価関数
def function(dim,posi_i):
    #具体的な関数
    S = 0
    for j in range(dim):
        S +=posi_i[j]**2-10*np.cos(2*np.pi*posi_i[j])
    S+= 10*dim
    return S
       
def main():
    N = 10
    dim = 3
    steps  = 1000
    posi,vel = vector_init(N,dim,-5,5)
    local_best_score,glo_best,glo_best_posi,local_best_posi = best_init(dim,posi,N)
    x = []
    y = []
    for i in range(steps):
        posi,vel,glo_best,local_best_score,glo_best_posi,local_best_posi = all_updater(dim,N,posi,vel,glo_best_posi,glo_best,local_best_score,local_best_posi)
        if i%100 == 0:  #100回ごとにその時の粒子全体での最大値を記録する。
            x.append(i)
            y.append(glo_best)
    return posi,vel,glo_best,local_best_score,glo_best_posi,local_best_posi,x,y
なお、最適化の評価関数に関してはこちらが詳しいです。

ABCアルゴリズム

ABCアルゴリズムに関してはpythonでの実装例がネットになかったので 福井大学 大学院工学研究科 知能システム工学専攻 進化ロボット研究室 様の論文とを参考にして実装しました。 ABCアルゴリズムは蜂をいくつか放してその最適度に応じた確率で蜂の位置を更新し、長い間更新されなかった個体は改めて別の場所にランダムに放つことを繰り返すアルゴリズムです。
# -*- coding: utf-8 -*-
"""
Created on Fri Jan 18 11:24:03 2019

@author: pub
"""

import numpy as np
import matplotlib.pyplot as plt

def vector_init(N,dim,a,b):
    #dimは次元、Nは粒子数,aは初期値の下限、bは上限
    posi = (b-a)*np.random.rand(N,dim)+a
    C= np.zeros(N)
    return posi,C

def function(dim,posi_i):
    #具体的な関数
    S = 0
    for j in range(dim):
        S +=posi_i[j]**4-16*posi_i[j]**2+5*posi_i[j]
    return S
       

def Employ_Bee(dim,N,posi,C,index):     
    psy = 2 * np.random.rand() -1
    j = np.random.randint(0,dim)
    k = np.random.randint(0,N)
    result = 0
    while k==index:
        k = np.random.randint(0,N)  
    v_posi = np.copy(posi[index])
    v_posi[j] += psy*(posi[index][j]-posi[k][j])
    if function(dim,posi[index]) >= function(dim,v_posi):
        result = v_posi
        C[index] =0
    else:
        result = posi[index]
        C[index] += 0
    return result,C

def best_init(dim,posi,N):
    glo_best_posi = posi[0]
    glo_best = function(dim,posi[0])
    for i in range(1,N):
        if glo_best > function(dim,posi[i]):
            glo_best = function(dim,posi[i])
            glo_best_posi = posi[i]
    return glo_best,glo_best_posi

def Onlooker_Bee(N,posi,dim):
    p = []
    Sum_p = 0
    for i in range(N):
        if function(dim,posi[i]) >0:
            Sum_p += 1/1+(function(dim,posi[i]))
        else:
            Sum_p += (1+np.abs((function(dim,posi[i]))))
    for i in range(N):
        if function(dim,posi[i]) >0:
            p.append((1/1+(function(dim,posi[i])))/Sum_p)
        else:
            p.append((1+np.abs((function(dim,posi[i]))))/Sum_p)
    index = np.random.choice(N,p=p)
    return  index

def Scout_Bee(dim,N,sup,C,a,b,posi):
    for i in range(N):
        if C[i] > sup:
            posi[i] = (b-a)*np.random.rand(dim)+a
            C[i] = 0
    return posi,C

def greatest_update(dim,posi,N,glo_best,glo_best_posi):
    for i in range(N):
        if glo_best > function(dim,posi[i]):
            glo_best = function(dim,posi[i])
            glo_best_posi = posi[i]
    return glo_best,glo_best_posi

結論

三か月前に書いたコード久しぶりに見ると大変恥ずかしいですね。。精進します。。
エンジニア入門
スポンサーリンク
スポンサーリンク
adminをフォローする
スポンサーリンク
何もない部屋

コメント