スラきちの野望

技術系で紹介したいこととか、遊んだゲームなどを載せていくブログです。

apt-getでBoost C++を入れるときにハマった話

どうも( ^ω^)

つい最近Boost C++ ライブラリを必要とする機会があり、
apt-getを使って入れたのですが、
必要だったヘッダファイル(具体的にはprocess.hpp)が見つからない
といった問題が発生しました。

  • OS: Ubuntu16.04
  • パッケージ: libboost-dev

インストール先のディレクトリで検索をかけてみても引っかからなかったので、
そもそもパッケージに入ってなかったみたいです。
しかもバージョンが1.58なのでちょっと古い。


そこで以下のサイトの記述を参考に、
Github上にあるBoost最新版をクローンしてきてビルドするという手順を踏みました。
(バージョンは2017/11/19時点で1.66)
Ubuntuでc++17のために最新版のg++, boost, cmakeを自然に使う - Qiita

ビルド時のコマンド
1. 適当なディレクトリで
  git clone --recursive https://github.com/boostorg/boost.git
2. 生成されたboostディレクトリ内で
 ./bootstrap.sh
3. ./b2
4. sudo ./b2 install

ビルドをする手順は公式ページにも載っています。
1と3にやたら時間が掛かかりました。

しかし、これでもprocess.hppが存在しないと言われます。
悲しい。


いろいろと調べたところ、
Boostのprocessのみを扱う以下のリポジトリを見つけます。
GitHub - klemens-morgenstern/boost-process: Boost.Process is a library to manage system processes

ここにあるprocess.hppをBoostのデフォルトインストール先である/usr/local/include にコピーしました。
これでいけるだろ!と思いましたがBoostを使用するソースコードコンパイルする時に謎のエラーに見舞われます。


process.hppはバージョンが1.64のものらしいのでそこが原因と思い、
以下のサイトで1.64のBoostを持ってくることにしました。
Boost C++ Libraries - Browse /boost at SourceForge.net

ファイル形式はtar.bz2でダウンロードしたので、
tar --bzip2 -xf boost_1_64_0.tar.bz2 コマンドで解凍し、再びビルドします。

するとあら不思議、中にprocess.hppが入ってるじゃありませんか!

そしてビルド後すぐにコンパイルを試してみると普通に通りました。
なんでGithubのやつには入ってなかったんですかねぇ( ´_ゝ`)


ということで、
Boostをインストールするときは、apt-getやGithubのものではなく、
tar.bz2形式のものをダウンロードしたほうが良いかもというお話でした。


追記:
boostを入れた理由として、SamurAI Coding というコンテストに参加するための環境構築に必要だったという訳があったのですが、 boost1.64.0だとmakeによるコンパイルは通るけれど、実行できないという問題が発生します。

原因として、boost最新版(1.65.1)と1.64.0の間でコマンドラインパーサの仕様が変わっているらしく、そこで問題が発生しているようでした(たぶん)。

なので、もしこのコンテスト用にboostを新しく入れるという人がいましたら、以下のboost公式サイトからver1.65.1でtar.bz2方式のファイルをダウンロードし、ビルドすることをおすすめします。
Boost C++ Libraries

勾配降下法に使われる最適化アルゴリズムを比較する簡単な実験をしてみた

こんにちは( ^ω^)

この記事は、勾配降下法を最適化するアルゴリズムを、
2つのベンチマーク関数を使って比較し、まとめたものです。

計算の経過をみるために、
最適化するベンチマーク関数は2変数関数に限定し、
3次元グラフに計算の経過をプロットし記事に載せています。

ニューラルネットワークの学習を行うときなどには
最適化するパラメータは膨大な数となるため、
今回の比較で得た各アルゴリズムの良し悪しは実際の学習には適用できないと思います。
あくまで参考程度にしていただければ幸いです。

勾配降下法がよくわからないという方はこちらを参考にしてみてください
勾配降下法って? - スラきちの野望

たここで使用しているアルゴリズムは以下のサイトを参考にさせていただきました
勾配降下法の最適化アルゴリズムを概観する | コンピュータサイエンス | POSTD

目次

使用した最適化アルゴリズム

  • 最急降下法 (x_{t+1}=x_t - \eta \nabla_{x_t} f(x_t))
  • Momentum (γ=0.9)
  • NAG (γ=0.9)
  • Adagrad
  • Adadelta (γ=0.9)
  • RMSprop (γ=0.9)
  • Adam (B_1=0.9, B_2=0.999)

ベンチマーク関数

以下の2つの関数を使用しています

Ackley関数

式:
 f(x_1, x_2)=20-20 exp(-0.2 \sqrt{\frac{1}{2}({x_1}^2 + {x_2}^2)}) + e
       - exp(\frac{1}{2}(cos(2\pi x_1) + cos(2\pi x_2)))

最適解:
 f_{min}(0,0) = 0

初期値:
 (20.0, 20.0)

勾配:
 \frac{\partial f}{\partial x_1} = \frac{(2.82843{x_1}exp(-0.141424 \sqrt{{x_1}^2 + {x_2}^2}))} {\sqrt{{x_1}^2 + {x_2}^2}} + \pi sin(2\pi{x_1})exp(\frac{1}{2}(cos(2 \pi {x_1}) + cos(2 \pi {x_2})))
 \frac{\partial f}{\partial x_2} = \frac{(2.82843{x_2}exp(-0.141424 \sqrt{{x_1}^2 + {x_2}^2}))} {\sqrt{{x_1}^2 + {x_2}^2}} + \pi sin(2\pi{x_2})exp(\frac{1}{2}(cos(2 \pi {x_1}) + cos(2 \pi {x_2})))
 ※面倒だったので勾配はWoframeAlphaさんを使って求めました

f:id:CAPsp:20171014164945p:plain

Rosenbrock関数

式:
 f(x_1, x_2)=100(x_2-{x_1}^2)^2 + (x_1 - 1)^2

最適解:
 f_{min}(1,1) = 0

初期値:
 (5.0, 5.0)

勾配:
 \frac{\partial f}{\partial x_1} = -400x_1(x_2 - {x_1}^2) + 2x_1 - 2
 \frac{\partial f}{\partial x_2} = 200(x_2 - {x_1}^2) f:id:CAPsp:20171014185504p:plain

以下のサイトにベンチマーク関数のまとめが載ってあります
最適化アルゴリズムを評価するベンチマーク関数まとめ - Qiita

比較結果

学習率は0.1として、
初期値から各アルゴリズムを使って最小値を求めます。

最小値の座標と計算中の座標との大きさが1未満になったときに収束したとする場合、
10000回タイムステップを進めたときの結果は

Ackley関数 Rosenbrock関数
最急降下法 収束せず 計算途中でオーバーフロー
Momentum 142ステップで収束 計算途中でオーバーフロー
NAG 1569ステップで収束 計算途中でオーバーフロー
Adagrad 収束せず 収束せず
Adadelta 収束せず 収束せず
RMSprop 収束せず 129ステップで収束
Adam 収束せず 8714ステップで収束

なお、学習率をいろいろ変えて試してみたところ、 学習率0.4付近だとRmspropと再急降下法がAckley関数の収束に成功していました。
その他は収束が早くなったり遅くなったりはありましたが、新たに収束に成功しているものはありませんでした。

経過のプロット

  • 赤:最急降下法
  • 青:Momentum
  • 緑:NAG
  • 黒:Adagrad
  • 白:Adadelta
  • ピンク:RMSprop
  • 黄色:Adam

Ackley function

f:id:CAPsp:20171014184309g:plain

収束しているNAGとMomentumは、しっかりと最小値に移動している様子が見れると思います。

Rosenbrock function

f:id:CAPsp:20171014184735g:plain
NAGがどっかに飛んでいってるのはなんでなんですかね( ^ω^)

まとめ

なんとも言えない結果になってしまいました、
全体的にみればRMSpropが良いっちゃ良いです。

収束していないものの多くはタイムステップを進めても座標がほとんど変化していなかったので、局所解に陥ってしまったのだと思います。

そういった状況にならないためには、適切な学習率やパラメータを設定する必要があると思うのですが、いろんなサイトを回ってもそれの確かめ方はわかりませんでした。

現状試行錯誤するしかないのでしょうかね?

ここまで記事を見てくださってありがとうございました!

勾配降下法って?

こんにちは( ^ω^)

何番煎じかわかりませんが、
ニューラルネットワークの学習などに使われる
「勾配降下法」というアルゴリズムについて簡単にまとめてみました。


勾配降下法とは

例えば、とある2次関数(y=ax^2+bx+c)の最小値をもとめるという問題があるとします。
この問題はこの関数が下に凸であった場合、頂点をもとめることで解析的に解くことができます。

しかし、関数の次元が増えたりして複雑になると解析的に解くことは難しくなります。
そこで関数の最小値をもとめる行為(最適化)を勾配を使ってやってみようというものが勾配降下法といわれるものになります。

具体的に勾配を使ってどう解くのかを簡単な例で示してみます。

f:id:CAPsp:20170925180931p:plain

これはy=x^2のグラフです。
最小値はx=0となるところです。

この関数の傾き(勾配)は2xとなります。
勾配は簡単に言えばグラフの傾斜の度合いを表す数値なので、 適当なxを選びそこから傾斜に沿ってグラフを下っていくように動けばなんとなく最小のxに辿り着けそうな気がします。

この考えを実際の式に置き換えてみます。

x^{t+1}=x^t - \eta 2x    (1)

\etaというのはどの程度動くのかを表す定数です。
これが小さすぎると最小値にたどり着くのが遅くなり、逆に大きすぎると最小値付近で右往左往することになります。

この手法の手順をまとめると、
1. 適当なxをとる
2. 値がある程度収束するまで(1)の式を使ってxを更新する

となります。

この手法は最急降下法と呼び、勾配を用いる最適化アルゴリズムの代表的なものです。

実際にx^0=10\eta=0.05とおき、100回ほどxの値を更新をしたときの経過は以下のようになります。

f:id:CAPsp:20170925180933g:plain

赤い点はその時のxと対応するyの値をプロットしたものです。
徐々に最小値に近づいているのが見て取れると思います。

勾配降下法は勾配さえ計算できれば、次元数が増えたとしても適用できます。

ニューラルネットワークで扱う場合、そのときのネットワークの出力と教師解にどれほどの差があるのかを表現する誤差関数というものを導入し、この誤差関数の出力を勾配降下法を使って最小に近づけることで学習を表現しています。

自己紹介

あいさつ

こんにちは( ^ω^)

 

自己紹介

キャップと申す者です。

 

周りの人がブログで様々な情報を発信してて楽しそうだったので、

自分も始めてみました。

 

普段の生活でも日本語の扱いが怪しい自分が良い記事を書けるのかは怪しいところですが、

投稿頑張りたいと思います!

 

プロフィール

性別   :男

年齢   :20前半

職業   :院生

趣味   :ゲーム遊んだり作ったり、丸いもの収集(スライムとか)

興味   :機械学習、AI、ゲーム開発、プログラミング全般

好きな物 :スライム、カービィ、ゲーム、コマンドー、( ^ω^)←これ

 

これから 

更新頻度は多くないと思いますが、

技術系で紹介したいこととか、遊んだゲームとか、好きなものについてを記事にしていきたいです。

 

 

ではでは( ^ω^)ノシ