【Python】 粒子群最適化法による最適化
粒子群最適化法による大域的最適化を行うクラスを実装します。粒子群最適化法は
- ハイパーパラメータが少ないので扱いやすい
- 単峰性が強い関数の最適化に向いている
といった特徴を持っています。最適化問題は慣例として"目隠しした登山家が山の頂上をどうにかして目指す"ことに例えられます。この慣例に従えば、粒子群最適化法は"目隠しした沢山の登山家を山の様々な場所に派遣し、各々が自分が今までに見つけた最も高い標高と、他の登山家が今までに見つけた最も高い標高を頼りに移動先を決めて頂上を目指す"ようなイメージの手法です。自分が持っている情報だけでなく、他の人の情報も使って移動先を決めるため、局所解から抜け出せる余地を持っています。粒子群最適化法では登山家を粒子として表現するのですが、まずは粒子をParticleというクラスで表現します。
import sys import numpy as np class Particle(object): """粒子群最適化法の粒子を表すクラス""" def __init__(self, f, position, velocity, maxs=None, mins=None): """ コンストラクタ @param f 最適化を行う関数 @param position 粒子の初期位置 @param velocity 粒子の初期速度 @param maxs 粒子が移動可能な位置最大値 @param mins 粒子が移動可能な位置最小値 """ self.__f = f self.__my_best_position = position self.__my_best_score = f(position) self.__my_position = position self.__my_velocity = velocity self.__maxs = maxs self.__mins = mins self.__WEIGHT_V = 0.8 self.__WEIGHT_ME = 1.0 self.__WEIGHT_US = 1.0 @property def score(self): return self.__my_best_score @property def position(self): return np.array(self.__my_best_position) def move(self, best_position): """ 粒子を移動させるメソッド @param best_position 関数の最小値を与える粒子の位置 """ # 粒子の位置を更新する self.__my_position += self.__my_velocity # 範囲外に出た粒子は範囲内に収める if (self.__maxs is not None): max_out_of_range_index = self.__my_position > self.__maxs self.__my_position[max_out_of_range_index] = self.__maxs[max_out_of_range_index] if (self.__mins is not None): min_out_of_range_index = self.__my_position < self.__mins self.__my_position[min_out_of_range_index] = self.__mins[min_out_of_range_index] # 評価値を計算する score = self.__f(self.__my_position) # 最良解を更新する if (score < self.__my_best_score): self.__my_best_position = self.__my_position self.__my_best_score = score # 速度を更新する item1 = self.__WEIGHT_V*self.__my_velocity random_me = np.random.rand(self.__my_position.size) item2 = self.__WEIGHT_ME*random_me*(self.__my_best_position - self.__my_position) random_us = np.random.rand(self.__my_position.size) item3 = self.__WEIGHT_US*random_us*(best_position - self.__my_position) self.__my_velocity = item1 + item2 + item3 # 範囲外に出た粒子の速度は0とする if (self.__maxs is not None): self.__my_velocity[max_out_of_range_index] = 0 if (self.__mins is not None): self.__my_velocity[min_out_of_range_index] = 0
次に、粒子を制御するクラスをParticleSwarmOptimizationとして作成します。このクラスは単に粒子群から最適解に最も近い粒子の位置を探し、粒子の位置を更新しているだけです。
import sys import Particle class ParticleSwarmOptimization(object): """粒子群最適化法により最適化を行うクラス""" def __init__(self, particles): """ コンストラクタ @param particles 粒子のリスト """ self.__particles = particles self.__best_score = sys.float_info.max for particle in self.__particles: if (particle.score < self.__best_score): self.__best_score = particle.score self.__best_position = particle.position @property def best_score(self): return self.__best_score @property def best_position(self): return self.__best_position def position(self, index): return [particle.position[index] for particle in self.__particles] def update(self): """ 粒子の位置を更新するメソッド """ for particle in self.__particles: particle.move(self.__best_position) for particle in self.__particles: if (particle.score < self.__best_score): self.__best_score = particle.score self.__best_position = particle.position
作成したParticleクラスとParticleSwarmOptimizationクラスを利用してのRosenbrock関数の最適化を行います。
import numpy as np import matplotlib.pyplot as plt from ParticleSwarmOptimization import ParticleSwarmOptimization from Particle import Particle if __name__ == '__main__': # 最適化する関数 def f(x): return 100.0*(x[1]-x[0]**2)**2 + (1.0-x[0])**2 # 変数が取り得る最大値 maxs = np.array([2.048, 2.048]) # 変数が取り得る最小値 mins = np.array([-2.048, -2.048]) # ばらまく粒子の個数 PARTICLE_COUNT = 100 # 粒子を作成する particles = [] for i in range(PARTICLE_COUNT): position = (np.random.rand(2) - 0.5)*4.0 velocity = (np.random.rand(2) - 0.5)/10.0 particle = Particle(f, position, velocity, maxs, mins) particles.append(particle) # ParticleSwarmOptimizationクラスの生成 pso = ParticleSwarmOptimization(particles) # 計算回数 ITERATION = 100 # 計算開始 for i in range(ITERATION): pso.update() if i == 0 or i == 9 or i == 49 or i == 99: plt.figure() plt.xlim([-2.048, 2.048]) plt.ylim([-2.048, 2.048]) plt.grid() plt.title('i = ' + str(i)) plt.scatter(pso.position(0), pso.position(1)) plt.show()
i=0, i=9, i=49, i=99の時の粒子の様子を図示します。計算が進むにつれて、ばらばらに散らばっていた粒子が最適解であるに集まる様子を確認できます。
- 作者: 古川正志,渡辺美知子,木下正博,鈴木育男,山本雅人,川上敬
- 出版社/メーカー: コロナ社
- 発売日: 2011/12/06
- メディア: 単行本
- この商品を含むブログ (1件) を見る
【Python】 フォルダ内の特定のファイルを取得する
C#のDirectory.GetFilesに相当するPythonの関数を探したのでそのメモ。
フォルダ内のファイル名一覧を取得する
import os files = os.listdir('Folder\\') for file_name in files: print(file_name)
実行結果例 a.txt b.txt c.txt d.docx
フォルダ内のテキストファイル名のみ取得する(方法1)
import os files = os.listdir('Folder\\') extension = '.txt' text_files = [file for file in files if extension in file] for file_name in text_files: print(file_name)
実行結果例 a.txt b.txt c.txt
フォルダ内のテキストファイル名のみ取得する(方法2)
import glob extension = '.txt' text_files = glob.glob('Folder\\*' + extension) for file_path in text_files: print(file_path)
実行結果例(中途半端にパスが付いてきます) Folder\a.txt Folder\b.txt Folder\c.txt
【Python】 二つのリストの対応関係を保ったままシャッフルする
リストx=[1,2,3,4]があったとして、このxと対応関係にあるリストy=[11,12,13,14]があったとします。xをシャッフルしたいのですが、この時yも対応関係を保ったままシャッフルしたいと考えています。例えばリストxがシャッフルによりx=[3,2,4,1]となった場合、yはy=[13,12,14,11]となって欲しい状況です。このやり方がStackOverflowに書かれていたのでメモします。
Numpy配列
python - Better way to shuffle two numpy arrays in unison - Stack Overflow
import numpy as np x = np.array([1,2,3,4]) y = np.array([11,12,13,14]) p = np.random.permutation(len(x)) x = x[p] y = y[p]
リスト
python - Shuffle two list at once with same order - Stack Overflow
import random x = [1,2,3,4] y = [11,12,13,14] p = list(zip(x, y)) random.shuffle(p) x, y = zip(*p)
【OpenCV】 画像から特定パターンを探す
OpenCVの復習が必要になったのでメモしておきます。
// 画像を読み込む UMat source; imread("scene.jpg", CV_LOAD_IMAGE_GRAYSCALE).copyTo(source); if (source.empty()) { throw runtime_error("Failed to open image"); } UMat parts; imread("parts.jpg", CV_LOAD_IMAGE_GRAYSCALE).copyTo(parts); if (parts.empty()) { throw runtime_error("Failed to open image"); } // テンプレートマッチングで場所を特定する UMat result; matchTemplate(source, parts, result, CV_TM_CCOEFF_NORMED); double maxValue; Point point1; minMaxLoc(result, NULL, &maxValue, NULL, &point1); // 特定した場所に四角を書き込む Point point2 = Point(point1.x + parts.cols, point1.y + parts.rows); UMat destination = source.clone(); Scalar color = Scalar(255, 0, 0); int thickness = 2; rectangle(destination, point1, point2, color, thickness); imshow("parts", parts); imshow("source", source); imshow("destination", destination);
さらに進化した画像処理ライブラリの定番 OpenCV 3基本プログラミング
- 作者: 北山洋幸
- 出版社/メーカー: カットシステム
- 発売日: 2016/04
- メディア: 単行本
- この商品を含むブログ (1件) を見る
【OpenCV】 画像の類似度を調べる
OpenCVの復習が必要になったのでメモしておきます。
// 画像を読み込む Mat source1; imread("lenna.jpg", CV_LOAD_IMAGE_GRAYSCALE).copyTo(source1); if (source1.empty()) { throw runtime_error("Failed to open image"); } Mat source2; imread("lenna.jpg", CV_LOAD_IMAGE_GRAYSCALE).copyTo(source2); if (source2.empty()) { throw runtime_error("Failed to open image"); } // 画像のヒストグラムを計算する int imageCount = 1; // 入力画像の枚数 int channelsToUse[] = { 0 }; // 0番目のチャネルを使う int dimention = 1; // ヒストグラムの次元数 int binCount = 256; // ヒストグラムのビンの数 int binCounts[] = { binCount }; float range[] = { 0, 256 }; // データの範囲は0~255 const float* histRange[] = { range }; Mat histogram1; calcHist(&source1, imageCount, channelsToUse, Mat(), histogram1, dimention, binCounts, histRange); Mat histogram2; calcHist(&source2, imageCount, channelsToUse, Mat(), histogram2, dimention, binCounts, histRange); // 類似度を調べる(同じ画像を読み込んだため1が出力される) double correlation = compareHist(histogram1, histogram2, CV_COMP_CORREL);
さらに進化した画像処理ライブラリの定番 OpenCV 3基本プログラミング
- 作者: 北山洋幸
- 出版社/メーカー: カットシステム
- 発売日: 2016/04
- メディア: 単行本
- この商品を含むブログ (1件) を見る
【OpenCV】 動画を表示する
OpenCVの復習が必要になったのでメモしておきます。
// 動画を読み込む VideoCapture capture = VideoCapture("movie.mp4"); if (!capture.isOpened()) { throw runtime_error("Failed to open movie"); } // 動画表示用のウインドウを作成する const string windowName = "movie"; namedWindow(windowName, CV_WINDOW_AUTOSIZE); // 動画を再生する UMat source; while (true) { // 1フレーム取り出す capture >> source; if (source.empty()) break; // 取り出したフレームをウインドウに表示する imshow(windowName, source); // フレームレートを30fpsに調整するための待ち時間 waitKey(33); } // 動画表示用のウインドウを破棄する destroyWindow(windowName);
さらに進化した画像処理ライブラリの定番 OpenCV 3基本プログラミング
- 作者: 北山洋幸
- 出版社/メーカー: カットシステム
- 発売日: 2016/04
- メディア: 単行本
- この商品を含むブログ (1件) を見る
【OpenCV】 パノラマ画像を作成する
OpenCVの復習が必要になったのでメモしておきます。
// 画像を読み込む UMat source1; imread("scene1.jpg", CV_LOAD_IMAGE_COLOR).copyTo(source1); if (source1.empty()) { throw runtime_error("Failed to open image"); } UMat source2; imread("scene2.jpg", CV_LOAD_IMAGE_COLOR).copyTo(source2); if (source2.empty()) { throw runtime_error("Failed to open image"); } vector<UMat> sources; sources.push_back(source1); sources.push_back(source2); // パノラマ画像を作成する Stitcher stitcher = Stitcher::createDefault(); UMat destination; Stitcher::Status status = stitcher.stitch(sources, destination); if (status != Stitcher::OK) { throw runtime_error("Failed to stitch images"); } imshow("source1", source1); imshow("source2", source2); imshow("destination", destination);
さらに進化した画像処理ライブラリの定番 OpenCV 3基本プログラミング
- 作者: 北山洋幸
- 出版社/メーカー: カットシステム
- 発売日: 2016/04
- メディア: 単行本
- この商品を含むブログ (1件) を見る