パラメータの最適化とExcelへの出力方法
はじめまして、大学院1年生です。
専攻は土木ですが、凝り固まった土木業界に機械学習の導入を目指しています。
はじめに
私は地盤工学の解析手法の一つとして機械学習を導入しています。専門は土木で(専門というもののたかが大学院生)、機械学習はあくまで一手法なので非常に未熟です。温かい目で見ていただければ幸いです。
また、不備等ありましたらコメントお願いします。
概要
言語:Python
ライブラリ:TensorFlow
解析手法:回帰分析(入力12変数、出力1変数)
目標
1.説明変数を減らす感度分析を行いたい。でもいちいちハイパーパラメータを最適化するのがめんどくさいため、半自動的にできるようにしたい。
2.各条件の比較は結果の平均絶対誤差と決定係数で行う。なので、解析ごとに使用したパラメータ値と結果をExcelに出力させたい。
最適化するもの
・層数 (1~8層を検討)
・バッチサイズ (16~128を検討)
・ノード数 (50~250を検討)
・初期学習率 (0.005~0.05を検討)
最適化手法
「ハイパーパラメータ最適化の手法はなく、試行錯誤的な決定が望ましい」
と先輩にうかがったため、複数組み合わせてパラメータを決定します。
for hidden_nodes in range(50,300,50): #ノード数を50,100,150,200,250
for batch_size in [16,32,64,128]: #バッチサイズを16,32,64,128
for first_lr in [0.005, 0.01, 0.05]: #初期学習率を0.005, 0.01, 0.05
こんな感じでパワーでfor文に当てはめました。最終のインデントの中に基幹となる計算を埋め込めば動きます。
これだと、5*4*3の60通りを回すのでモノによってはだいぶ時間がかかります。
また、層数は入っていません。なぜなら現状の層形式が
layer_1_drop=tf.nn.dropout(layer_1,rate=layer_1_rate)#第1層に対するDropoutを設定
weight_2 = __init__weight(shape=[hidden_nodes, hidden_nodes], st_dev=(2/hidden_nodes)**0.5)#標準偏差は√(2/hidden_nodes)(=前層のノード数)とした
bias_2 = __init__bias(shape=[hidden_nodes], st_dev=(2/hidden_nodes)**0.5)
layer_2 = fully_connected(layer_1_drop, weight_2, bias_2) #Dropoutを考慮
このように汎用性を利かせられない形式になっているからです。今は層数のみ逐次手打ちで変更しています。いつか簡略化したいです。def関数でできるんですかね?
加えて、ドロップアウトの考慮もしないといけないので、ある説明変数に対しては層数*2(DropOut ありなし)の数だけ解析を回す必要があります。
僕の例では層数は(1,2,4,6,8)において結果を観たいので10回の解析が必要です。
これも捉え方次第ですが、for文を使ってなかったら600回手を動かす必要があったのでだいぶましです。
出力
解析は回せましたが、いかにExcelに出力させるか。
出力させたいもの
・最終の教師損失関数
→未学習でないか、学習は終えているかの確認
・最終のテスト損失関数
→発散していないかの確認
・MAE(平均絶対誤差)
→精度比較に利用。基本的にこれが小さいやつを最適としたい。
・R2(決定係数)
→サブの精度比較に利用。
1試行ごとに4つの数値を得たいわけです。
イメージとしては、見てわかるように用いたハイパーパラメータの値とこれら4つを1行にどんどん追加させていきたい。
出力方法
(一部)
#一行目の列名指定
active_sheet['A1']='hidden-nodes'
active_sheet['B1']='batch-size'
active_sheet['E1']='平均絶対誤差(MAE)'
active_sheet['F1']='決定係数(R^2)'
#2行目に順次追加していく
active_sheet.cell(row=2, column=1).value = hidden_nodes
active_sheet.cell(row=2, column=2).value = batch_size
active_sheet.cell(row=2, column=5).value = MAE
active_sheet.cell(row=2, column=6).value = decr2
#2行目に1行空の行を挿入
active_sheet.insert_rows(2, amount=1)
#ここで、MAEとdecr2は前もって定義してます。
アクティブシートを使用しているのはこれまでの解析でテストデータの値と予測値をExcelに出力させていたからです。名残です。わからないですが、普通のシートで動くと思います。
結果論ですが、結構簡単でした。でも考え付くのに1時間ほどかかって、コードが完成するまで2時間ほどかかりました。
一番のみそは空行の挿入ですね。末行に追加していくのではなくて、上から降ろしていくイメージです。
まとめ
ある程度の作業効率化は図れました。簡単なことに置き換えて、できそうなパターンで試行を繰り返すことが大事だと思いました。