aiaccelドキュメント
本ソフトウェアは、AI Bridging Cloud Infrastructure (ABCI)`_ のためのハイパーパラメータ最適化ライブラリです。 ディープラーニングやマルチエージェントシミュレーションなどのAI技術に関連するハイパーパラメータ最適化を解決します。 現在、ランダムサーチ、グリッドサーチ、ソボルシーケンス、ネルダーミード法、TPEの5つの最適化アルゴリズムに対応しています。
aiaccel概要
AI橋渡しクラウドABCI向けハイパーパラメータ最適化ライブラリ。 ランダムサーチ、グリッドサーチ、Sobol列、Nelder-Mead法、およびベイズ最適化法 (TPE)をサポートしています。
クイックインストール
本ソフトウェアは下記コマンドでインストールできます。
pip install git+https://github.com/aistairc/aiaccel.git
実行例
ローカル環境で実行する場合
(オプション) Virtualenvをインストールし、仮想環境を作成します。
> pip install virtualenv > virtualenv venv > source venv/bin/activate
aiaccel
をインストールしますpip install git+https://github.com/aistairc/aiaccel.git
ワークスペースを作成し、sphereディレクトリをコピーします。
> mkdir your_workspace_directory > cd your_workspace_directory > git clone https://github.com/aistairc/aiaccel.git > cp -R ./aiaccel/examples . > cd examples > ls sphere > cd sphere > ls config.yaml job_script_preamble.sh user.py
パラメータ最適化を実行します。
> python -m aiaccel.start --config config.yaml
Tips: ワークスペースは
--clean
を付加することで実行前に初期化できます。> python -m aiaccel.start --config config.yaml --clean
結果を確認する。
> ls ./work abci_output alive hp lock log result runner state verification > cat ./work/result/final_result.result
設定を変更したい場合は、config.yamlファイルを編集してください。
vi config.yaml
ABCI上で実行する
まず、ABCIユーザーズガイドに従って、pythonの環境を構築してください。
module load python/3.8/3.8.13 python3 -m venv optenv source work/bin/activate
config.yamlのresourceをABCIに変更します。
resource: type: "ABCI" num_node: 4
ワークスペースを用意します.ここからの作業は、ローカル環境で実行する場合の2および3と同じです。
実行
> python -m aiaccel.start --config config.yaml
実行中のジョブを確認したい場合は、ABCIユーザーズガイドを参照してください。
インストールガイド (WIP)
Linux 向けインストールガイド
Python-venv による仮想環境の作成
venv 環境での使用を推奨いたします. 仮想環境を作成するには,下記のコマンドを実行します.
python3 -m venv optenv
ここでは仮想環境の名前を「optenv」とし,以後も当仮想環境を「optenv」と表記します. 仮想環境の名前は任意の名前を設定できます.
アクティベート
仮想環境を利用するには,下記のコマンドを実行します.
source optenv/bin/activate
以後の作業はアクティベート済みのものとして進めます.
(参考)仮想環境の終了
仮想環境を終了するには,下記のコマンドを実行します.
deactivate
インストール
Note
事前に pip をアップグレードすることを推奨いたします.
python3 -m pip install --upgrade pip
aiaccel は下記コマンドでインストールできます.
python3 -m pip install git+https://github.com/aistairc/aiaccel.git
aiaccel がインポートできることを確認します.
python3
import aiaccel
(参考)ローカルからのインストール
aiaccel をダウンロードし,ローカルからインストールすることもできます.
まず,aiaccel をダウンロードします.
git clone https://github.com/aistairc/aiaccel.git
ダウンロード完了後,aiaccel フォルダに移動します.
cd aiaccel
依存環境をインストールします.
python3 -m pip install -r requirements.txt
setup.py を実行し,aiaccel をインストールします.
python3 setup.py install
ABCI 向けインストールガイド
Python 環境の構築
まず,ABCIユーザーズガイドに従って,python の環境を構築してください.
module load gcc/11.2.0
module load python/3.8/3.8.13
python3 -m venv optenv
source optenv/bin/activate
Python-venv による仮想環境の作成
venv 環境での使用を推奨いたします. 仮想環境を作成するには,下記のコマンドを実行します.
python3 -m venv optenv
ここでは仮想環境の名前を「optenv」とし,以後も当仮想環境を「optenv」と表記します. 仮想環境の名前は任意の名前を設定できます.
アクティベート
仮想環境を利用するには,下記のコマンドを実行します.
source optenv/bin/activate
以後の作業はアクティベート済みのものとして進めます.
(参考)仮想環境の終了
仮想環境を終了するには,下記のコマンドを実行します.
deactivate
インストール
Note
事前に pip をアップグレードすることを推奨いたします.
python3 -m pip install --upgrade pip
aiaccel は下記コマンドでインストールできます.
python3 -m pip install git+https://github.com/aistairc/aiaccel.git
aiaccel がインポートできることを確認します.
python3
import aiaccel
(参考)ローカルからのインストール
aiaccel をダウンロードし,ローカルからインストールすることもできます.
まず,aiaccel をダウンロードします.
git clone https://github.com/aistairc/aiaccel.git
ダウンロード完了後,aiaccel フォルダに移動します.
cd aiaccel
依存環境をインストールします.
python3 -m pip install -r requirements.txt
setup.py を実行し,aiaccel をインストールします.
python3 setup.py install
Windows 向けインストールガイド
準備1: Git のインストール
GitHub 経由で aiaccel をインストールする場合,git がインストールされている必要があります. あらかじめインストールしてください.
準備2: Execution Polisy の設定
PowerShell を使用して仮想環境を作る場合,セキュリティ設定によって仮想環境をアクティベートするスクリプトが実行できないことがあります. 以下の手順でセキュリティ設定を変更することが可能ですが,セキュリティリスクが上がることに十分注意してください.詳細はこちらをご確認ください.
以下のコマンドを実行して,PowerShell の設定を確認します.
> Get-ExecutionPolicy
Restricted
この例のように Restricted と表示された場合,以下のコマンドを実行し,設定を変更します.
> Set-ExecutionPolicy RemoteSigned
実行後,コマンド Get-ExecutionPolicy
を実行して,RemoteSigned
と表示されれば設定完了です.
> Get-ExecutionPolicy
RemoteSigned
使用中の PowerShell ウィンドウのみに変更を適用したい場合,以下のようにオプションを追加して設定します.
> Set-ExecutionPolicy RemoteSigned -Scope Process
Python-venv による仮想環境の作成
venv 環境での使用を推奨いたします. 仮想環境を作成するには,下記のコマンドを実行します.
> python -m venv optenv
ここでは仮想環境の名前を「optenv」とし,以後も当仮想環境を「optenv」と表記します. 仮想環境の名前は任意の名前を設定できます.
アクティベート
仮想環境を利用するには,下記のコマンドを実行します.
> .\optenv\Scripts\activate
以後の作業はアクティベート済みのものとして進めます.
(参考)仮想環境の終了
仮想環境を終了するには,下記のコマンドを実行します.
deactivate
インストール
Note
事前に pip をアップグレードすることを推奨いたします.
> python -m pip install --upgrade pip
以下のコマンドを実行します.
> python -m pip install git+https://github.com/aistairc/aiaccel.git
(参考)ローカルからのインストール
aiaccel をダウンロードし,ローカルからインストールすることもできます.
まず,aiaccel をダウンロードします.
> git clone https://github.com/aistairc/aiaccel.git
ダウンロード完了後,aiaccel フォルダに移動します.
> cd aiaccel
依存環境をインストールします.
> python -m pip install -r requirements.txt
setup.py を実行し,aiaccel をインストールします.
> python setup.py install
aiaccel がインポートできることを確認します.
> python
>>> import aiaccel
>>>
MacOS 向けインストールガイド (WIP)
作業ファイルの準備
ワークスペースを作成し,移動します.
> mkdir your_workspace_directory
> cd your_workspace_directory
リポジトリのクローンを取得し,ディレクトリ examles のコピーを作成します.
> git clone https://github.com/aistairc/aiaccel.git
> cp -R your_workspace_directory/aiaccel/examples .
examples 下には以下のフォルダが存在します.
benchmark
resnet50_cifar10
schwefel
sphere
styblinski-tang
wrapper_sample
使用するフォルダに移動して設定を行い, aiaccel を実行します. 例えば sphere に移動するには,以下のようにします.
> cd examples/sphere
ランダムオプティマイザのローカル環境での実行例
ここでは,ランダムオプティマイザをローカルで実行する方法を説明します. 例として,ベンチマーク関数の一つである sphere の最適化を行います.
以下の説明では aiaccel/examples/sphere に保存されているファイルを編集して使用します.
1. ファイル構成
config.yaml
最適化およびソフトウェアの設定ファイルです.
user.py
与えられたパラメータからベンチマーク関数 sphere の値を計算し,aiaccel の Storage に保存するユーザプログラムです.
2. ファイル作成手順
config.yaml の作成
generic
generic:
workspace: "./work"
job_command: "python user.py"
batch_job_timeout: 600
workspace - aiaccel の実行に必要な一時ファイルを保存するディレクトリを指定します.
job_command - ユーザープログラムを実行するためのコマンドです.
batch_job_timeout - ジョブのタイムアウト時間を設定します.[単位: 秒]
Note
Windows では,仮想環境の python で実行するためには job_command
の欄を "optenv/Scripts/python.exe"
のように設定する必要があります.
resource
resource:
type: "local"
num_node: 4
type - 実行環境を指定します.ローカル環境で実行するためには
"local"
で設定します.num_node - 使用するノード数を指定します.
optimize
optimize:
search_algorithm: 'aiaccel.optimizer.RandomOptimizer'
goal: "minimize"
trial_number: 100
rand_seed: 42
parameters:
-
name: "x1"
type: "uniform_float"
lower: -5.0
upper: 5.0
initial: -5.0
-
name: "x2"
type: "uniform_float"
lower: -5.0
upper: 5.0
initial: -5.0
-
name: "x3"
type: "uniform_float"
lower: -5.0
upper: 5.0
initial: -5.0
-
name: "x4"
type: "uniform_float"
lower: -5.0
upper: 5.0
initial: -5.0
-
name: "x5"
type: "uniform_float"
lower: -5.0
upper: 5.0
search_algorithm - 最適化アルゴリズムを設定します.この例ではランダムオプティマイザを設定しています.
goal - 最適化の方向を設定します.
関数 sphere を最小化することが目的であるため,
"minimize"
を設定しています.
trial_number - 試行回数を設定します.
rand_seed - 乱数の生成に使用するシードを設定します.
parameters - ハイパパラメータの各種項目を設定します.ここでは 5 次元の spehre の最適化を行うため,5 種類のパラメータを用意しています.5 つのパラメータに対して,以下の項目をそれぞれ設定する必要があります.パラメータの範囲や初期値を,全て同じにする必要はありません.
name - ハイパパラメータの名前を設定します.
type - ハイパパラメータのデータ型を設定します.ここでは例として
"uniform_float"
に設定していますが,ランダムオプティマイザでは,以下の 4 つから選択することができます.uniform_float - 浮動小数点数
uniform_int - 整数
categorical - カテゴリカル変数
ordinal - オーディナル変数
lower / upper - ハイパパラメータ最小値 / 最大値を設定します.
initial - ハイパパラメータの初期値を設定します.上の例の
"x5"
の場合のようにinitial
の項目がない場合,実行時にランダムな初期値が自動で設定されます.
user.py の作成
user.py
は以下のように記述します.
import numpy as np
from aiaccel.util import aiaccel
def main(p):
x = np.array([p["x1"], p["x2"], p["x3"], p["x4"], p["x5"]])
y = np.sum(x ** 2)
return float(y)
if __name__ == "__main__":
run = aiaccel.Run()
run.execute_and_report(main)
モジュール
import numpy as np
from aiaccel.util import aiaccel
必要なモジュールをインポートします.
numpy - 関数 sphere を計算するために使用します.
aiaccel.util.aiaccel - ユーザープログラム内で定義される関数
main()
と aiaccelとの間のインターフェイスを提供します.
main
def main(p):
x = np.array([p["x1"], p["x2"], p["x3"], p["x4"], p["x5"]])
y = np.sum(x ** 2)
return float(y)
最適化対象の関数で,aiaccel はこの関数の return
値を最小化します.
引数にハイパパラメータの辞書型オブジェクトを取り,ハイパパラメータの二乗和を返却します.
実行部分
if __name__ == "__main__":
run = aiaccel.Run()
run.execute_and_report(main)
aiaccel から関数 main()
にハイパパラメータを渡し,main()
の返却値を Storage に保存します.
run
はそのインターフェイスとなるインスタンスです.
メソッド execute_and_report()
の内部で main()
が値を計算し,Storage に計算結果が保存されます.
3. 実行
作成した config.yaml と user.py が保存されているディレクトリに移動し,下記のコマンドで aiaccel を起動してください.
> aiaccel-start --config config.yaml --clean
コマンドラインオプション引数
--config
- 設定ファイルを読み込むためのオプション引数です.読み込むコンフィグのパスを記述します.--clean
- aiaccel の起動ディレクトリ内に config.yaml の workspace で指定したディレクトリが存在する場合,削除してから実行するためのオプション引数です.
4. 結果の確認
aiaccel の正常終了後,最適化の結果は以下の 2 か所に保存されます.
./work/results.csv
./work/result/{trial_id}.hp
ここで,./work はコンフィグファイルの workspace に設定したディレクトリです.
results.csv には,それぞれの試行でのパラメータの値と,そのパラメータに対する目的関数の値が保存されています. result/{trial_id}.hp は,{trial_id} 回目の試行のパラメータと関数の値が YAML 形式で保存されています. さらに,同じフォルダには final_result.result というファイルが作成され,全試行中で最良のパラメータと目的関数の値が YAML 形式で保存されます.
上で実行した最適化の結果は以下のようになります.
ハイパパラメータ
x1
x2
x3
x4
x5
評価値
sphere
最適化手法
Random
結果比較
デフォルトパラメータ
x1 = -5.0 x2 = -5.0 x3 = -5.0 x4 = -5.0 x5 = -1.254598811526375 (自動生成) sphere = 101.57401817788339
最適化結果
x1 = -1.9575775704046228 x2 = 0.24756431632237863 x3 = -0.6805498135788426 x4 = -2.0877085980195806 x5 = 1.118528947223795 sphere = 9.966180279652084
グリッドオプティマイザのローカル環境での実行例
ここでは,グリッドオプティマイザをローカルで実行する方法を説明します. 例として,ベンチマーク関数の一つである Schwefel の最適化を行います.
以下の説明では aiaccel/examples/schwefel に保存されているファイルを編集して使用します.
1. ファイル構成
config.yaml
最適化およびソフトウェアの設定ファイルです.
user.py
与えられたパラメータからベンチマーク関数 Schwefel の値を計算し,aiaccel の Storage に保存するユーザプログラムです.
2. ファイル作成手順
config.yaml の作成
generic
generic:
workspace: "./work"
job_command: "python user.py"
batch_job_timeout: 600
workspace - aiaccel の実行に必要な一時ファイルを保存するディレクトリを指定します.
job_command - ユーザープログラムを実行するためのコマンドです.
batch_job_timeout - ジョブのタイムアウト時間を設定します.[単位: 秒]
Note
Windows では,仮想環境の python で実行するためには job_command
の欄を "optenv/Scripts/python.exe"
のように設定する必要があります.
resource
resource:
type: "local"
num_node: 4
type - 実行環境を指定します.ローカル環境で実行するためには
"local"
で設定します.num_node - 使用するノード数を指定します.
optimize
optimize:
search_algorithm: 'aiaccel.optimizer.GridOptimizer'
goal: "minimize"
trial_number: 30
rand_seed: 42
parameters:
-
name: "x1"
type: "uniform_float"
lower: -500.0
upper: 500.0
step: 10
log: false
base: 10
-
name: "x2"
type: "uniform_float"
lower: -500.0
upper: 500.0
step: 10
log: false
base: 10
-
name: "x3"
type: "uniform_float"
lower: -500.0
upper: 500.0
step: 10
log: false
base: 10
-
name: "x4"
type: "uniform_float"
lower: -500.0
upper: 500.0
step: 10
log: false
base: 10
-
name: "x5"
type: "uniform_float"
lower: -500.0
upper: 500.0
step: 10
log: false
base: 10
search_algorithm - 最適化アルゴリズムを設定します.この例ではグリッドオプティマイザを設定しています.
goal - 最適化の方向を設定します.
関数 Schwefel を最小化することが目的であるため,
"minimize"
を設定しています.
trial_number - 試行回数を設定します.
rand_seed - 乱数の生成に使用するシードを設定します.
parameters - ハイパパラメータの各種項目を設定します.ここでは 5 次元の Schwefel の最適化を行うため,5 種類のパラメータを用意しています.5 つのパラメータに対して,以下の項目をそれぞれ設定する必要があります.パラメータの範囲や初期値を,全て同じにする必要はありません.
name - ハイパパラメータの名前を設定します.
type - ハイパパラメータのデータ型を設定します.ここでは例として
"uniform_float"
に設定していますが,グリッドオプティマイザでは,以下の 4 つから選択することができます.uniform_float - 浮動小数点数
uniform_int - 整数
categorical - カテゴリカル変数
ordinal - オーディナル変数
lower / upper - ハイパパラメータ最小値 / 最大値を設定します.
step - パラメータ空間を分割するステップサイズを設定します.
log - 対数スケールでパラメータ空間を分割するかを
true
またはfalse
で設定します.base - パラメータ空間を対数スケールで分割する際に使用する基数を設定します.対数スケールでパラメータ空間を分割しない場合は使用されませんが,必ず値を設定してください.設定されていない場合エラーになりまず.
注意: グリッドオプティマイザを使用する際は,パラメータの初期値を設定することができません.
user.py の作成
user.py
は以下のように記述します.
import numpy as np
from aiaccel.util import aiaccel
def main(p):
x = np.array([p["x1"], p["x2"], p["x3"], p["x4"], p["x5"]])
y = -np.sum(x * np.sin(np.sqrt(np.abs(x))))
return float(y)
if __name__ == "__main__":
run = aiaccel.Run()
run.execute_and_report(main)
モジュール
import numpy as np
from aiaccel.util import aiaccel
必要なモジュールをインポートします.
numpy - 関数 Schwefel を計算するために使用します.
aiaccel.util.aiaccel - ユーザープログラム内で定義される関数
main()
と aiaccelとの間のインターフェイスを提供します.
main
def main(p):
x = np.array([p["x1"], p["x2"], p["x3"], p["x4"], p["x5"]])
y = -np.sum(x * np.sin(np.sqrt(np.abs(x))))
return float(y)
最適化対象の関数で,aiaccel はこの関数の return
値を最小化します.
引数にハイパパラメータの辞書型オブジェクトを取ります,
この例では,関数 Schwefel の値を計算し,返却します.
実行部分
if __name__ == "__main__":
run = aiaccel.Run()
run.execute_and_report(main)
aiaccel から関数 main()
にハイパパラメータを渡し,main()
の返却値を Storage に保存します.
run
はそのインターフェイスとなるインスタンスです.
メソッド execute_and_report()
の内部で main()
が値を計算し,Storage に計算結果が保存されます.
3. 実行
作成した config.yaml と user.py が保存されているディレクトリに移動し,下記のコマンドで aiaccel を起動してください.
> aiaccel-start --config config.yaml --clean
コマンドラインオプション引数
--config
- 設定ファイルを読み込むためのオプション引数です.読み込むコンフィグのパスを記述します.--clean
- aiaccel の起動ディレクトリ内に config.yaml の workspace で指定したディレクトリが存在する場合,削除してから実行するためのオプション引数です.
4. 結果の確認
aiaccel の正常終了後,最適化の結果は以下の 2 か所に保存されます.
./work/results.csv
./work/result/{trial_id}.hp
ここで,./work はコンフィグファイルの workspace に設定したディレクトリです.
results.csv には,それぞれの試行でのパラメータの値と,そのパラメータに対する目的関数の値が保存されています. result/{trial_id}.hp は,{trial_id} 回目の試行のパラメータと関数の値が YAML 形式で保存されています. さらに,同じフォルダには final_result.result というファイルが作成され,全試行中で最良のパラメータと目的関数の値が YAML 形式で保存されます.
上で実行した最適化の結果は以下のようになります.
ハイパパラメータ
x1
x2
x3
x4
x5
評価値
Schwefel
最適化手法
Grid
結果比較
最適化結果
x1 = -500.0 x2 = -500.0 x3 = -500.0 x4 = -500.0 x5 = -300.0 results = -1022.0952317469887
TPE オプティマイザのローカル環境 (python_local モード) での実行例
ここでは,TPE オプティマイザを python_local
モードを用いてローカルで実行する方法を説明します.
例として,ベンチマーク関数の一つである Styblinski-Tang の最適化を行います.
以下の説明では aiaccel/examples/styblinski-tang に保存されているファイルを編集して使用します.
1. ファイル構成
config.yaml
最適化およびソフトウェアの設定ファイルです.
user.py
与えられたパラメータからベンチマーク関数 Styblinski-Tang の値を計算し,aiaccel の Storage に保存するユーザプログラムです.
2. ファイル作成手順
config.yaml の作成
generic
generic:
workspace: "./work"
job_command: "python user.py"
python_file: "./user.py"
function: "main"
batch_job_timeout: 600
workspace - aiaccel の実行に必要な一時ファイルを保存するディレクトリを設定します.
job_command - ユーザープログラムを実行するためのコマンドです.
python_local
モードでは使用されませんが,実行時に読み込むため,記述します.python_file - python で実装された最適化対象の関数のファイルパスを設定します.
function - 最適化対象の関数名を設定します.
batch_job_timeout - ジョブのタイムアウト時間を設定します.[単位: 秒]
resource
resource:
type: "python_local"
num_node: 4
type - 実行環境を指定します.
python_local
モードを使用してローカルで実行するためには"python_local"
と設定します.num_node - 使用するノード数を指定します.
optimize
optimize:
search_algorithm: 'aiaccel.optimizer.TpeOptimizer'
goal: "minimize"
trial_number: 30
rand_seed: 42
parameters:
-
name: "x1"
type: "uniform_float"
lower: -5.0
upper: 5.0
initial: 0.0
-
name: "x2"
type: "uniform_float"
lower: -5.0
upper: 5.0
initial: 0.0
-
name: "x3"
type: "uniform_float"
lower: -5.0
upper: 5.0
initial: 0.0
-
name: "x4"
type: "uniform_float"
lower: -5.0
upper: 5.0
initial: 0.0
-
name: "x5"
type: "uniform_float"
lower: -5.0
upper: 5.0
initial: 0.0
search_algorithm - 最適化アルゴリズムを設定します.この例では TPE オプティマイザを設定しています.
goal - 最適化の方向を設定します.
ベンチマーク関数 Styblinski-Tang を最小化することが目的であるため,
"minimize"
を設定しています.
trial_number - 試行回数を設定します.
rand_seed - 乱数の生成に使用するシードを設定します.
parameters - ハイパパラメータの各種項目を設定します.ここでは 5 次元の Styblinski-Tang の最適化を行うため,5 種類のパラメータを用意しています.5 つのパラメータに対して,以下の項目をそれぞれ設定する必要があります.パラメータの範囲や初期値を,全て同じにする必要はありません.
name - ハイパパラメータの名前を設定します.
type - ハイパパラメータのデータ型を設定します.ここでは例として
"uniform_float"
に設定していますが,TPE オプティマイザでは,以下の 3 つのタイプから選択することができます.uniform_float - 浮動小数点数
uniform_int - 整数
categorical - カテゴリカル変数
lower / upper - ハイパパラメータ最小値 / 最大値を設定します.
initial - ハイパパラメータの初期値を設定します.
user.py の作成
user.py
は以下のように記述します.
import numpy as np
def main(p):
x = np.array([p["x1"], p["x2"], p["x3"], p["x4"], p["x5"]])
t1 = np.sum(x ** 4)
t2 = -16 * np.sum(x ** 2)
t3 = 5 * np.sum(x)
y = 0.5 * (t1 + t2 + t3)
return float(y)
モジュール
import numpy as np
必要なモジュールをインポートします.
numpy - 関数 Styblinski-Tang を計算するために使用します.
main
def main(p):
x = np.array([p["x1"], p["x2"], p["x3"], p["x4"], p["x5"]])
t1 = np.sum(x ** 4)
t2 = -16 * np.sum(x ** 2)
t3 = 5 * np.sum(x)
y = 0.5 * (t1 + t2 + t3)
return float(y)
最適化対象の関数で,aiaccel はこの関数の return
値を最小化します.
引数にハイパパラメータの辞書型オブジェクトを取ります.
この例では,与えられたパラメータに対してベンチマーク関数 Styblinski-Tang の値を計算し,返却します.
注意
python_local
モードで実行する場合,aiaccel は user.py から main()
をインポートして使用します.
そのため,local
や abci
の場合のように,user.py の内部で aiaccel.util.aiaccel.Run
などを用いて関数の実行と Storage への結果の保存を行う必要はありません.
3. 実行
作成した config.yaml と user.py が保存されているディレクトリに移動し,下記のコマンドで aiaccel を起動してください.
> aiaccel-start --config config.yaml --clean
コマンドラインオプション引数
--config
- 設定ファイルを読み込むためのオプション引数です.読み込むコンフィグのパスを記述します.--clean
- aiaccel の起動ディレクトリ内に config.yaml の workspace で指定したディレクトリが存在する場合,削除してから実行するためのオプション引数です.
4. 結果の確認
aiaccel の正常終了後,最適化の結果は以下の 2 か所に保存されます.
./work/results.csv
./work/result/{trial_id}.hp
ここで,./work はコンフィグファイルの workspace に設定したディレクトリです.
results.csv には,それぞれの試行でのパラメータの値と,そのパラメータに対する目的関数の値が保存されています. result/{trial_id}.hp は,{trial_id} 回目の試行のパラメータと関数の値が YAML 形式で保存されています. さらに,同じフォルダには final_result.result というファイルが作成され,全試行中で最良のパラメータと目的関数の値が YAML 形式で保存されます.
上で実行した最適化の結果は以下のようになります.
ハイパパラメータ
x1
x2
x3
x4
x5
評価値
Styblinski-Tang
最適化手法
TPE
結果比較
デフォルトパラメータ
x1 = 0.0 x2 = 0.0 x3 = 0.0 x4 = 0.0 x5 = 0.0 result = 0.0
最適化結果
x1 = -3.930303675338723 x2 = 2.640453540706446 x3 = -2.954080362853035 x4 = -2.359296335376299 x5 = 2.690131733893075 result = -138.00660281690844
ソボルオプティマイザの ABCI 環境での実行例
ここでは,ソボルオプティマイザを ABCI 環境で実行する方法を説明します.例として,以下 user.py の main()
内で定義されている多項式をベンチマーク関数として最適化を行います.
以下の説明では aiaccel/examples/benchmark に保存されているファイルを編集して使用します.
1. ファイル構成
config.yaml
最適化およびソフトウェアの設定ファイルです.
user.py
与えられたパラメータからベンチマーク関数の値を計算し,aiaccel の Storage に保存するユーザプログラムです.
job_script_preamble.sh
ABCI で使用するモジュール指定やジョブ設定を行うためのシェルスクリプトファイルです.
2. ファイル作成手順
config.yaml の作成
generic
generic:
workspace: "./work"
job_command: "python user.py"
batch_job_timeout: 600
workspace - aiaccel の実行に必要な一時ファイルを保存するディレクトリを指定します.
job_command - ユーザープログラムを実行するためのコマンドです.
batch_job_timeout - ジョブのタイムアウト時間を設定します.[単位: 秒]
resource
resource:
type: "abci"
num_node: 4
type - 実行環境を指定します.ABCI 環境で実行するためには
"abci"
で設定します.num_node - 使用するノード数を指定します.
ABCI
ABCI:
group: "[group]"
job_script_preamble: "./job_script_preamble.sh"
job_execution_options: ""
group - 所属している ABCI グループを指定します.
job_script_preamble - ABCI の設定を記述したシェルスクリプトのファイルを指定します.
optimize
optimize:
search_algorithm: 'aiaccel.optimizer.SobolOptimizer'
goal: "minimize"
trial_number: 100
rand_seed: 42
parameters:
-
name: "x1"
type: "uniform_float"
lower: 0.0
upper: 5.0
-
name: "x2"
type: "uniform_float"
lower: 0.0
upper: 5.0
search_algorithm - 最適化アルゴリズムを設定します.この例ではソボルオプティマイザを設定しています.
goal - 最適化の方向を設定します.
ベンチマーク関数を最小化することが目的であるため,
"minimize"
を設定しています.
trial_number - 試行回数を設定します.
rand_seed - 乱数の生成に使用するシードを設定します.
parameters - ハイパパラメータの各種項目を設定します.ここでは 2 次元のベンチマーク関数の最適化を行うため,2 種類のパラメータを用意しています.2 つのパラメータに対して,以下の項目をそれぞれ設定する必要があります.パラメータの範囲や初期値を,全て同じにする必要はありません.
name - ハイパパラメータの名前を設定します.
type - ハイパパラメータのデータ型を設定します.
lower / upper - ハイパパラメータ最小値 / 最大値を設定します.
注意: ソボルオプティマイザを使用する際は,パラメータの初期値を設定することができません.
user.py の作成
user.py
は以下のように記述します.
from aiaccel.util import aiaccel
def main(p):
y = (p["x1"]**2) - (4.0 * p["x1"]) + (p["x2"]**2) - p["x2"] - (p["x1"] * p["x2"])
return float(y)
if __name__ == "__main__":
run = aiaccel.Run()
run.execute_and_report(main)
モジュール
from aiaccel.util import aiaccel
必要なモジュールをインポートします.
aiaccel.util.aiaccel - ユーザープログラム内で定義される関数
main()
と aiaccelとの間のインターフェイスを提供します.
main
def main(p):
y = (p["x1"]**2) - (4.0 * p["x1"]) + (p["x2"]**2) - p["x2"] - (p["x1"] * p["x2"])
return float(y)
最適化対象のメイン関数で,aiaccel はこの関数の return
値を最小化します.
引数にハイパパラメータの辞書型オブジェクトを取り,多項式の計算結果を返却します.
実行部分
if __name__ == "__main__":
run = aiaccel.Run()
run.execute_and_report(main)
aiaccel から関数 main()
にハイパーパラメータを渡し,main()
の返却値を Storage に保存します.run
はそのインターフェイスとなるインスタンスです.メソッド execute_and_report()
の内部で main()
が呼ばれ,目的関数の値を計算し,Storage に計算結果が保存されます.
job_script_preamble.shの作成
job_script_preamble.sh
は、ABCI にジョブを投入するためのバッチファイルのベースファイルです.
このファイルには事前設定を記述します.
ここに記述した設定が全てのジョブに適用されます.
#!/bin/bash
#$-l rt_C.small=1
#$-j y
#$-cwd
ABCI のバッチジョブ実行オプションを指定しています.
参考: https://docs.abci.ai/ja/job-execution/#job-execution-options
source /etc/profile.d/modules.sh
module load gcc/11.2.0
module load python/3.8/3.8.13
source ~/optenv/bin/activate
ユーザプログラム実行に必要なモジュールの読み込みと仮想環境のactivateを行います.
~/optenv には aiaccel をインストールした仮想環境のパスを設定します.
3. 実行
作成した config.yaml と user.py が保存されているディレクトリに移動し,下記のコマンドで aiaccel を起動してください.
aiaccel-start --config config.yaml --clean
コマンドラインオプション引数
--config
- 設定ファイルを読み込むためのオプション引数です.読み込むコンフィグのパスを記述します.--clean
- aiaccel の起動ディレクトリ内に config.yaml の workspace で指定したディレクトリが存在する場合,削除してから実行するためのオプション引数です.
4. 結果の確認
aiaccel の正常終了後,最適化の結果は以下の 2 か所に保存されます.
./work/results.csv
./work/result/{trial_id}.hp
ここで,./work はコンフィグファイルの workspace に設定したディレクトリです.
results.csv には,それぞれの試行でのパラメータの値と,そのパラメータに対する目的関数の値が保存されています. result/{trial_id}.hp は,{trial_id} 回目の試行のパラメータと関数の値が YAML 形式で保存されています. さらに,同じフォルダには final_result.result というファイルが作成され,全試行中で最良のパラメータと目的関数の値が YAML 形式で保存されます.
上で実行した最適化の結果は以下のようになります.
ハイパパラメータ
x1
x2
評価値
polynomial
最適化手法
Sobol
結果比較
最適化結果
x1 = 3.134656548500061 x2 = 1.9281481206417084 polynomial = -6.967029595301102
ネルダーミードオプティマイザの ABCI 環境での実行例
ここでは,ネルダーミードオプティマイザを ABCI 環境で実行する方法を説明します.例として,モデル ResNET50 に データセット CIFAR10 を学習させる際のハイパパラメータの最適化を行います.
以下の説明では aiaccel/examples/resnet50_cifar10 に保存されているファイルを編集して使用します.
1. ファイル構成
config.yaml
最適化およびソフトウェアの設定ファイルです.
user.py
与えられたパラメータから目的関数の値を計算し,aiaccel の Storage に保存するユーザプログラムです.今回の例では,モデル ResNET50 にデータセット CIFAR10 を学習させるユーザプログラムです.
job_script_preamble.sh
ABCI で使用するモジュール指定やジョブ設定を行うためのシェルスクリプトファイルです.
setup_dataset.py
データセット CIFAR10 ダウンロード用プログラムです.
2. ファイル作成手順
config.yaml の作成
generic
generic:
workspace: "./work"
job_command: "python user.py"
batch_job_timeout: 7200
workspace - aiaccel の実行に必要な一時ファイルを保存するディレクトリを指定します.
job_command - ユーザープログラムを実行するためのコマンドです.
batch_job_timeout - ジョブのタイムアウト時間を設定します.[単位: 秒]
参考 - 100 epoch の学習に最長 60 分程かかるため,
7200
と長めに設定します.
resource
resource:
type: "abci"
num_node: 6
type - 実行環境を指定します.ABCI 環境で実行するためには
"abci"
で設定します.num_node - 使用するノード数を指定します.
参考 - 今回の例では,最適化アルゴリズムが
NelderMeadOptimizer
,パラメータ数が 5 のため, 同時に計算されるシンプレックス頂点の最大数である6
にノード数を設定します.
ABCI
ABCI:
group: "[group]"
job_script_preamble: "./job_script_preamble.sh"
job_execution_options: ""
group - 所属している ABCI グループを指定します.
job_script_preamble - ABCI の設定を記述したシェルスクリプトのファイルを指定します.
optimize
optimize:
search_algorithm: 'aiaccel.optimizer.NelderMeadOptimizer'
goal: "minimize"
trial_number: 100
rand_seed: 42
parameters:
-
name: "batch_size"
type: "uniform_int"
lower: 64
upper: 256
initial: 256
-
name: "lr"
type: "uniform_float"
lower: 1.0e-4
upper: 1.0
initial: 0.1
-
name: "momentum"
type: "uniform_float"
lower: 0.8
upper: 1.0
initial: 0.9
-
name: "weight_decay"
type: "uniform_float"
lower: 5.0e-6
upper: 5.0e-2
initial: 5.0e-4
-
name: "lr_decay"
type: "uniform_float"
lower: 0.0
upper: 1.0
initial: 1.0e-3
search_algorithm - 最適化アルゴリズムを設定します.この例ではネルダーミードオプティマイザを設定しています.
goal - 最適化の方向を設定します.
参考 - Validation Error Rate を最小化することが目的であるため,
"minimize"
と設定します.
trial_number - 試行回数を設定します.
rand_seed - 乱数の生成に使用するシードを設定します.
parameters - ハイパパラメータの各種項目を設定します.ここでは,5 種類のハイパパラメータを用意しています.5 つのパラメータに対して,以下の項目をそれぞれ設定する必要があります.
name - ハイパパラメータの名前を設定します.
type - ハイパパラメータのデータ型を設定します.
lower / upper - ハイパパラメータ最小値 / 最大値を設定します.
initial - ハイパパラメータの初期値を設定します.
NelderMeadOptimizer
の場合は,シンプレックスの頂点数 (=パラメータ数 + 1) と要素数が同じリストを設定します.頂点数未満の数値リストが与えられた場合,足りない初期値は aiaccel によってランダムに設定されます.今回の例では,各ハイパパラメータに 1 個の初期値しか与えていないため,足りない 5 個の初期値は aiaccel によって設定されます.
user.py の作成
user.py
は以下のような構成になっています.
train_func
main
内で用いられる訓練用関数です.
val_test_func
main
内で用いられる評価・汎化性能検証用関数です.
main
最適化対象のメイン関数です.この関数の
return
値を最適化します.Validation Error Rate
で設定しています.
job_script_preamble.shの作成
job_script_preamble.sh
は、ABCI にジョブを投入するためのバッチファイルのベースファイルです.
このファイルには事前設定を記述します.
ここに記述した設定が全てのジョブに適用されます.
#!/bin/bash
#$-l rt_F=1
#$-j y
#$-cwd
#$ -l h_rt=2:00:00
ABCIのバッチジョブ実行オプションを指定しています.
#$-l rt_F=1
でFullノードを利用するように設定しています.参考: https://docs.abci.ai/ja/job-execution/#job-execution-options
source /etc/profile.d/modules.sh
module load gcc/11.2.0 python/3.8/3.8.13 cuda/10.1/10.1.243 cudnn/7.6/7.6.5
source ~/optenv/bin/activate
ユーザプログラム実行に必要なモジュールの読み込みと仮想環境の activate を行います.
~/optenv には aiaccel をインストールした仮想環境のパスを設定します.
3. 動作説明
aiaccel と PyTorch 動作する環境が必要です.
ABCIにおけるPyTorch導入手順(出典:https://docs.abci.ai/ja/apps/pytorch/)
aiaccelの仮想環境作成・activate後、下記コマンドを実行してください.
pip3 install --upgrade pip setuptools pip3 install filelock torch==1.8.1+cu111 torchvision==0.9.1+cu111 torchaudio==0.8.1 -f https://download.pytorch.org/whl/torch_stable.html
config.yaml の [ABCI][group] は,所属しているABCIグループ名に変更してください.
ABCI: group: "[group]" job_script_preamble: "./job_script_preamble.sh" job_execution_options: ""
事前に
python3 setup_dataset.py
を実行し,データセットのダウンロードを行ってください.上記準備を終えたら,下記のコマンドで aiaccel を起動してください.
aiaccel-start --config config.yaml --clean
コマンドラインオプション引数
--config
- 設定ファイルを読み込むためのオプション引数です.読み込むコンフィグのパスを記述します.--clean
- aiaccel の起動ディレクトリ内に config.yaml の workspace で指定したディレクトリが存在する場合,削除してから実行するためのオプション引数です.
4. 結果の確認
aiaccel の正常終了後,最適化の結果は以下の 2 か所に保存されます.
./work/results.csv
./work/result/{trial_id}.hp
ここで,./work はコンフィグファイルの workspace に設定したディレクトリです.
results.csv には,それぞれの試行でのパラメータの値と,そのパラメータに対する目的関数の値が保存されています. result/{trial_id}.hp は,{trial_id} 回目の試行のパラメータと関数の値が YAML 形式で保存されています. さらに,同じフォルダには final_result.result というファイルが作成され,全試行中で最良のパラメータと目的関数の値が YAML 形式で保存されます.
上で実行した最適化の結果は以下のようになります.
ハイパパラメータ
batch_size
lr
momentum
weight_decay
lr_decay
評価値
Validation Error Rate
最適化アルゴリズム
NelderMeadOptimizer
結果比較
デフォルトパラメータ
batch_size = 256, lr = 0.1, momentum = 0.9, weight_decay = 5.0e-4, lr_decay = 1.0e-3 EvalLoss = 0.9949815124511718, evalAcc = 79.86 TestLoss = 0.9659099947929383, TestAcc = 80.95
最適化結果
batch_size = 226, lr = 0.036964256184365454, momentum = 0.8899804003224022, weight_decay = 0.0027056323588476026, lr_decay = 0.03683728125425209 EvalLoss = 0.7713460917830467, evalAcc = 83.27 TestLoss = 0.7550274838387966, TestAcc = 83.59
5. 注意
上記設定で最適化を実行すると,ABCIポイントを約50ポイント消費します.
Wrapper の作成例
必要に応じて wrapper プログラムを作成します. aiaccel はユーザーが作成した最適化対象の関数の値を計算するプログラムの wrapper を作成するための API を提供します.
1. ファイル構成
ユーザープログラム
与えられたパラメータから最適化したい目的関数の値を計算し,標準出力に出力します.
wrapper.py
aiaccel からパラメータをユーザープログラムに渡し,計算結果を aiaccel に返却します.
config.yaml
最適化およびソフトウェアの設定ファイルです.
2. ファイル作成手順
関数プログラムの作成
以下のようなコマンドを実行した際に,最適化対象すべき値が標準出力に出力されるようなプログラムを作成します.
> {cmd} --config={config} --trial_id={trial_id} --x1={x1} --x2={x2}
cmd - ユーザープログラムを起動するコマンドです.
config - コンフィグファイルのパスです.
trial_id - aiaccel のジョブ ID です.
x1, x2, … - 最適化するパラメータです.ここでは例として 2 つのパラメータに x1, x2 という名前を付けましたが,任意の名前のパラメータを必要な数だけ設定することができます.
標準出力に出力される値は,以下のような形式である必要があります.
objective_y:{y}
y - 最適化対象の計算結果です,
ユーザープログラムの例
ここでは例として,python で最適化対象の関数を実装する場合を確認します.
import argparse
def main(x1, x2):
y = (x1 ** 2) - (4.0 * x1) + (x2 ** 2) - x2 - (x1 * x2)
return y
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('--x1', type=float)
parser.add_argument('--x2', type=float)
args = vars(parser.parse_known_args()[0])
y = main(args["x1"], args["x2"])
print(f"objective_y:{y}")
モジュール
import argparse
必要なモジュールをインポートします.
argparse - コマンドライン引数を取得するために使用するモジュールです.
最適化対象の関数
def main(x1, x2):
y = (x1 ** 2) - (4.0 * x1) + (x2 ** 2) - x2 - (x1 * x2)
return y
最適化対象の関数を定義します.
実行部分
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('--x1', type=float)
parser.add_argument('--x2', type=float)
args = vars(parser.parse_known_args()[0])
y = main(args["x1"], args["x2"])
print(f"objective_y:{y}")
以下の部分でパーサを作成し,コマンドライン引数を受け取ります.
parser = argparse.ArgumentParser()
parser.add_argument('--x1', type=float)
parser.add_argument('--x2', type=float)
args = vars(parser.parse_known_args()[0])
この例にある最適化対象の関数では,コンフィグのパスとジョブの ID は使用しないため,パラメータ (x1
と x2
) のみを取得するような処理が行われています.
パラメータを最適化対象の関数 (main()
) に渡し,値を計算します.
y = main(args["x1"], args["x2"])
計算結果を標準出力に出力します. このとき,計算された値の前に “objective_y:” を付け加えます.
print(f"objective_y:{y}")
この python で実装されたプログラムの名前を user.py とすると,ユーザープログラムの起動コマンドは,python user.py
となります.
例えばコンフィグのパスが config.yaml
,ジョブの ID が 0,パラメータ x1
が 1, パラメータ x2
が 2 の場合,実行コマンドは次の通りです.
> python user.py --config=condig.yaml --trial_id=0 --x1=1 --x2=2
このときの出力は以下のようになります.
objective_y:-3.0
wrapper.py の作成
以下のような wrapper プログラムを python で実装します.
from aiaccel.util import aiaccel
run = aiaccel.Run()
run.execute_and_report("python user.py")
モジュール
from aiaccel.util import aiaccel
aiaccel.util.aiaccel - wrapper オブジェクトを作成するためのモジュールです.
Wrapper オブジェクトの作成
run = aiaccel.Run()
aiaccel が提供する wrapper オブジェクトを作成します.
ユーザープログラムの実行
run.execute_and_report("python user.py")
ユーザープログラムを実行します.
"python user.py"
の部分は,自身のプログラムを実行するためのコマンドを記述してください.コマンドライン引数として渡される config, trial_id, パラメータは,
run.execute_and_report()
の内部で自動的に追加されます.そのため,ここに記述する必要はありません.
config.yaml の作成
generic
generic:
workspace: "./work"
job_command: "python wrapper.py"
batch_job_timeout: 600
aiaccel で wrapper プログラムを最適化させる場合は,job_command
に作成した wrapper の実行コマンドを設定します.
作成した python ファイルの名前が wrapper.py であれば,実行コマンドは python wrapper.py
です.
resource
resource:
type: "local"
num_node: 4
wrapper プログラムを最適化する場合,指定可能な実行タイプは "local"
または "ABCI"
です.
"python_local"
は選べません.
基本的な使い方
ABCIのセットアップ
ABCIのセットアップは下記資料を参考ください。
Python-venvによる仮想環境の作成
venv環境での使用を推奨いたします。このチュートリアルはvenv環境で動作させることを前提としています。
python3 -m venv optenv
ここでは仮想環境の名前を「optenv」とし、以後も当仮想環境を「optenv」と表記します。 仮想環境の名前は任意の名前を設定できます。
アクティベート
仮想環境を利用するには下記コマンドを実施します。
source optenv/bin/activate
以後の作業はアクティベート済みのものとして進めます
インストール
aiaccelをダウンロードします。
git clone https://github.com/aistairc/aiaccel.git
ダウンロード完了後、aiaccelフォルダに移動します。
cd aiaccel
依存環境をインストールします.
python -m pip install -r requirements.txt
Note
事前にpipをアップグレードすることを推奨いたします。
python -m pip install --upgrade pip
setup.pyを実行し、aiaccelをインストールします。
python setup.py install
または、
python -m pip install git+https://github.com/aistairc/aiaccel.git
aiaccelがインポートできることを確認します。
python
import aiaccel
チュートリアル
プロジェクトファイルの構成
コンフィグファイル、ユーザープログラム、ABCI実行用シェルスクリプトを用意し、一つのフォルダに格納します。 以後、この一式を含んだフォルダを「プロジェクトフォルダ」とします。 プロジェクトフォルダは任意の場所に作成してください。
├── config.yaml
├── user.py
└── job_script_preamble.sh
Note
config.yaml
- 最適化の設定ファイルです。user.py
- 最適化対象のプログラムです。詳細は後述します。job_script_preamble.sh
- ABCIにジョブを投入するためのスクリプトです。このファイルにはスクリプトの共通部分のみを記述します。このファイルをベースに、バッチジョブファイルを生成します。
Note
config.yaml
、 user.py
、 job_script_preamble.sh
は任意のファイル名に変更可能です。
コンフィグファイルの作成
generic
サンプル
generic:
workspace: "./work"
job_command: "python user.py"
batch_job_timeout: 600
workspace - 途中経過の保存先を指定します。
job_command - ユーザプログラムを実行するコマンドを記述します。
batch_job_timeout - jobのタイムアウト時間を設定します。[単位: 秒]
resource
サンプル
resource:
type: "ABCI"
num_node: 4
type - 実行環境を指定します。
ABCI
、またはlocal
を指定します。num_node - 使用するノード数を指定します。ローカルの場合はCPUコア数を指定してください。
ABCI
サンプル
ABCI:
group: "[group]"
job_script_preamble: "./job_script_preamble.sh"
job_execution_options: ""
job_script_preamble - ABCI上でソフトウェアを実行するためのラッパーシェルスクリプトです。詳細は後述します。
group - 自分が所属しているABCIグループ名を指定します。([]は記述不要です。)
optimize
サンプル
optimize:
search_algorithm: "aiaccel.optimizer.NelderMeadOptimizer"
goal: "minimize"
trial_number: 30
rand_seed: 42
parameters:
-
name: "x1"
type: "uniform_float"
lower: 0.0
upper: 5.0
initial: 1.0
-
name: "x2"
type: "uniform_float"
lower: 0.0
upper: 5.0
initial: 1.0
search_algorithm - 最適化アルゴリズムを指定します。
goal - 最適化の方向を設定します。[minimize | maximize]
trial_number - 試行回数を設定します。
parameters
name - ハイパーパラメータの名前を設定します。
type - ハイパーパタメータのデータ型を設定します。
データ型一覧
uniform_float
uniform_int
categorical
ordinal
lower - ハイパーパラメータ最小値を設定します。
upper - ハイパーパラメータ最大値を設定します。
initial - ハイパーパラメータの初期値を設定します。
step - ハイパーパラメータの分解能を設定します(最適化アルゴリズムがgridの場合は必ず指定してください。)。
log - 対数設定用の項目です(最適化アルゴリズムがgridの場合は必ず指定してください。)。
base - 対数設定用の項目です(最適化アルゴリズムがgridの場合は必ず指定してください。)。
comment - 自由記述欄。
Note
aiaccelは、次の最適化アルゴリズムをサポートしています。
random - ハイパーパラメータの値をランダムに生成します。
grid - ハイパーパラメータの値を一定間隔でサンプリングします。
sobol - Sobol列を用いてハイパーパラメータの値を生成します。
nelder-mead - ヒューリスティクスな最適化アルゴリズムです.
tpe - ベイズ最適化による最適化アルゴリズムです。
parametersの記述例
Type: uniform_intの記述例
parameters:
-
name: "x1"
type: "uniform_int"
lower: 0
upper: 5
initial: 1
-
name: "x2"
type: "uniform_int"
lower: 0
upper: 5
initial: 1
Note
initialを指定しない場合は、項目を削除します。
-
name: "x1"
type: "uniform_int"
lower: 0
upper: 5
Type: uniform_floatの記述例
parameters:
-
name: "x1"
type: "uniform_float"
lower: 0.0
upper: 5.0
initial: 0.0
-
name: "x2"
type: "uniform_float"
lower: 0.0
upper: 5.0
initial: 0.0
Type: categoricalの記述例
parameters:
-
name: "x1"
type: "categorical"
choices: ['green', 'red', 'yellow', 'blue']
-
name: "x2"
type: "categorical"
choices: ['green', 'red', 'yellow', 'blue']
Note
categorial使用時は
choices
項目を使用します.choices
は配列で指定する必要があります。catogoricalを使用できるのは、最適化アルゴリズムが
Random
,Grid', および
TPE` の場合のみです。
Type: ordinalの記述例
parameters:
-
name: "x1"
type: "ordinal"
sequence: [2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]
lower: 0
upper: 1024
-
name: "x2"
type: "ordinal"
sequence: [1024, 512, 256, 128, 64, 32, 16, 8, 4, 2]
lower: 0
upper: 1024
Note
ordinal使用時は
sequence
項目を使用します.sequence
は配列で指定する必要があります。ordinal使用時は
initial
の設定はできません。ordinalを使用できるのは、最適化アルゴリズムが
Random
とGrid
の場合のみです。
grid使用時の注意事項
最適化アルゴリズムで grid
を使用する場合、 parameters
の設定に log
、 step
、 base
を指定してください。
parameters:
-
name: "x1"
type: "uniform_int"
lower: 0
upper: 5
step: 1
log: false
base: 10
initial: 0.0
-
name: "x2"
type: "uniform_int"
lower: 0
upper: 5
step: 1
log: false
base: 10
initial: 0.0
Nelder-Mead使用時の注意事項
Nelder-Meadを使用する場合、 initial
を配列で指定する必要があります。
parameters:
-
name: "x1"
type: "uniform_int"
lower: 0
upper: 5
initial: [0, 5, 3]
-
name: "x2"
type: "uniform_int"
lower: 0
upper: 5
initial: [2, 4, 1]
また、 initial
を使用しない場合は、空のリストを指定します.
parameters:
-
name: "x1"
type: "uniform_int"
log: False
lower: 0
upper: 5
initial: []
-
name: "x2"
type: "uniform_int"
log: False
lower: 0
upper: 5
initial: []
あるいは、 initial
項目そのものを削除します。
parameters:
-
name": "x1"
type": "uniform_int"
log": False
lower": 0
upper": 5
-
name: "x2"
type: "uniform_int"
log: False
lower: 0
upper: 5
コンフィグファイル サンプル
config.yaml
generic:
workspace: "./work"
job_command: "python user.py"
batch_job_timeout: 600
resource:
type: "local"
num_node: 4
ABCI:
group: "[group]"
job_script_preamble: "./job_script_preamble.sh"
job_execution_options: ""
optimize:
search_algorithm: "aiaccel.optimizer.NelderMeadOptimizer"
goal: "minimize"
trial_number: 30
rand_seed: 42
parameters:
-
name: "x1"
type: "uniform_float"
lower: 0.0
upper: 5.0
initial: [0.0, 5.0, 3.0]
-
name: "x2"
type: "uniform_float"
lower: 0.0
upper: 5.0
initial: [2.0, 4.0, 1.0]
ユーザープログラムの作成
最適化対象の処理を作成します。ここでは、作成済みモデルをaiaccelで最適化するための変更方法を記述します。
次の関数を最適化させる場合の例を示します。
def func(x1, x2):
y = (x1**2) - (4.0 * x1) + (x2**2) - x2 - (x1 * x2)
return y
これを、aiaccelで最適化させるには次のように変更します。
from aiaccel.util import aiaccel
def func(p):
x1 = p["x1"]
x2 = p["x2"]
y = (x1**2) - (4.0 * x1) + (x2**2) - x2 - (x1 * x2)
return y
if __name__ == "__main__":
run = aiaccel.Run()
run.execute_and_report(func)
Wrapperの作成
必要に応じてwrapperプログラムを作成します。aiaccelはユーザープログラムのwrapperを作成するためのAPIを提供します。
サンプル
wrapper.py(任意の名前に変更可能)
from aiaccel.util import aiaccel
# Wrapperオブジェクトの生成
run = aiaccel.Run()
# ユーザープログラムを実行します。
# commandにユーザープログラムを実行するためのコマンドを記述してください。
# コマンドライン引数は自動で生成します。
# --config
# --index
# --x1 (例)
# --・・・
run.execute_and_report("python user.py")
aiaccelでwrapperプログラムを最適化させる場合はコンフィグファイルのjob_command
を変更します。
generic:
workspace: "./work"
job_command: "python wrapper.py"
batch_job_timeout: 600
job_script_preamble.shの作成
job_script_preamble.sh
は、ABCIにジョブを投入するためのバッチファイルのベースファイルです。
このファイルには事前設定を記述します。ここに記述した設定が全てのジョブに適用されます。
サンプル
#!/bin/bash
#$-l rt_C.small=1
#$-j y
#$-cwd
source /etc/profile.d/modules.sh
module load gcc/11.2.0
module load python/3.8/3.8.13
module load cuda/10.2
module load cudnn/8.0/8.0.5
module load nccl/2.8/2.8.4-1
source ~/optenv/bin/activate
AIACCELPATH=$HOME/local/aiaccel-dev
export PYTHONPATH=$AIACCELPATH:$AIACCELPATH/lib
最適化実行
プロジェクトフォルダに移動し、次のコマンドを実行します。
python -m aiaccel.cli.start --config config.yaml
Note
コンフィグファイル名 `config.yaml` は適切な文字列に変更してください。
実行するとターミナルに進捗状況を出力します。
オプション付きの実行
start
コマンドの後に、追加オプションを指定できます。
python -m aiaccel.cli.start
–clean : workspaceが既に存在する場合、最適化実行前にworkspaceを削除します。
–resume : workspaceが既に存在する場合、保存データが存在するトライアルを指定することで、指定のトライアルから再開することができます。
例
python -m aiaccel.cli.start --config config.yaml --clean
ローカル環境での実行方法
ローカル環境でaiaccelを使用する場合は、次のように設定を変更します。
resourceの設定
コンフィグファイルの resource
の type
に local
を指定します。
resource:
type: "local"
num_node: 4
ABCIの設定
ローカル環境で実施する場合, ABCI
の設定は動作に反映されません。
ABCI:
group: "[group]"
job_script_preamble: "./job_script_preamble.sh"
job_execution_options: ""
job_script_preamble.sh
ローカル環境で実施する場合、 job_script_preamble.sh
は不要です。
記述した内容は動作に反映されません。
コンフィグレーションの設定ガイド (WIP)
generic:
workspace (str, optional):
aiaccel の実行に必要な一時ファイルを保存するディレクトリを指定します. デフォルトでは “./work” に設定されています.
job_command (str):
ユーザープログラムを実行するためのコマンドです.
python_file (str, optional):
ローカル実行のモードの一つである python_local モードを用いる場合に,最適化対象の関数が実装されている python のファイルパスを指定します. 実行モードが ABCI または通常の Local の場合には指定する必要はありません.
function (str, optional):
ローカル実行のモードの一つである python_local モードを用いる場合に,最適化対象の関数名を指定します. aiaccel は実行時,python_file に書かれたファイルから,ここで指定された名前の関数をインポートします. 実行モードが ABCI または通常の Local の場合には指定する必要はありません.
batch_job_timeout (int, optional):
ジョブのタイムアウト時間を秒単位で設定します. デフォルトでは 600 (秒) に設定されています.
sleep_time (float, optional):
最適化実行のメインループ 1 周あたりのスリープ時間を秒単位で指定します. デフォルトでは 0.01 (秒) に設定されています.
resource:
type (str):
実行環境を指定します. aiaccel は以下の 3 つの環境での実行をサポートしています.
“abci” - ABCI 上で最適化を実行します.
“local” - ローカル環境で最適化を実行します.
“python_local” - ローカル環境で最適化を実行します.最適化対象の関数が python で実装されている必要がありますが,通常のローカル実行よりも高速に最適化を実行することが可能です. デフォルトでは “local” に設定されています.
num_node (int):
使用するノード数を指定します. デフォルトでは 1 に設定されています.
ABCI:
group (str):
ユーザーが所属する ABCI のグループを指定します.
job_script_preamble (str):
ABCI の設定を記述したシェルスクリプトのファイルを指定します.
job_execution_options (str | list[str], optional):
aiaccel が ABCI の計算ノード上にジョブを投入する際に付加されるオプションのコマンドです. デフォルトでは “” (空の文字列) が設定されています.
optimize:
search_algorithm (str, optional):
最適化アルゴリズムを設定します. aiaccel では以下のアルゴリズムをサポートしています.
“aiaccel.optimizer.NelderMeadOptimizer” - Nelder-Mead 法でパラメータの探索を行います.
“aiaccel.optimizer.RandomOptimizer” - パラメータをランダムに生成します,
“aiaccel.optimizer.SobolOptimizer” - Sobol’ 列を用いてパラメータを生成します.
“aiaccel.optimizer.GridOptimizer” - 分割した探索空間からパラメータを選びます.
“aiaccel.optimizer.TpeOptimizer” - ベイズ最適化を用いてパラメータの探索を行います.
デフォルトでは “aiaccel.optimizer.NelderMeadOptimizer” に設定されています.
goal (str, optional):
最適化の向きを決定します.
“minimize” - 目的関数が小さくなるようにパラメータを最適化します.
“maximize” - 目的関数が大きくなるようにパラメータを最適化します.
デフォルトでは “minimize” に設定されています.
trial_number (int):
試行回数を設定します.
rand_seed (int, optional):
乱数生成に用いるシードを設定します.設定可能な値の範囲は numpy.random.default_rng
が取り得る範囲に一致します.
デフォルトでは None に設定されています.
sobol_scramble (bool, optional):
ソボルオプティマイザを使用する際に,スクランブルを使用するかを指定します. デフォルトでは true に設定されています.
parameters (list):
パラメータの探索条件をまとめたリストを設定します. 最適化アルゴルズムとパラメータのデータ型に応じて,各要素には以下の項目が含まれます.
name - パラメータの名前を設定します.
type - パラメータのデータ型を設定します.aiaccel は次のデータ型をサポートします.
“uniform_float” - 浮動小数点数型
“uniform_int” - 整数型
“categorical” - カテゴリカル型
“ordinal” - オーディナル型
lower - パラメータの最小値を設定します.
upper - パラメータの最大値を設定します.
initial - パラメータの初期値を設定します.
step - パラメータの分解能を設定します.
log - パラメータの探索空間を対数スケールで分割するかを指定します.対数スケールを使用する場合は
true
を,使用しない場合はfalse
を設定します.base - 対数スケールでパラメータの探索空間を分割する場合の対数の基数を指定します.
choices - データ型が categorical の場合に,選択肢のリストを設定します.
sequence - データ型が ordinal の場合に,選択肢のリストを設定します.
comment - コメントを設定します.
それぞれのアルゴリズムとデータ型で必要なパラメータは以下の通りです.
Nelder-Mead 法 (“aiaccel.optimizer.NelderMeadOptimizer”)
設定可能なデータ型は “uniform_float”,”uniform_int”,および “ordinal” です.
“uniform_float” または “uniform_int” の場合
name
type (“uniform_float”, “uniform_int”)
lower
upper
initial - 要素数が パラメータ数 + 1 の配列を設定します.initial の項目が存在しない場合,aiaccel はランダムに初期値の配列を設定します.また,設定された配列の要素数が パラメータ数 + 1 より少ない場合,aiaccel は足りない初期値をランダムに生成し補います.
“ordinal” の場合
name
type (“ordinal”)
sequence - 選択肢の配列を設定します.配列の要素は float, int, または str 型です.
initial - 要素数が パラメータ数 + 1 の配列を設定します.initial の項目が存在しない場合,aiaccel はランダムに初期値の配列を設定します.また,設定された配列の要素数が パラメータ数 + 1 より少ない場合,aiaccel は足りない初期値をランダムに生成し補います.
ランダムオプティマイザ (“aiaccel.optimizer.RandomOptimizer”)
設定可能なデータ型は “uniform_float”, “uniform_int”, “categorical”, および “ordinal” です.
“uniform_float” または “uniform_int” の場合
name
type (“uniform_float”, “uniform_int”)
lower
upper
initial
“categorical” の場合
name
type (“categorical”)
choices - 選択肢の配列を設定します.配列の要素は float, int, または str 型です.
initial
“ordinal” の場合
name
type (“ordinal”)
sequence - 選択肢の配列を設定します.配列の要素は float, int, または str 型です.
initial
ソボルオプティマイザ (“aiaccel.optimizer.SobolOptimizer”)
設定可能なデータ型は “uniform_float” と “uniform_int” です. データ型に依らず,初期値は設定できません.
name
type (“uniform_float”, “uniform_int”)
lower
upper
グリッドオプティマイザ (“aiaccel.optimizer.GridOptimizer”)
設定可能なデータ型は “uniform_float”, “uniform_int”, “categorical”, および “ordinal” です. データ型に依らず,初期値は設定できません.
“uniform_float” または “uniform_int” の場合
name
type (“uniform_float”, “uniform_int”)
lower
upper
step
log
base
(注意) log
が true
の場合,lower
,upper
,および step
は対数スケールでの値として参照されます.
即ち,探索の下限は \({base}^{lower}\),上限は \({base}^{upper}\) と解釈され, \(n\ (=0, 1, \cdots)\) 番目の点は \({base}^{lower} {base}^{n \times step}\) で与えられます.
一方で log
が false
の場合,lower
,upper
,および step
は,それぞれ探索の下限,上限,およびステップに直接対応します.
この場合,base
の値は使用されませんが,何も値を設定していないとエラーが生じます.
“categorical” の場合
name
type (“categorical”)
choices - 選択肢の配列を設定します.配列の要素は float, int, または str 型です.
“ordinal” の場合
name
type (“ordinal”)
sequence - 選択肢の配列を設定します.配列の要素は float, int, または str 型です.
TPE オプティマイザ (“aiaccel.optimizer.TpeOptimizer”)
設定可能なデータ型は “uniform_float”, “uniform_int”, “categorical”, および “ordinal” です.
“uniform_float” または “uniform_int” の場合
name
type (“unform_float”, “uniform_int”)
lower
upper
initial
log
“categorical” の場合
name
type (“categorical”)
choices - 選択肢の配列を設定します.配列の要素は float, int, または str 型です.
initial
“ordinal” の場合
name
type (“ordinal”)
sequence - 選択肢の配列を設定します.配列の要素は float, int, または str 型です.
initial
job_setting:
cancel_retry (int, optional):
Max retry counts to transit the state from HpCancelFailed to HpCancelFailure. Defaults to 3.
cancel_timeout (int, optional):
Timeout seconds to transit the state from HpCancelChecking to HpCancelFailed. Defaults to 60.
expire_retry (int, optional):
Max retry counts to transit the state from HpExpireFailed to HpExpireFailure. Defaults to 3.
expire_timeout (int, optional):
Timeout seconds to transit the state from HpExpireChecking to HpExpireFailed. Defaults to 60.
finished_retry (int, optional):
Max retry counts to transit the state from HpFinishedFailed to HpFinishedFailure. Defaults to 3.
finished_timeout (int, optional):
Timeout seconds to transit the state from HpFinishedChecking to HpFinishedFailed. Defaults to 60.
job_loop_duration (float, optional):
スケジューラジョブスレッドのループ 1 周あたりのスリープ時間を秒単位で指定します. デフォルトでは 0.5 (秒) に設定されています.
A sleep time each job loop. Defaults to 0.5.
job_retry (int, optional):
Max retry counts to transit the state from HpCancelFailed to HpCancelFailure. Defaults to 2.
job_timeout (int, optional):
Timeout seconds to transit the state from JobChecking to JobFailed. Defaults to 60.
kill_retry (int, optional):
Max retry counts to transit the state from KillFailed to KillFailure. Defaults to 3.
kill_timeout (int, optional):
Timeout seconds to transit the state from KillChecking to KillFailed. Defaults to 60.
result_retry (int, optional):
Max retry counts to transit the state from RunnerFailed to RunnerFailure. Defaults to 1.
runner_retry (int, optional):
Max retry counts to transit the state from RunnerFailed to RunnerFailure. Defaults to 3.
runner_timeout (int, optional):
Timeout seconds to transit the state from RunnerChecking to RunnerFailed. Defaults to 60.
running_retry (int, optional):
Max retry counts to transit the state from HpRunningFailed to HpRunningFailure. Defaults to 3.
running_timeout (int, optional):
Timeout seconds to transit the state from HpRunningChecking to HpRunningFailed. Defaults to 60.
init_fail_count (int, optional):
Defaults to 100.
name_length (int, optional):
文字列としてのジョブ ID の長さです. この文字列は,結果を .hp ファイルに保存する際にファイル名として使用されます. デフォルトでは 6 に設定されています.
logger:
file:
実行ログの保存先を設定します.
master (str, optional):
マスターモジュールのログの保存先を設定します. デフォルトでは “master.log” に設定されています.
optimizer (str, optional):
オプティマイザモジュールのログの保存先を設定します. デフォルトでは “optimizer.log” に設定されています.
scheduler (str, optional):
スケジューラモジュールのログの保存先を設定します. デフォルトでは “scheduler.log” に設定されています.
log_level:
master (str):
マスターモジュールからのログファイル出力のログレベルを設定します. 以下の文字列が設定可能です.
‘DEBUG’
‘INFO’
‘WARNING’
‘WARN’
‘ERROR’
‘CRITICAL
デフォルトでは “DEBUG” に設定されています.
A logging level for a log file output of master module. Following strings are available;
‘DEBUG’
‘INFO’
‘WARNING’
‘WARN’
‘ERROR’
‘CRITICAL
Defaults to “DEBUG”.
optimizer (str, optional):
オプティマイザモジュールからのログファイル出力のログレベルを設定します. デフォルトでは “DEBUG” に設定されています.
A logging level for a log file output of optimizer module. Defaults to “DEBUG”.
scheduler (str, optional):
オプティマイザモジュールからのログファイル出力のログレベルを設定します. デフォルトでは “DEBUG” に設定されています.
A logging level for a log file output of scheduler module. Defaults to “DEBUG”.
stream_level:
master (str, optional):
マスターモジュールからのストリーム出力のログレベルを設定します. デフォルトでは “DEBUG” に設定されています.
A logging level for a stream output of master module. Defaults to “DEBUG”.
optimizer (str, optional):
オプティマイザモジュールからのストリーム出力のログレベルを設定します. デフォルトでは “DEBUG” に設定されています.
A logging level for a stream output of optimizer module. Defaults to “DEBUG”.
scheduler (str, optional):
スケジューラモジュールからのストリーム出力のログレベルを設定します. デフォルトでは “DEBUG” に設定されています.
A logging level for a stream output of scheduler module. Defaults to “DEBUG”.
verification:
is_verified (bool, optional):
最適化結果の verification を行うかを設定します. デフォルトでは flase が設定されています.
Defaults to false.
condition (list, optional):
Verification の条件の配列を設定します. 配列の各要素には,以下の項目が設定されている必要があります.
loop - Verification 対象となるジョブの ID です.
minimum - 試行回数 loop 回までに計算された最も良い目的関数の値として許容される値の下限です.
maximum - 試行回数 loop 回までに計算された最も良い目的関数の値として許容される値の下限です.
デフォルトでは,[] (空の配列) が設定されています.
Defaults to [] (an empty list).
aiaccelアーキテクチャ
aiaccelは,与えられた入力ハイパーパラメータ群から最適なハイパーパラメータを出力するハイパーパラメータ最適化ライブラリです.
本章は,開発者に向けたドキュメントです. aiaccelのアーキテクチャやトピックごとにaiaccelの機能を解説し,aiaccelに関する開発の一助となることを目的としています.
aiaccelのシステム概要
aiaccelのシステムについて概説します. aiaccelは,ABCI上で実行することを想定したハイパーパラメータ最適化ライブラリです. ローカルコンピュータでも動作はしますが,その機能を最大限に発揮するためにはABCIを利用することが推奨されます. ABCIについては,ABCI User Guideを参照してください. aiaccelは,ABCIのインタラクティブノード上で実行されることを想定されます. Configを入力として,aiaccelは内部でMaster, Optimizer, Scheduler を起動し,Storage(ファイルシステムやデータベース)に状態を保存しながら,最適化対象であるユーザープログラムをABCI計算ノードにてジョブとして実行します. ABCI計算ノードで実行されたユーザープログラムは,結果をStorageに保存します.
aiaccelの入出力
aiaccelの入出力をもう少しく詳しくみてみます.
入力
Config: コンフィグレーションファイルです. examples/sphere/config.yaml などが該当します. 上記のシステム概要のConfigの一部です.
User Program: ユーザープログラムです. examples/sphere/user.py などが該当します. user.py は上記のコンフィグレーションファイル内で指定します. user.pyである必要はありませんが,aiaccelがユーザープログラムを実行するためのインタフェースが user.py に記述されていますので user.py に該当するファイルは必要となります. Java, C++ などの実行ファイルを利用する場合は user.py に該当するファイルから呼び出して実行してください. 上記のシステム概要の<user program>.pyです.
Job Script: ジョブスクリプトファイルです. examples/sphere/job_script_preamble.sh などが該当します. ジョブスクリプトファイルは,ABCIを利用する際に必要となるファイルです. 役割は,aiaccelがABCI上でuser.pyをジョブとして実行するためのスクリプトとなります. 詳しくはABCIのバッチジョブに関するドキュメントの記法を参照してください. 上記のシステム概要のConfigの一部です.
出力
Work Directory: aiaccelを実行した際生成されるワークディレクトリです. aiaccelを実行した際 work という名前のディレクトリが生成されます. 上記のシステム概要のStorageの一部です.
Result Directory: aiaccelを実行した際,実行結果を保存するリザルトディレクトリです. ワークディレクトリは,現在実行中・実行した状態を保存するディレクトリであるのに対し,リザルトディレクトリは過去に実行した結果を全て保存するディレクトリです. ただし,実行したディレクトリ内に生成されるため,実行するディレクトリを変更するとまた新しいリザルトディレクトリが生成されます. 上記のシステム概要のStorageの一部です.
Database: aiaccelの実行中の状態・実行結果を保存するデータベースです. work/storage/storage.db が該当します. work はワークディレクトリです. データベースはsqlite3を採用しています. 上記のシステム概要のStorageの一部です.
aiaccelの構成モジュール
aiaccelは,内部で3つのモジュールが連携しながら実行されます. 本節ではaiaccelの3つのモジュールの役割について説明します.
マスター
スケジューラ・オプティマイザを管理します. 開始時に起動され,オプティマイザ・スケジューラを起動し,これら2つのモジュールの死活監視をします. オプティマイザ(またはスケジューラ)が停止すると実行中のスケジューラ(またはオプティマイザ)を停止させ,自身も終了します.
オプティマイザ
どのハイパーパラメータを次に実行するかを計算します.5つの最適化アルゴリズムをサポートしており,コンフィグに記述することで実行するアルゴリズムを選択します.
スケジューラ
オプティマイザが選択したハイパーパラメータをジョブとして実行し,そのジョブを管理します. ジョブは,ハイパーパラメータごとに生成されローカルコンピュータまたはABCI上で実行されます.
aiaccelの処理フロー
aiaccelが内部でどのように実行されるかを別の視点から見てみます. 以下の図でもマスター・オプティマイザ・スケジューラの3つのモジュールを軸に構成されています.
aiaccel-startコマンドからコンフィグを入力として指定して実行します.
start.pyがコンフィグをロードし,Masterを起動します.
MasterがOptimizerを起動します.
MasterがSchedulerを起動します.
Optimizerはコンフィグからハイパーパラメータを読み込み,最適化アルゴリズムに基づきハイパーパラメータを生成しStorageに保存します.
SchedulerはStorageから新しいハイパーパラメータを読み込み,コンフィグに基づき指定の計算ノードでユーザープログラムをジョブとして実行します.
aiaccelのラッパーにより実行されたユーザープログラムが終了すると,aiaccelラッパーがユーザープログラムの結果をStorageに保存します.
5-7 が指定のトライアル数まで繰り返されます.ハイパーパラメータの生成数や同時に実行できる計算ノード数などは全てコンフィグに記述します.
全てのトライアル数分のハイパーパラメータが完了する,または停止命令を受けるとMaster, Optimizer, Scheduler は停止します.
コードから見るaiaccelの処理フロー
aiaccelの処理フローでは,大まかにaiaccelではMaster, Optimizer, Schedulerが協調し,それぞれの役割を果たしていることについて述べた. では実際にコードレベルで,それらのフローを追ってみよう.
start.py
aiaccelはaiaccel-startスクリプトにより実行を開始する.aiaccel/cli/start.py を見てみるとまずMaster, Optimizer, Schedulerが初期化される
Master = create_master(args.config)
Optimizer = create_optimizer(args.config)
Scheduler = create_scheduler(args.config)
初期化されたモジュールは,以下のコードで実行される. pre_processメソッドの後メインループが周り,メインループ後にpost_processメソッドが実行される. シンプルに表せば基本的にMasterもOptimizerもSchedulerは,これらの処理で説明できる.
for module in modules:
module.pre_process()
while True:
for module in modules:
if not module.inner_loop_main_process():
break
if not module.check_error():
break
module.loop_count += 1
else:
time.sleep(sleep_time)
continue
break
for module in modules:
module.post_process()
module.py
pre_processメソッド・メインループ・post_processメソッドの基本的な記述は aiaccel/module.py にある. module.py は,Master, Optimizer, Scheduler のスーパークラスにあたる AbstractModule クラスが定義されている.
Master
再度 aiaccel/cli/start.py を見てみる. Masterモジュールは create_master メソッドにより初期化されている. aiaccel/master/create.py を見てみると,コンフィグに記述されたresource_typeに基づき異なるMasterクラスが実行される.
簡単のため,ここでは LocalMaster クラスを見てみる. aiaccel/master/local_master.py を見てみると,AbstractMasterクラスを継承しており特に追記はない.
では更に aiaccel/master/abstract_master.py の AbstractMaster クラスを見てみる. 時間に関するコードや Evaluator などがあるが,inner_loop_main_process メソッド内の以下のコードが終了判定をしている.
if self.hp_finished >= self.trial_number:
return False
AbstractMaster クラスにおいては,ここで False が返る,つまり終了したハイパーパラメータ数がトライアル数以上になるとMasterが終了する.
Optimizer
Optimizerモジュールも,Master同様 start.py にて create_optimizer メソッドにより初期化されている. aiaccel/optimizer/create.py を見てみると,コンフィグに記述された最適化アルゴリズム名に基づきOptimizerを初期化している.
ここでは簡単のため RandomOptimizer クラス を見てみる. aiaccel/optimizer/random_optimizer.py を見てみると,AbstractOptimzier クラスを継承しており,generate_parameter メソッドのみオーバーライドされている.
RandomOptimizer クラスの generate_parameter メソッドは,以下のコードでランダムなハイパーパラメータを生成する.
sample = self.params.sample(rng=self._rng)
では更に aiaccel/optimizer/abstract_optimizer.py の AbstractOptimizer クラスを見てみる. メインループである inner_loop_main_process メソッドを見ると,以下のコードで新しいハイパーパラメータを生成している.
for _ in range(pool_size):
new_params = self.generate_new_parameter()
pool_size 変数は,計算ノードがどの程度空いているかに基づいた数値である.
Scheduler
Schedulerモジュールも,Master, Optimizer 同様のアーキテクチャとなっている. ここでは LocalScheduler クラスを見てみる.
aiaccel/scheduler/local_scheduler.py は,AbstractScheduler クラスを継承している. get_stats メソッドは,現在のジョブの状態を取得する役割を担う. LocalSchedulerクラスでは,ps コマンドをパースしてジョブの状態を取得していることが分かる.
inner_loop_main_process メソッドはメインループであり,ジョブをプロセスとして実行する. その際の execute メソッドが実行コマンドを生成し実行する.
カスタムオプティマイザー作成ガイド
オプティマイザは,ハイパーパラメータを生成する機能を担うためどのハイパーパラメータの組を選択するかのアルゴリズムにより,最適化のパフォーマンスは大きく変わってきます. 本稿では,ユーザーがaiaccelを用いた独自のオプティマイザを開発するための方法について解説します.
カスタムオプティマイザの実行確認
それでは,まずカスタムオプティマイザを実行するための動作を確かめてみましょう. 所謂Hello, Worldの位置づけです. ここで解説する内容は簡単にまとめると下記のようになります.
カスタムオプティマイザのソースファイルを作成する
カスタムオプティマイザのソースファイルをaiaccelが読み込めるようにする
コンフィグレーションファイルを編集し,カスタムオプティマイザを実行できるようにする
カスタムオプティマイザをどのように実行するかは環境に依存しますが,今回は自分で作成したワークスペースディレクトリに追加して実行してみます. その他にはソースコードに追加するなど,環境次第でやり方は異なりますので各自の環境に合わせて設定してください.
開発環境の確認
まず環境の確認からします. 本ガイドでは,各種インストールは終了しaiaccelが実行できる状態から始めます. インストールが未だの方はインストールガイドを参照してください. 各ディレクトリ・ファイルは以下のとおりとします. 皆さんの環境に読み替えて参考にしてください.
aiaccelのソースディレクトリ: /workspace/aiaccel
ワークスペースディレクトリ: /workspace/aiaccel/work
例えばランダムオプティマイザのファイル: /workspace/aiaccel/aiaccel/optimizer/random_optimizer.py
カスタムオプティマイザファイルの作成
カスタムオプティマイザのソースファイルを作成します. 今回はランダムオプティマイザをコピーします.
> pwd
/workspace/aiaccel
> mkdir -p work/lib/my_optimizer
> cp aiaccel/optimizer/random_optimizer.py work/lib/my_optimizer/custom_optimizer.py
これでcustom_optimizer.pyが作成されました.
ファイルの編集
このままではcustom_optimizer.pyの内容はランダムオプティマイザと同じですので,少しだけ編集します.
/workspace/aiaccel/work/lib/my_optimizer/custom_optimizer.py
from aiaccel.optimizer.abstract_optimizer import AbstractOptimizer
- class RandomOptimizer(AbstractOptimizer):
+ class CustomOptimizer(AbstractOptimizer):
"""An optimizer class with a random algorithm.
"""
上記はdiff表記で削除された行頭に - 追加された行頭に + が付いています. クラス名をRandomOptimizerからCustomOptimizerに変更しました. 変更したファイルは保存します.
パスの設定
今custom_optimizer.pyにはランダムオプティマイザを全く同じ動作をするCustomOptimizerを定義しました. aiaccelから作成したCustomOptimizerクラスを実行する必要があるので,まず__init__.pyファイルを作成します. ここではaiaccel/optimizerにある__init__.pyを編集して利用します.
> pwd
/workspace/aiaccel
> cp aiaccel/optimizer/__init__.py work/lib/my_optimizer/
追加したCustomOptimizerを読み込むように編集します.
/workspace/aiaccel/work/lib/my_optimizer/init.py
- from .grid_optimizer import GridOptimizer
- from .nelder_mead_optimizer import NelderMeadOptimizer
- from .random_optimizer import RandomOptimizer
- from .sobol_optimizer import SobolOptimizer
- from .tpe_optimizer import TpeOptimizer
+ from .custom_optimizer import CustomOptimizer
__all__ = [
- GridOptimizer,
- RandomOptimizer,
- SobolOptimizer,
- NelderMeadOptimizer,
- TpeOptimizer
+ CustomOptimizer
]
次にパスの設定を行います. PYTHONPATHに,aiaccelと追加したcustom_optimizer.pyのディレクトリを追加します.
> echo $PYTHONPATH
> export PYTHONPATH=/workspace/aiaccel:/workspace/aiaccel/work/lib
> echo $PYTHONPATH
/workspace/aiaccel:/workspace/aiaccel/work/lib
ユーザーファイルの作成
カスタムオプティマイザを作成したので,実際に実行するユーザーファイルを作成します. 今回は/workspace/aiaccel/examples/sphereディレクトリをコピーして作成します.
> pwd
/workspace/aiaccel
> cp -R examples/sphere work/
> cd work/sphere
> pwd
/workspace/aiaccel/work/sphere
> ls
config.yaml user.py
examples/sphereディレクトリをコピーし,sphereディレクトリに移動しました. 次にコンフィグレーションファイルを編集します. オプティマイザに今回作成したカスタムオプティマイザを利用したいのでconfig.yamlを編集します.
/workspace/aiaccel/work/sphere/config.yaml
optimize:
- search_algorithm: "aiaccel.optimizer.NelderMeadOptimizer"
+ search_algorithm: "my_optimizer.CustomOptimizer"
goal: "minimize"
trial_number: 30
rand_seed: 42
parameters:
これでコンフィグレーションファイルの編集は一旦終了です. 編集したファイルを保存します.
実行の確認
それでは現在のディレクトリで実行してみます.
> pwd
/workspace/aiaccel/work/sphere
> aiaccel-start --config config.yaml --clean
正常に実行できれば成功です. このカスタムオプティマイザの中身はランダムオプティマイザと同じなので,ランダムにハイパーパラメータが選択されます.
ここまででカスタムオプティマイザが実行できることが確認できたので,次節ではオプティマイザのソースコードを編集して実行する点を解説します.
カスタムオプティマイザの編集
前節でカスタムオプティマイザの実行確認を行いました. 本節では,前節で作成したカスタムオプティマイザを編集しシンプルなアルゴリズムを実装します. 簡単のため前節で作成したワークスペースを流用し5つのfloat型のハイパーパラメータに対し正規分布でハイパーパラメータを生成するオプティマイザを作成してみましょう.
既存のオプティマイザには,ランダム・Sobol’列・グリッド・NelderMead・TPEがサポートされていますが,ランダムオプティマイザをコピーしたソースファイルから編集を始めます.
ランダムオプティマイザの確認
前節でコピーしたカスタムオプティマイザのファイルを見てみましょう.
/workspace/aiaccel/work/lib/my_optimizer/custom_optimizer.py
from __future__ import annotations
from aiaccel.optimizer.abstract_optimizer import AbstractOptimizer
class CustomOptimizer(AbstractOptimizer):
"""An optimizer class with a random algorithm.
"""
def generate_parameter(self) -> list[dict[str, float | int | str]]:
"""Generate parameters.
Returns:
list[dict[str, float | int | str]]: A list of created parameters.
"""
new_params = []
sample = self.params.sample(rng=self._rng)
for s in sample:
new_param = {
'parameter_name': s['name'],
'type': s['type'],
'value': s['value']
}
new_params.append(new_param)
return new_params
CustomOptimizer
クラスは AbstractOptimizer
を継承し,generate_parameter
メソッドのみを実装しています.
generate_parameter
以外のオプティマイザとしての機能は AbstractOptimizer
に実装されているので,generate_parameter
メソッドを実装すれば簡単なオプティマイザなら実装することができます.
ハイパーパラメータのソースコードの確認
generate_parameter
メソッドを見てみましょう.
self.params.sample
というメソッドを実行しています.
このメソッドは,aiaccel/parameter.py の HyperParameterConfiguration
インスタンスである self.params
の sample
メソッドです.
引数として与えられている self._rng
は 継承元の AbstractOptimizer
が持つ numpy.random.RandomState
オブジェクトです.
sample
メソッド内では,さらに HyperParameter
インスタンスである value
から更に sample
メソッドが呼ばれています.
この2度目に呼ばれた sample
メソッドは HyperParameter
クラスのメソッドであり,中身を見てみるとハイパーパラメータのタイプごとに処理が分かれていますが,例えば FLOAT
型の場合 numpy.random.RandomState.uniform
が実行されます.
/workspace/aiaccel/aiaccel/parameter.py
elif self.type.lower() == 'float':
value = rng.uniform(self.lower, self.upper)
こうして生成されたランダムなハイパーパラメータを返すことが generate_parameter
メソッドの役割となります.
正規分布オプティマイザの作成
では,aiaccel/parameter.py の HyperParameterConfiguration
クラスをもう少し詳しく見てみましょう.
sample
メソッドの他に,get_parameter_list
というメソッドがあります.
このメソッドは,sample
メソッドでハイパーパラメータをランダムに選択する前のハイパーパラメータのリストを返します.
/workspace/aiaccel/work/lib/my_optimizer/custom_optimizer.py
new_params = []
+ hp_list = self.params.get_parameter_list()
- sample = self.params.sample(rng=self._rng)
for s in sample:
次に正規分布を用いてハイパーパラメータを生成します.
aiaccel/parameter.py の HyperParameter
クラスでは numpy の random.RandomState.uniform
を実行していましたが,今回は正規分布なので numpy の random.RandomState.normal
を利用します.
/workspace/aiaccel/work/lib/my_optimizer/custom_optimizer.py
from __future__ import annotations
from aiaccel.optimizer.abstract_optimizer import AbstractOptimizer
class CustomOptimizer(AbstractOptimizer):
"""An optimizer class with a random algorithm.
"""
def generate_parameter(self) -> list[dict[str, float | int | str]]:
"""Generate parameters.
Returns:
list[dict[str, float | int | str]]: A list of created parameters.
"""
new_params = []
hp_list = self.params.get_parameter_list()
for hp in hp_list:
value = self._rng.normal(0, 0.1)
value = min(max(value, hp.lower), hp.upper)
new_param = {
'parameter_name': hp.name,
'type': hp.type,
'value': value
}
new_params.append(new_param)
return new_params
正規分布で生成したハイパーパラメータが,最大値・最小値を超えないよう修正を加えています.
/workspace/aiaccel/work/lib/my_optimizer/custom_optimizer.py
value = min(max(value, hp.lower), hp.upper)
正規分布オプティマイザの実行確認
それでは現在のディレクトリで実行してみます.
> pwd
/workspace/aiaccel/work/sphere
> aiaccel-start --config config.yaml --clean
正常に終了すれば成功です.
オプティマイザへの変数の導入
正規分布のオプティマイザの平均と分散の値はハードコーディングしていました. このようなオプティマイザに利用する変数はコンフィグレーションファイルや引数として渡したい値です.
ここでは平均と分散をコンフィグレーションファイルから与える方法について解説します.
まずコンフィグレーションファイルに以下の追加をします.
/workspace/aiaccel/work/sphere/config.yaml
optimize:
search_algorithm: "my_optimizer.CustomOptimizer"
goal: "minimize"
trial_number: 30
rand_seed: 42
+ mu: 3
+ sigma: 0.1
mu と sigma が追加されました. 次に custom_optimizer.py を編集して,mu と sigma を取得できるようにします.
/workspace/aiaccel/work/lib/my_optimizer/custom_optimizer.py
from aiaccel.optimizer.abstract_optimizer import AbstractOptimizer
import numpy as np
class CustomOptimizer(AbstractOptimizer):
"""An optimizer class with a random algorithm.
"""
def __init__(self, options: dict) -> None:
super().__init__(options)
self.mu = self.config.config.get('optimize', 'mu')
self.sigma = self.config.config.get('optimize', 'sigma')
init メソッドを追加し,コンフィグレーションから mu と sigma を取得し変数として保持しました.
あとは self._rng.normal
を呼ぶ際に mu と sigma を渡します.
/workspace/aiaccel/work/lib/my_optimizer/custom_optimizer.py
from aiaccel.optimizer.abstract_optimizer import AbstractOptimizer
import numpy as np
class CustomOptimizer(AbstractOptimizer):
"""An optimizer class with a random algorithm.
"""
def __init__(self, options: dict) -> None:
super().__init__(options)
self.mu = self.config.config.get('optimize', 'mu')
self.sigma = self.config.config.get('optimize', 'sigma')
def generate_parameter(self) -> None:
"""Generate parameters.
Args:
number (int | None): A number of generating parameters.
Returns:
None
"""
new_params = []
hp_list = self.params.get_parameter_list()
for hp in hp_list:
value = value = self._rng.normal(self.mu, self.sigma)
value = min(max(value, hp.lower), hp.upper)
new_param = {
'parameter_name': hp.name,
'type': hp.type,
'value': value
}
new_params.append(new_param)
return new_params
正規分布オプティマイザの実行確認
それでは現在のディレクトリで実行してみます.
> pwd
/workspace/aiaccel/work/sphere
> aiaccel-start --config config.yaml --clean
/workspace/aiaccel/work/sphere/workディレクトリに実行結果が保存されます. 前回事項した結果と異なることを確認してみてください.
オプティマイザ内部からの目的関数の値の参照
この節では,オプティマイザの内部から過去に計算した目的関数の値を参照して,次のパラメータを決定する方法を確認します.
aiaccel 上のジョブの ID が n
のときの目的関数の値は,AbstractOptimizer
を継承して作成したカスタムオプティマイザの内部から,次のようにして取得できます.
objective_value = self.storage.result.get_any_trial_objective(n)
この処理の後,objective_value
は n
で指定した目的関数の値か None
を保持します.
None
が保持されるのは,self.storage.result.get_any_trial_objective()
が呼ばれた時点で,目的関数の値を計算する user program が Storage に 計算結果を保存していない場合です.
例: 勾配降下法による最適化
勾配降下法では,着目する試行におけるパラメータが与える目的関数の勾配を元に,次のパラメータを決定します. 一次元の場合, \(n\) 試行目のパラメータを \(W_n\) とし,目的関数を \(f(W_n)\) と書くと, \(n+1\) 試行目のパラメータは
となります.ここで, \(\gamma\) は学習率 (パラメータの更新をどの程度行うかの指標), \(f'(W_n)\) は \(W_n\) における目的関数の勾配です.
ここでは \(f\) の解析的な形が分からない場合に,勾配を差分で置き換えることを考えます. 簡単のため,前進差分のみを考えると,差分を用いた勾配の近似式は
となります. 従って \(n + 1\) 試行目におけるパラメータは
と近似できます.
オプティマイザの実装
上の例では \(n + 1\) 試行目のパラメータを決定するために, \(f(W_n)\) と \(f(W_{n+1})\) という 2 つの目的関数の値を使用しました.
カスタムオプティマイザでは,これらをメソッド generate_parameter()
内で取得する必要があります.
以下に,前進差分を用いたオプティマイザの例を示します.
from __future__ import annotations
from enum import Enum, auto
import copy
from aiaccel.optimizer.abstract_optimizer import AbstractOptimizer
class SearchState(Enum):
PREPARE = auto()
CALC_FORWARD = auto()
WAIT_CURRENT_OBJECTIVE = auto()
WAIT_FORWARD_OBJECTIVE = auto()
CALC_NEXT_PARAM = auto()
class GradientDescent(AbstractOptimizer):
def __init__(self, options: dict) -> None:
super().__init__(options)
self.learning_rate = self.config.config.get(
'optimize', 'learning_rate')
self.delta: float = 1e-03
self.current_id: int = 0
self.current_params: list[dict[str, str | float]
] = self.generate_initial_parameter()
self.num_parameters = len(self.current_params)
self.forward_objectives: list[float] = []
self.num_generated_forwards: int = 0
self.num_calculated_forward_objectives: int = 0
self.forward_ids: list[int] = []
self.state: SearchState = SearchState.CALC_FORWARD
def generate_parameter(self
) -> list[dict[str, str | float]] | None:
if self.state == SearchState.PREPARE:
self.current_id = self.current_trial_id - 1
self.forward_objectives = []
self.num_generated_forwards = 0
self.num_calculated_forward_objectives = 0
self.forward_ids = []
self.state = SearchState.CALC_FORWARD
return None
if self.state == SearchState.CALC_FORWARD:
new_params = copy.deepcopy(self.current_params)
param = self.current_params[self.num_generated_forwards]
forward = {
'parameter_name': param['parameter_name'],
'type': param['type'],
'value': param['value'] + self.delta
}
new_params[self.num_generated_forwards] = forward
self.forward_ids.append(self.current_trial_id)
self.num_generated_forwards += 1
if self.num_generated_forwards == self.num_parameters:
self.state = SearchState.WAIT_CURRENT_OBJECTIVE
return new_params
if self.state == SearchState.WAIT_CURRENT_OBJECTIVE:
self.current_objective = self._get_objective(self.current_id)
if self.current_objective is not None:
self.state = SearchState.WAIT_FORWARD_OBJECTIVE
return None
if self.state == SearchState.WAIT_FORWARD_OBJECTIVE:
forward_id = self.forward_ids[
self.num_calculated_forward_objectives]
forward_objective = self._get_objective(forward_id)
if forward_objective is not None:
self.forward_objectives.append(forward_objective)
self.num_calculated_forward_objectives += 1
if (self.num_calculated_forward_objectives ==
self.num_parameters):
self.state = SearchState.CALC_NEXT_PARAM
return None
if self.state == SearchState.CALC_NEXT_PARAM:
new_params: list[dict[str, str | float]] = []
for param, forward_objective in zip(self.current_params,
self.forward_objectives):
grad = (forward_objective - self.current_objective
) / self.delta
value = param['value'] - self.learning_rate * grad
new_param = {
'parameter_name': param['parameter_name'],
'type': param['type'],
'value': value
}
new_params.append(new_param)
self.current_params = new_params
self.state = SearchState.PREPARE
return new_params
def _get_objective(self, index):
return self.storage.result.get_any_trial_objective(index)
@property
def current_trial_id(self):
return self.trial_id.integer
このオプティマイザは以下で説明する 4 つの状態を取ります.
PREPARE: オプティマイザが保持する変数やリストの初期化を行います.
CALC_FORWARD: \(W_n + \delta\) を計算します.
WAIT_CURRENT_OBJECTIVE: Storage に \(W_n\) のときの目的関数の値が保存されるまで待機します.
WAIT_FORWARD_OBJECTIVE: Storage に \(W_n + \delta\) のときの目的関数の値が保存されるまで待機します.
CALC_NEXT_PARAM: \(n+1\) 試行目のパラメータを計算します.
これらの状態を Enum
モジュールを用いて実装しています.
class SearchState(Enum):
PREPARE = auto()
CALC_FORWARD = auto()
WAIT_CURRENT_OBJECTIVE = auto()
WAIT_FORWARD_OBJECTIVE = auto()
CALC_NEXT_PARAM = auto()
オプティマイザが保持する変数は以下の通りです.
learning_rate: 学習率.
delta: 目的関数の前進値を計算するための変分 \(\delta\).
current_params: 現在 ( \(n\) 試行目) のパラメータ \(W_n\).
num_parameters: 最適化するパラメータの数.
forward_objectives: \(W_n + \delta\) における目的関数の値 \(f(W_n + \delta)\).
num_generated_forwards: 既に生成された \(W_n + \delta\) の数.
num_calculated_forward_objectives: 計算が完了した \(f(W_n + \delta)\) の数.
forward_ids: \(f(W_n + \delta)\) の計算が実行される aiaccel 上のジョブ ID (
trial_id
).
generate_parameter()
内の処理の流れ
状態: PREPARE
if self.state == SearchState.PREPARE:
self.current_id = self.current_trial_id - 1
self.forward_objectives = []
self.num_generated_forwards = 0
self.num_calculated_forward_objectives = 0
self.forward_ids = []
self.state = SearchState.CALC_FORWARD
return None
オプティマイザが保持する変数やリストの初期化を行います.
初期化を行った後,オプティマイザの状態を PREPARE
から CALC_FORWARD
に変更します.
この状態では,メソッド self.generate_parameters()
は必ず None
を返却します.
状態: CALC_FORWARD
if self.state == SearchState.CALC_FORWARD:
new_params = copy.deepcopy(self.current_params)
param = self.current_params[self.num_generated_forwards]
forward = {
'parameter_name': param['parameter_name'],
'type': param['type'],
'value': param['value'] + self.delta
}
new_params[self.num_generated_forwards] = forward
self.forward_ids.append(self.current_trial_id)
self.num_generated_forwards += 1
if self.num_generated_forwards == self.num_parameters:
self.state = SearchState.WAIT_CURRENT_OBJECTIVE
return new_params
パラメータの前進値 \(W_n + \delta\) を 1 回の呼び出しで 1 つだけ計算し,aiaccel のメインループに値を返却します.
まず,パラメータのリストから前進値を計算するパラメータを一つずつ取り出します.
new_params = copy.deepcopy(self.current_params)
param = self.current_params[self.num_generated_forwards]
ここで self.num_generated_forwards
は,既に生成されたパラメータの前進値の総数を表します.
続いて,項目 value
を \(W_n + \delta\) で置き換えます.
forward = {
'parameter_name': param['parameter_name'],
'type': param['type'],
'value': param['value'] + self.delta
}
new_params[self.num_generated_forwards] = forward
同時に,返却するパラメータの前進値を計算する aiaccel 上のジョブ ID (trial_id
) を保持します.
self.forward_ids.append(self.current_trial_id)
self.current_id
は,このカスタムオプティマイザ内で以下のように定義されるプロパティです.
@property
def current_trial_id(self):
return self.trial_id.integer
計算された前進値の数 self.num_generated_forwards
をインクリメントします.
self.num_generated_forwards += 1
全てのパラメータについて,その前進値が計算されたとき,オプティマイザの状態を CALC_FORWARD
から WAIT_CURRENT_OBJECTIVE
に変更します.
if self.num_generated_forwards == self.num_parameters:
self.state = SearchState.WAIT_CURRENT_OBJECTIVE
return new_params
注意: オプティマイザの状態が CALC_FORWARD
のとき,メソッド generate_parameters()
は最適化するパラメータの数と同じ回数だけ aiaccel のメインループに呼ばれます.
状態: WAIT_CURRENT_OBJECTIVE
if self.state == SearchState.WAIT_CURRENT_OBJECTIVE:
self.current_objective = self._get_objective(self.current_id)
if self.current_objective is not None:
self.state = SearchState.WAIT_FORWARD_OBJECTIVE
return None
現在のパラメータ \(W_n\) における目的関数の値 \(f(W_n)\) が Storage に保存されるまで待ち,その値を取得します.
self.current_objective = self._get_objective(self.current_id)
self._get_objective()
はカスタムオプティマイザ内で以下のように定義されるメソッドです.
def _get_objective(self, index):
return self.storage.result.get_any_trial_objective(index)
このメソッドは,取得したい目的関数の値の trial_id
(aiaccel 上のジョブ ID) を引数に取り,Storage から値を読み出します.
ただし,呼び出された時点で Storage に値が保存されていなければ,None
を返却します.
メソッド self._get_objective()
が目的関数の値を返した場合,オプティマイザの状態を WAIT_CURRENT_OBJECTIVE
から WAIR_FORWARD_OBJECTIVE
に変更します.
この時点で, \(f(W_n)\) の値はメンバ変数 self.current_objective
に保持されています.
if self.current_objective is not None:
self.state = SearchState.WAIT_FORWARD_OBJECTIVE
注意: オプティマイザが状態 WAIT_CURRENT_OBJECTIVE
のとき,メソッド self.generate_parameters()
は 1 回以上,Storage に対象とする目的関数の値が保存されるまで呼ばれます.
また,Storage から目的関数の値を読み出せたか否かに関わらず,WAIT_CURRENT_OBJECTIVE
状態の self.generate_parameters()
は None
をメインループに返します.
状態: WAIT_FORWARD_OBJECTIVE
if self.state == SearchState.WAIT_FORWARD_OBJECTIVE:
forward_id = self.forward_ids[
self.num_calculated_forward_objectives]
forward_objective = self._get_objective(forward_id)
if forward_objective is not None:
self.forward_objectives.append(forward_objective)
self.num_calculated_forward_objectives += 1
if (self.num_calculated_forward_objectives ==
self.num_parameters):
self.state = SearchState.CALC_NEXT_PARAM
return None
パラメータの前進値 \(W_{n} + \delta\) における目的関数の値 \(f(W_n + \delta)\) が Storage に保存されるのを待ち,その値を取得します.
まず,取得する目的関数の aiaccel 上のジョブ ID (trial_id
) をリストから読み出します.
forward_id = self.forward_ids[
self.num_calculated_forward_objectives]
ここで,self.num_calculated_forward_objectives
は取得済みの前進値に対する目的関数の値の総数です.
続いて,メソッド self._get_objective()
に読み出した ID を渡して,Storage から目的関数の値を読み出します.
forward_objective = self._get_objective(forward_id)
正常な値が返却された場合,返却された値をリストに保持し,取得済みの値の総数 self.num_calculated_forward_objectives
をインクリメントします.
if forward_objective is not None:
self.forward_objectives.append(forward_objective)
self.num_calculated_forward_objectives += 1
このとき,すべての目的関数の値が取得できていれば,オプティマイザの状態を WAIT_FORWARD_OBJECTIVE
から CALC_NEXT_PARAM
に変更します.
if (self.num_calculated_forward_objectives ==
self.num_parameters):
self.state = SearchState.CALC_NEXT_PARAM
注意: オプティマイザが状態 WAIT_FORWARD_OBJECTIVE
のとき,メソッド self.generate_parameters()
は少なくとも最適化対象のパラメータの総数以上,Storage にすべての目的関数の値が保存されるまで呼ばれます.また,Storage から目的関数の値が読み出せたか否かや,すべての値の読み出しが完了したか否かに依らず,WAIT_FORWARD_OBJECTIVE
状態の self.generate_parameters()
は None
をメインループに返します.
状態: CALC_NEXT_PARAM
if self.state == SearchState.CALC_NEXT_PARAM:
new_params: list[dict[str, str | float]] = []
for param, forward_objective in zip(self.current_params,
self.forward_objectives):
grad = (forward_objective - self.current_objective
) / self.delta
value = param['value'] - self.learning_rate * grad
new_param = {
'parameter_name': param['parameter_name'],
'type': param['type'],
'value': value
}
new_params.append(new_param)
self.current_params = new_params
self.state = SearchState.PREPARE
return new_params
Storage から読み出した \(W_n\) における目的関数の値 \(f(W_n)\) (self.current_params
) と \(W_{n+1}\) における目的関数の値 \(f(W_{n+1})\) (self.forward_objectives
) を用いて勾配を計算します.
new_params: list[dict[str, str | float]] = []
for param, forward_objective in zip(self.current_params,
self.forward_objectives):
grad = (forward_objective - self.current_objective
) / self.delta
計算した勾配を用いて次のパラメータ \(W_{n+1}\) を計算して dict
型オブジェクトを作成し,リストに保持します.
value = param['value'] - self.learning_rate * grad
new_param = {
'parameter_name': param['parameter_name'],
'type': param['type'],
'value': value
}
new_params.append(new_param)
オプティマイザの状態を CALC_NEXT_PARAM
から PREPARE
に変更し,作成した次のパラメータをメインループに返却します.
self.state = SearchState.PREPARE
return new_params
注意事項
一般に,パラメータの更新ステップ数 \(n\) と aiaccel 上のジョブ ID (trial_id
) は一致しないことに注意してください.
例えば上の例において,最適化したいパラメータの数が 5 個の場合,パラメータを1度更新するために目的関数を 5 回計算する必要があります.
この場合は 1 回のパラメータ更新で aiaccel の trial_id
は 5 増加することになります.
従って,config.yaml で指定した trial_number
が,例えば 30 回の場合,初期値を除いて 4 回しかパラメータは更新されません.
同様な ID の不一致は NelderMeadOptimizer を用いた際にも起こります.
Nelder-Mead 法の 1 ステップに相当する処理が終了したとき,aiaccel 上では trial_id
が パラメータ数 + 1 だけ増加します.
Issues
問題を発見した場合や追加機能の要望がある場合,すでに同様の issue が投稿されていないかの確認をお願いします. 同様のテーマが話し合われていない場合,新しい issue を作成してください.
バグの報告 (Bug report)
バグの報告では,以下の内容についての明確かつ簡潔な説明を含めてください.
バグの内容
バグを再現する手順
あなたが起こると期待したこと
実行環境
機能リクエスト (Feature request)
機能リクエストを行う際には,以下の内容についての明確かつ簡潔な説明を含めることを推奨します.
バグが関連する場合,バグの内容
実現したい機能の説明
検討した実装の説明
Pull request
aiaccel のコードを修正しリポジトリに反映して欲しい場合,pull request を実行してください. Pull request を行う際には,以下に注意してください.
手順
初めて開発に参加する場合
まず,GitHub 上で aiaccel をフォークします.
フォークした後,aiaccel のリポジトリを clone します.
git clone https://github.com/[YOUR USERNAME]/aiaccel.git
開発
ローカルのリポジトリを最新の状態に更新します.
git checkout main git pull upstream main
ブランチを作成します.
git checkout -b feature/add-new-feature
git add
およびgit commit
を使用し,進行に合わせてローカルでコミットします.コミットメッセージでは,変更の動機,バグの性質,または拡張機能の詳細を説明します.
メッセージは,コードを見なくても内容を理解できるように記述する必要があります.
投稿
Pull request を行う前に,以下を確認してください:
事前に issue などで他の開発者と議論したか?
MIT ライセンスで配布できるか?
適切なユニットテストは存在するか?
ユニットテストをローカル環境で実行できたか?
パブリックな関数は docstring を持っているか?
ドキュメンテーションは正しくレンダリングされるか?
コーディングスタイルは適切か?
コミットメッセージは適切か?
大規模な追加の場合,例 (docs/source/examples) やモジュールレベルの説明はあるか?
コンパイル済みのコードを追加する場合,setup.py を変更したか?
上記を確認した後:
GitHub 上のフォークに変更をプッシュします.
git push origin feature/add-new-optimizer
GitHub のユーザーネームとパスワードを入力します.
GitHub に移動します.以下に注意しながらタイトルとメッセージを記述します.
タイトル
変更を反映した簡単な説明を行うこと.
コードはバックフォートでラップすること.
ピリオドで終了しないこと.
説明
動機を書くこと.
変更点を書くこと.
関連する issue を閉じることができる場合,
Close #N
で issue を閉じること.作業が進行中 (work-in-progress) であるなら,残りのタスクを書くこと.
Pull request を送信します.
レビュープロセス
他の開発者は,pull request の実装,ドキュメント,コーディングスタイルを改善するためのコメントを投稿します.
Pull request したコードの更新を行う際は,ローカルリポジトリで変更をコミットし,ローカル環境でのテストが成功した場合にのみフォークへプッシュします.
aiaccel の開発チームのメンバー 1 人以上が pull request を検証し,承認された場合に main ブランチへマージされます.
ドキュメンテーション (WIP)
docstrings
実装した関数の基本的な説明,パラメータや返却値の型と意味,使用例を docstrings として記述します.
Google Python Style Guide に準拠する形で記述してください.
コーディング規約 も参考にしてください.
ドキュメント
ドキュメントのソースファイルは docs の下のディレクトリに作成します.
ドキュメントのファイル形式はマークダウン形式を推奨しています.
大規模な機能の追加があった場合,ドキュメントを作成してください.
レンダリングの確認
ドキュメントの追加や変更・修正があった場合には,ローカル環境でレンダリングが正常に行われるかを確認してください.
API リファレンスの生成を行うには,aiaccel に移動し,以下のコマンドを実行します.
cd aiaccel
sphinx-apidoc -f -o docs/source/api_reference aiaccel
ドキュメンテーションのレンダリングを確認するには,aiaccel/docs に移動し,HTML ファイルのビルドを行います.
cd docs
make html
ビルドされた HTML 形式のファイルは docs/build/html の下に生成されます.
多言語ドキュメントの生成を行うには,aiaccel/docs で以下のコマンドを実行します.
make gettext
sphinx-intl update -p build/gettext -l en -l ja
テスト
テストの追加
aiaccel では pytest を用いてテストを行います.
ユニットテストは tests の下のディレクトリに作成します.
aiaccel/tests/unit 以下のディレクトリ構造は,config.py などの一部のモジュールを除いて,aiaccel/aiaccel 以下の構造に対応します. 例えば,aiaccel/aiaccel/optimizer/abstract_optimizer.py のテストは aiaccel/tests/unit/optimzier_test/test_abstract_optimizer.py です.
新たな機能の追加,またはバグの修正を行った場合,テストコードを作成してください.
テストの実行 (WIP)
ローカル環境ですべてのテストコードを実行するには,aiaccel に移動し,以下のコマンドを実行します.
cd aiaccel
pytest
特定のテストコードのみを実行したい場合には,ファイル名を引数として指定します.
pytest tests/unit/optimizer_test/test_abstract_optimizer.py
さらに,コーディングスタイルのチェックを行うため,以下のコマンドを実行します.
pycodestyle aiaccel examples
flake8 aiaccel examples
追加コードに対するカバレッジ
コードカバレッジの厳密な基準は設定されていませんが,テストを設計する際にはこの値を十分に考慮します. 特に,以下のような場合は注意が必要です.
全体的なスコアが大幅に低下する場合.
あるクラスやモジュールのカバレッジが異常に低い場合.
テストが if 文の特定の分岐をカバーしていない場合.
カバレッジの測定
C0 カバレッジを測定するには,オプション --cov
を使用して pytest を実行します.
pytest --cov=aiaccel
特定のテストコードのみのカバレッジを測定するには,aiaccel の部分を適切なパスに置き換えます.
C1 カバレッジを測定するには,オプション --cov
に加えて --cov-branch
を使用して pytest を実行します.
pytest --cov=aiaccel --cov-branch
コーディング規約
基本的なルール
aiaccel のソースコードは Python で作成します.
コーディングスタイルは PEP8 に従います.
aiaccel では pycodestyle と flake8 を用いてコーディングスタイルの検証を行います.
下記の Docstrings についても確認してください.
aiaccel では型ヒントの検証は行いませんが,できる限り型ヒントを記述してください.
aiaccel ではバージョン 3.8 の Python をサポートするため,ビルトインな “
list
” などを型ヒントに使用する際は,future-import を行ってください.
ランダムな値の生成には
numpy.random.RandomState
を使用して下さい.これは aiaccel が利用しているライブラリ optuna との互換性を保つためです.
Docstrings
基本的には Google Python Style Guide に準拠する形で docstrings を記述します. ただし,以下の例外についても注意してください.
各モジュールの docstrings は必須ではありません.
Args:
セクションでは,パラメータ名の後ろにパラメータの型を括弧で括って記述します.必要に応じて
Example:
セクションを追加します.__init__
メソッドはクラスの docstring に含めます.__init__
メソッドには記述しません.Python オブジェクトへのリンクは sphinx-style なリンクを使用します.
エディタとして vscode を利用する場合,autoDocstring が docstring 生成の役に立ちます.
Example
class ExampleClass:
"""Summary of class.
There can be additional description(s) of this class.
Args:
param1 (type_of_param1): Description of `param1` which
is given when __init__ method is called.
param2 (type_of_param2): Description of `param2`.
Attributions:
param1 (type_of_param1): Description of `param1`.
param2 (type_of_param2): Description of `param2`.
param3 (type_of_param3): Description of 'param3`.
"""
def __init__(self, param1: type_of_param1, param2: type_of_param2):
self.param1 = param1
self.param2 = param2
self.param3 = generate_param3()
def method(self, arg1: type_of_arg1) -> type_of_return:
"""Recieves `type_of_arg1` object and returns return_of_method.
Args:
arg1 (type_of_arg1): Description of `arg1`.
Returns:
type_of_return: Description of return value. If this method
returns nothing, this section can be omitted.
Raise:
TypeOfException: Description of Exception.
"""
...
return return_of_method
qsubで実行中の計算ノードでコマンドを実行する方法
qsubで実行中の計算ノードでコマンドを実行する方法を説明します。
参照資料
インタラクティブノードからのqrsh -inherit
テスト時のqsub.sh
#!/bin/bash
#$ -l rt_C.small=1
#$ -l h_rt=1:00:00
#$ -j y
#$ -cwd
sleep 3600
テスト時のコマンド
> qsub -g your_group_id qsub.sh
Your job 10607396 ("qsub.sh") has been submitted
> qstat # with some omissions
job-ID prior name user state submit/start at queue
10608572 prior qsub.sh user r submit/start at gpu@g0001
> JOB_ID=10608572 SGE_TASK_ID=undefined qrsh -inherit g0001 /bin/bash
promptが表示されませんが、例えば、
> ls
とコマンドを入力すると、結果が出力されます。
終了時は必ず
> exit
/bin/bashなどのshellの場合の注意事項
キーボードからのControl-Cで、job自体の実行が停止されるようです。
そのため、終了には、exitコマンドを使用して下さい。コマンドプロンプトが出ないようです。
違和感が有りますが、コマンド-Enterでコマンドを実行できます。使用できないコマンド、出力が通常と違うコマンドが有ります。
SGE_LOCALDIRを定期的にHOMEなどにrsyncする方法
qsubで実行中の計算ノードの\(SGE_LOCALDIRの内容を\)HOMEなどに定期的にrsyncする方法を説明します。
ユーザプログラムが終了した後に、再度1度だけrsyncしています。
テスト時のqsub.sh
#!/bin/bash
#$ -l rt_C.small=1
#$ -l h_rt=1:00:00
#$ -j y
#$ -cwd
source /etc/profile.d/modules.sh
module load gcc/11.2.0
module load python/3.8/3.8.13
python3 rsync.py loop &
python3 test.py
kill $!
sleep 1
python3 rsync.py
テスト時のrsync.py
import os
import subprocess
import sys
import signal
import time
sleep_time = 15
src_dir = os.environ['SGE_LOCALDIR']
dst_dir = '~/test_rsync_dir'
proc = None
def do_rsync():
global proc
proc = subprocess.Popen(f'exec rsync -avh {src_dir}/ {dst_dir}', shell=True)
proc.wait()
def handler(signum, frame):
if proc is not None:
proc.terminate()
sys.exit()
signal.signal(signal.SIGTERM, handler)
a = sys.argv
if len(a) == 2 and a[1] == 'loop':
while True:
time.sleep(sleep_time)
do_rsync()
else:
do_rsync()
テスト時のユーザプログラムtest.py
import os
import pathlib
import time
sleep_time = 5
src_path = pathlib.Path(os.environ['SGE_LOCALDIR'])
for i in range(10):
(src_path/f'{i}-touch.txt').touch()
time.sleep(sleep_time)
テスト時のコマンド
> cd your_directory # with the above three files
> qsub -g your_group_id qsub.sh
# After the end
> ls ~/test_rsync_dir
0-touch.txt 2-touch.txt 4-touch.txt 6-touch.txt 8-touch.txt
1-touch.txt 3-touch.txt 5-touch.txt 7-touch.txt 9-touch.txt
> vi your_qsub_output_file
テスト時のvi your_qsub_output_fileの表示結果
sending incremental file list
created directory /your_home_directory/test_rsync_dir
./
0-touch.txt
1-touch.txt
2-touch.txt
3-touch.txt
sent 347 bytes received 149 bytes 992.00 bytes/sec
total size is 0 speedup is 0.00
sending incremental file list
./
4-touch.txt
5-touch.txt
6-touch.txt
sent 386 bytes received 76 bytes 924.00 bytes/sec
total size is 0 speedup is 0.00
sending incremental file list
./
7-touch.txt
8-touch.txt
9-touch.txt
sent 464 bytes received 76 bytes 360.00 bytes/sec
total size is 0 speedup is 0.00
sending incremental file list
sent 340 bytes received 12 bytes 704.00 bytes/sec
total size is 0 speedup is 0.00
aiaccel
aiaccel package
Subpackages
aiaccel.abci package
Submodules
aiaccel.abci.batch module
- aiaccel.abci.batch.create_abci_batch_file(batch_file: pathlib.Path, wrapper_file: str, commands: list, dict_lock: pathlib.Path) None
Create a ABCI batch file.
The ‘wrapper_file’ is a base of the ABCI batch file. At first, loads ‘wrapper_file’, and adds the ‘commands’ to the loaded contents. Finally, writes the contents to ‘batch_file’.
- Parameters
batch_file (Path) – A path of a creating file.
wrapper_file (str) – A wrapper file of ABCI batch file.
commands (list) – Commands to write in a batch file.
dict_lock (Path) – A directory to store lock files.
- Returns
None
aiaccel.abci.qstat module
- aiaccel.abci.qstat.parse_job_list(config: Config, job_list: Element) list[dict]
Parse from XML element of ‘qstat’ to a job list.
- Parameters
config (Config) – A Config object.
job_list (Element) – A XML element of ‘qstat’ command.
- Returns
A job list converted from a XML element of ‘qstat’ command.
- Return type
list
aiaccel.abci.qsub module
Module contents
aiaccel.cli package
Submodules
aiaccel.cli.plot module
aiaccel.cli.report module
aiaccel.cli.start module
aiaccel.cli.view module
Module contents
aiaccel.master package
Subpackages
Submodules
aiaccel.master.abci_master module
aiaccel.master.abstract_master module
aiaccel.master.create module
aiaccel.master.local_master module
aiaccel.master.pylocal_master module
Module contents
aiaccel.optimizer package
Submodules
aiaccel.optimizer.abstract_optimizer module
aiaccel.optimizer.create module
aiaccel.optimizer.grid_optimizer module
aiaccel.optimizer.nelder_mead_optimizer module
aiaccel.optimizer.random_optimizer module
aiaccel.optimizer.sobol_optimizer module
aiaccel.optimizer.tpe_optimizer module
Module contents
aiaccel.storage package
Submodules
aiaccel.storage.abstract module
aiaccel.storage.error module
- class aiaccel.storage.error.Error(file_name: pathlib.Path)
Bases:
aiaccel.storage.abstract.Abstract
- all_delete() None
Clear table
- Returns
None
- delete_any_trial_error(trial_id: int) None
- Returns
None
- get_any_trial_error(trial_id: int) str | None
Get error messages for any trial.
- Parameters
trial_id (int) – Any trial id
- Returns
- Return type
str | None
- get_error_trial_id() list
Obtain a list of trial ids in which an error occurred.
- Returns
trial id list
- Return type
trial_ids(list)
- set_any_trial_error(trial_id: int, error_message: str) None
Set any error message for any trial.
- Parameters
trial_id (int) – Any trial id
error_message (str) – Any error message
- Returns
None
aiaccel.storage.hp module
- class aiaccel.storage.hp.Hp(file_name: pathlib.Path)
Bases:
aiaccel.storage.abstract.Abstract
- all_delete() None
Clear table
- Returns
None
- delete_any_trial_params(trial_id: int) None
- Returns
None
- get_any_trial_params(trial_id: int) list[HpTable] | None
Obtain the set parameter information for any given trial.
- Parameters
trial_id (int) – Any trial id.
- Returns
- Return type
list[HpTable] | None
- set_any_trial_param(trial_id: int, param_name: str, param_value: Any, param_type: str) None
Set the specified parameter information for an any trial.
- Parameters
trial_id (int) – Any trial id
param_name (str) – Hyperparameter name.
param_value (Any) – Hyperparameter value
param_type (str) – Hyperparameter data type
- Returns
TrialTable | None
- set_any_trial_params(trial_id: int, params: list) None
aiaccel.storage.jobstate module
- class aiaccel.storage.jobstate.JobState(file_name: pathlib.Path)
Bases:
aiaccel.storage.abstract.Abstract
- delete_any_trial_jobstate(trial_id: int) None
- Returns
None
- get_all_trial_jobstate() list
- get_any_trial_jobstate(trial_id: int) str | None
Get the job status of any trial.
- Parameters
trial_id (int) – Any trial id
- Returns
Some kind of jobstate
- Return type
str | None
- is_failure(trial_id: int) bool
Whether the jobstate of the specified trial is Failuer or not.
- Parameters
trial_id (int) – Any trial id
- Returns
bool
- set_any_trial_jobstate(trial_id: int, state: str) None
Set the specified jobstate to the specified trial.
- Parameters
trial_id (int) – Any trial id
state (str) – Any jobstate
- Returns
None
- set_any_trial_jobstates(states: list) None
Set the specified jobstate to the specified trial.
- Parameters
trial_id (int) – Any trial id
state (str) – Any jobstate
- Returns
None
aiaccel.storage.model module
- class aiaccel.storage.model.ErrorTable(**kwargs)
Bases:
sqlalchemy.orm.decl_api.Base
- error
- trial_id
- class aiaccel.storage.model.HpTable(**kwargs)
Bases:
sqlalchemy.orm.decl_api.Base
- param_id
- param_name
- param_type
- param_value
- trial_id
- class aiaccel.storage.model.JobStateTable(**kwargs)
Bases:
sqlalchemy.orm.decl_api.Base
- state
- trial_id
- class aiaccel.storage.model.ResultTable(**kwargs)
Bases:
sqlalchemy.orm.decl_api.Base
- data_type
- objective
- trial_id
- class aiaccel.storage.model.TimestampTable(**kwargs)
Bases:
sqlalchemy.orm.decl_api.Base
- end_time
- start_time
- trial_id
aiaccel.storage.result module
- class aiaccel.storage.result.Result(file_name: pathlib.Path)
Bases:
aiaccel.storage.abstract.Abstract
- all_delete() None
Clear table
- Returns
None
- delete_any_trial_objective(trial_id: int) None
_summary_
- Parameters
trial_id (int) – _description_
- Raises
e – _description_
- get_all_result() list
Get all results
- Returns
list
- get_any_trial_objective(trial_id: int) int | float | None
Obtain the results of an arbitrary trial.
- Parameters
trial_id (int) – Any trial id
- Returns
- Return type
int | float | None
- get_bests(goal: str) list
Obtains the sorted result.
- Returns
result values
- Return type
list
- get_objectives() list
Get all results in list.
- Returns
result values
- Return type
list
- get_result_trial_id_list() list | None
Obtains the sorted result.
- Returns
result values
- Return type
list | None
- set_any_trial_objective(trial_id: int, objective: Any) None
Set any trial result value.
- Parameters
trial_id (int) – Any trial id
objective (Any) – ready, running, finished
- Returns
None
aiaccel.storage.storage module
aiaccel.storage.timestamp module
- class aiaccel.storage.timestamp.TimeStamp(file_name: pathlib.Path)
Bases:
aiaccel.storage.abstract.Abstract
- all_delete() None
Clear table
- Returns
None
- delete_any_trial_timestamp(trial_id) None
- get_any_trial_end_time(trial_id: int) str | None
Obtains the end time of the specified trial.
- Parameters
trial_id (int) – Any trial id
- Returns
“MM/DD/YYYY hh:mm:ss”
- Return type
end_time(str)
- get_any_trial_start_time(trial_id: int) str | None
Obtains the start time of the specified trial.
- Parameters
trial_id (int) – Any trial id
- Returns
“MM/DD/YYYY hh:mm:ss”
- Return type
start_time(str)
- set_any_trial_end_time(trial_id: int, end_time: str) None
Set the specified end time for the specified trial.
- Parameters
trial_id (int) – Any trial id
end_time (str) – “MM/DD/YYYY hh:mm:ss”
- Returns
None
- set_any_trial_start_time(trial_id: int, start_time: str) None
Set the specified start time for the specified trial.
- Parameters
trial_id (int) – Any trial id
start_time (str) – “MM/DD/YYYY hh:mm:ss”
- Returns
None
aiaccel.storage.trial module
aiaccel.storage.variable module
- class aiaccel.storage.variable.Serializer(file_name: pathlib.Path)
Bases:
object
- delete_any_trial_variable(trial_id) None
- register(process_name: str, labels: list) None
- class aiaccel.storage.variable.Value(file_name: pathlib.Path, label: str)
Bases:
aiaccel.storage.variable.Variable
- delete(trial_id: int) None
- get(trial_id: int) Any | None
- set(trial_id: int, value: Any, update_allow: bool = True) None
- set_process_name(process_name: str) None
- class aiaccel.storage.variable.Variable(file_name: pathlib.Path)
Bases:
aiaccel.storage.abstract.Abstract
- all_delete() None
Clear table
- Returns
None
- delete_any_trial_variable(trial_id: int, process_name: str, label: str) None
- get_any_trial_variable(trial_id: int, process_name: str, label: str)
- set_any_trial_variable(trial_id: int, process_name: str, label: str, value: Any, update_allow: bool)
Module contents
Submodules
aiaccel.common module
Common variables and methods.
Import this as follows:
import aiaccel
aiaccel.config module
- class aiaccel.config.BaseConfig
Bases:
object
An interface for all config classes.
Fork by confile: https://github.com/777nancy/confile
- abstract get_property(key, *keys)
- abstract to_dict()
- class aiaccel.config.Config(config_path: str | Path, warn: bool = False, format_check: bool = False)
Bases:
object
Defines the configuration of a configuration file.
- Parameters
config_path (str | Path) – A path of configuration file.
warn (bool, optional) – A flag of print a warning or not. Defaults to False.
format_check (bool, optional) – A flag of do tha check format or not. Defaults to None.
- config_path
Path to the configuration file.
- Type
Path
- config
- Type
- workspace
- Type
- define_items(config: aiaccel.config.ConfileWrapper, warn: bool) None
Define the configuration of the configuration file
- Parameters
config (ConfileWrapper) –
warn (bool) – A flag of print a warning or not. Defaults to False.
- class aiaccel.config.ConfigEntry(config: ConfileWrapper, type: list, default: Any, warning: bool, group: str, keys: list | tuple | str)
Bases:
object
A class for defining values in a configuration file or for holding read values.
- Parameters
config_path (str) – A path of configuration file.
type (list) – A data type.
default (Any) – A default value.
warning (bool) – A flag of print a warning or not.
group (str) – A name of the group to which the parameter belongs.
keys (tuple) – A key to access the value For example, a parameter under ‘generic’ would be written as (‘generic’)
Example
workspace = ConfigEntry( config=config, type=[str], default=_DEFAULT_WORKSPACE, warning=warn, group="generic", keys=("workspace") ) workspace.get()
- property Value
- empty_if_error()
If the value is not set, it will force an error to occur.
- get() Any
- Returns
self._value
- load_config_values()
Reads values from the configuration file.
- set(value) None
- Args
value (any)
- show_warning() None
If the default value is used, a warning is displayed.
- class aiaccel.config.ConfileWrapper(config: Any, config_type: str)
Bases:
object
A wrapper class for confile library.
Thins wrapper class supports to load a configuration file in JSON object, JSON file and YAML format. It provides a simple method ‘get’ to get a property for the specified keys.
- Parameters
config (Any) – A file path to configuration file.
config_type (str) – A file path to default configuration file.
- get(key: str, *keys: str) str | list | dict | None
Get a property with specified keys.
- Parameters
key (str) – A key for the property
*keys (list) – Nested eys for the property
- Returns
A property for the specified keys.
- Return type
str | list | dict | None
- class aiaccel.config.JsonOrYamlObjectConfig(config: dict, file_type: str)
Bases:
aiaccel.config.BaseConfig
A wrapper for confile to support json, yaml object.
Fork by confile: https://github.com/777nancy/confile
- Parameters
config (dict) – A json or yaml object
file_type (str) – ‘json_object’ or ‘yaml_object’.
- get_property(key: str, *keys: str) str | list | dict | None
Get a property for specified keys.
- Parameters
key (str) – A key to get a property.
*keys (str) – Keys to get a property.
- Returns
A property for the keys.
- Return type
str | list | dict | None
- to_dict() dict
Convert the configuration to a dictionary object.
- Returns
The dictionary object of the configuration.
- Return type
dict
- aiaccel.config.load_config(config_path: str) aiaccel.config.ConfileWrapper
Load any configuration files, return the ConfileWrapper object. :param config_path: A path to a configuration file. :type config_path: str
- Returns
A wrapper object of the configuration.
- Return type
aiaccel.module module
aiaccel.parameter module
- class aiaccel.parameter.HyperParameter(parameter: dict[str, bool | int | float | list])
Bases:
object
A hyper parameter class.
- Parameters
parameter (dict) – A parameter dictionary in a configuration file.
- _raw_dict
A parameter dictionary in a configuration file.
- Type
dict
- name
A parameter name.
- Type
str
- type
A parameter type any of ‘INT’, ‘FLOAT’, ‘CATEGORICAL’ and ‘ORDINAL’.
- Type
str
- log
A parameter is logarithm or not.
- Type
bool
- lower
A lower value of a parameter.
- Type
float | int
- upper
A upper value of a parameter.
- Type
float | int
- choices
This is set as a list of a parameter, when a parameter type is ‘CATEGORICAL’.
- Type
list[float, int, str]
- sequence
This is set as a list of a parameter, when a parameter type is ‘ORDINAL’.
- Type
list[float, int, str]
- initial
A initial value. If this is set, this value is evaluated at first run.
- Type
float | int | str
- q
A quantization factor.
- Type
float | int
- sample(initial: bool = False, rng: Optional[numpy.random.mtrand.RandomState] = None) dict
Sample a parameter.
- Parameters
initial (bool) – This is set, when a initial value is required.
rng (np.random.RandomState) – A reference to a random generator.
- Returns
A parameter dictionary.
- Return type
dict
- Raises
TypeError – Causes when an invalid type is set.
- class aiaccel.parameter.HyperParameterConfiguration(json_string: dict)
Bases:
object
A configuration of hyper parameters.
- Parameters
json_string (dict) – A configuration dictionary of hyper parameters.
- json_string
A configuration dictionary of hyper parameters.
- Type
dict
- hps
Hyper parameters.
- Type
dict
- get_hyperparameter(name: str) aiaccel.parameter.HyperParameter
Get a hyper parameter with a name.
- Parameters
name (str) – A hyper parameter name.
- Returns
A matched hyper parameter object.
- Return type
- Raises
KeyError – Causes when no matched hyper parameter is.
- get_parameter_dict() dict
Get a dictionary of hyper parameters.
- Returns
A hyper parameter dictionary.
- Return type
dict
- get_parameter_list() list[HyperParameter]
Get a list of hyper parameter objects.
- Returns
A list of hyper parameter objects.
- Return type
list[HyperParameter]
- sample(initial: bool = False, rng: np.random.RandomState = None) list[dict]
Sample a hyper parameters set.
- Parameters
initial (bool, optional) – This is set, when a initial value is required.
rng (np.random.RandomState) – A reference to a random generator.
- Returns
A hyper parameters set.
- Return type
list[dict]
- aiaccel.parameter.get_best_parameter(files: list[Path], goal: str, dict_lock: Path) tuple[float | None, Path | None]
Get a best parameter in specified files.
- Parameters
files (list[Path]) – A list of files to find a best.
goal (str) – Maximize or Minimize.
dict_lock (Path) – A directory to store lock files.
- Returns
A best result value and a file path. It returns None if a number of files is less than one.
- Return type
tuple[float | None, Path | None]
- Raises
ValueError – Causes when an invalid goal is set.
- aiaccel.parameter.get_type(parameter: dict) str
Get a type of a specified parameter.
- Parameters
parameter (dict) – A parameter dictionary in a configuration file.
- Returns
A parameter type any of ‘INT’, ‘FLOAT’, ‘CATEGORICAL’ and ‘ORDINAL’.
- Return type
str
- aiaccel.parameter.load_parameter(json_string: dict) aiaccel.parameter.HyperParameterConfiguration
Load HyperParameterConfiguration object from a configuration file.
- Parameters
json_string (dict) – A hyper parameter configuration.
- Returns
A hyper parameter configuration.
- Return type
aiaccel.workspace module
- class aiaccel.workspace.Workspace(base_path: str)
Bases:
object
Provides interface to workspace.
- Parameters
base_path (str) – Path to the workspace.
- path
Path to the workspace.
- Type
Path
- alive
Path to “alive”, i.e. path/alive.
- Type
Path
- error
Path to “error”, i.e. ‘path`/error.
- Type
Path
- hp
Path to “hp”, i.e. path/hp.
- Type
Path
- hp_ready
Path to “ready”, i.e. path/hp/ready.
- Type
Path
- hp_running
Path to “running”, i.e. path/hp/running.
- Type
Path
- hp_finished
Path to “finished”, i.e. path/hp/finished.
- Type
Path
- jobstate
Path to “jobstate”, i.e. path/jobstate.
- Type
Path
- lock
Path to “lock”, i.e. path/lock.
- Type
Path
- log
Path to “log”, i.e. path/log.
- Type
Path
- output
Path to “abci_output”, i.e. path/abci_output.
- Type
Path
- pid
Path to “pid”, i.e. path/pid.
- Type
Path
- result
Path to “result”, i.e. path/result.
- Type
Path
- runner
Path to “runner”, i.e. path/runner.
- Type
Path
- storage
Path to “storage”, i.e. path/storage.
- Type
Path
- timestamp
Path to “timestamp”, i.e. path/timestamp.
- Type
Path
- verification
Path to “verification”, i.e. path/verification.
- Type
Path
- consists
A list of pathes under the workspace.
- Type
list[Path]
- results
Path to the results which is prepared in the execution directory, i.e. “./results”.
- Type
Path
- check_consists() bool
Check required directories exist or not.
- Returns
All required directories exist or not.
- Return type
bool
- clean() None
Delete a workspace.
It is assumed to be the first one to be executed.
- create() bool
Create a work directory.
- Returns
None
- Raises
NotADirectoryError – It raises if a workspace argument (self.path) is not a directory.
- exists() bool
Returns whether workspace exists or not.
- Returns
True if the workspace exists.
- Return type
bool
- move_completed_data() Path | None
Move workspace to under of results directory when finished.
- Raises
FileExistsError – Occurs if destination directory already exists when the method is called.
- Returns
Path of destination.
- Return type
Path | None
aiaccel.wrapper_tools module
- aiaccel.wrapper_tools.create_runner_command(command: str, param_content: dict, trial_id: int, config_path: str, command_error_output: str) list[str]
Create a list of command strings to run a hyper parameter.
- Parameters
command (str) – A string command.
param_content (dict) – A hyper parameter content.
trial_id (str) – A unique name of a hyper parameter.
- Returns
A list of command strings.
- Return type
list[str]
- aiaccel.wrapper_tools.save_result(ws: pathlib.Path, dict_lock: pathlib.Path, trial_id_str: str, result: float, start_time: str, end_time: str, err_message: str = '') None
Save a result file.
- Parameters
ws (Path) – A path of a workspace.
dict_lock (Path) – A directory to store lock files.
trial_id_str (str) – An unique name of a parameter set.
result (float) – A result of a parameter set.
start_time (str) – A start time string.
end_time (str) – An end time string.
err_message (str) – Error message from Wrapper (user program)
- Returns
None
Module contents
索引と検索
謝辞
この成果の一部は、国立研究開発法人新エネルギー・産業技術総合開発機構(NEDO)の委託業務として開発されたものです。
TPEアルゴリズムは Optuna を利用しました。