ソフトウェアエンジニアの勉強ログ

興味があるのは、computer vision, three.js, python, 深層学習, emacs

Google Apps Script (GAS) をローカルで開発する環境を整えた

突然ですが、GoogleのSpreadsheet便利ですよね。 私はSpreadsheet上でオリジナルの家計簿を作っているのですが、いかんせんブラウザ上でプログラミングするのが辛い… ローカルで開発でできないかなと調べたら以下の方法があることを知りました。

qiita.com

早速、claspなるものを導入しました。 結構簡単に導入できるのでおすすめです。

ついでにemacsjavascriptのインデントを4から2に変更しました。

stackoverrun.com

.init.elのような場所を直接編集する方法もいいですけど、 変更しても反映されたりされなかったりが面倒そうだったので、 「M-x customize-group」から変更するのが確実な気がして、そっちを採用しました。

ROSを試してみたがインストールでこけてしまった

久々の更新ですが、ただの自分用備忘録です。

ROSを試してみようと思って、以下のサイトを参考にROSをインストールした

ja/kinetic/Installation/Ubuntu - ROS Wiki

その後、catkinが必要だったような気がして、

apt-get install catkin

とすると、以下のエラーでインストールができない。

パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています                
状態情報を読み取っています... 完了
インストールすることができないパッケージがありました。おそらく、あり得
ない状況を要求したか、(不安定版ディストリビューションを使用しているの
であれば) 必要なパッケージがまだ作成されていなかったり Incoming から移
動されていないことが考えられます。
以下の情報がこの問題を解決するために役立つかもしれません:

以下のパッケージには満たせない依存関係があります:
 catkin : 依存: python-catkin-pkg しかし、インストールされようとしていません
E: 問題を解決することができません。壊れた変更禁止パッケージがあります。

なんとなくバージョンの依存関係で矛盾が生じてしまっているのはわかるが、 どうすればよいかわからない。 調べてみると以下のサイトを見つけた。

Ubuntuで依存関係が壊れている時の対応 - tizen.moe

早速

aptitude install catkin

一度目の選択肢に対して「.」を押して、次の選択肢を表示させると以下のようなメッセージが。。。

以下のアクションでこれらの依存関係の問題は解決されます:

       以下のパッケージを削除する:                                       
1)       python-catkin-pkg-modules                                       
2)       python-rosdep                                                   
3)       python-rosdistro                                                
4)       python-rosdistro-modules                                        
5)       ros-kinetic-actionlib                                           
6)       ros-kinetic-actionlib-tutorials                                 
...
134)     ros-kinetic-turtlesim                                           
135)     ros-kinetic-urdf                                                
136)     ros-kinetic-urdf-tutorial                                       
137)     ros-kinetic-visualization-tutorials                             
138)     ros-kinetic-viz                                                 
139)     ros-kinetic-xacro                                               

       以下のパッケージをインストールする:                               
140)     python-funcsigs [0.4-2 (xenial)]                                
141)     python-mock [1.3.0-2.1ubuntu1 (xenial)]                         
142)     python-pbr [1.8.0-4ubuntu1 (xenial)]                            

       以下のパッケージをダウングレードする:                             
143)     python-catkin-pkg [0.4.1-100 (now, xenial) -> 0.2.10-2 (xenial)]
144)     python-rosinstall [0.7.8-1 (now, xenial) -> 0.7.7-1 (xenial)]   


この解決方法を受け入れますか? [Y/n/q/?] 

さすがにこれは受け入れられない。。。

ここで一度、ROSのインストール記事を見ているときに手動でcatkinを入れろと書いていないなと思い、 そのまま以下のコマンドを試す。

$ catkin_init_workspace
$ catkin_make

以下のエラーが出てうまく行かない。

ImportError: "from catkin_pkg.package import parse_package" failed: No module named 'catkin_pkg'

このエラーについて調べると、anacondaが悪さをしているようだ。。。

Google グループ

Anacondaのアンインストールはあまりしたくないな。。。と思い、 そもそも環境を汚さない方法として、Dockerがあるじゃないか、と思い出す。

Dockerについては、名前以外はほとんど知らないので以下の記事を一通り読んだ。

www.atmarkit.co.jp

つづいて、以下の記事のとおりに作業を行うことで、とりあえず確認はできた

Docker + ROS(kinetic)でチュートリアル - Qiita

ただ、Dockerのイメージをベースに自分のコードを動かす方法がわかっていないので、それを学ぶ必要がある。

深層学習の超基礎知識を勉強した(学習に関するテクニック)

本当に久しぶりですが、ゼロから作るDeepLearningの6章、学習に関するテクニックを読んだときのメモを残します。 今年は継続的な勉強を頑張りたいです。継続は力なり。

  • SGDとは、確率的勾配降下法のこと
    • 勾配方向に向かう一番単純な方法
    • stochastic gradient descent
  • SGDは解く関数の形状が等方的でないと収束がうまくいかない
    • x方向の勾配は急だけど、y方向の勾配が非常に緩い場合など
    • このとき、勾配の方向が本来の最小値の方向を指しているとは限らない
      • この辺が、ガウス・ニュートンだと解決されているのか?
        • 自分の理解が正しければ、方向というよりは、収束点がわかっているイメージ
          • 勾配降下法は学習率のパラメータが必要だけど、いらないということ
  • Momentum
    • 収束に慣性を持たせる
  • AdaGrad
    • パラメータ毎に適応的に学習係数を調整する
    • 各パラメータの勾配の二乗和(スカラー)を逐次的に足し合わせてその分だけ学習係数を小さくする
    • 一回でも間違って大きく更新されてしまうとその後戻るステップが遅くなるみたいな性質を想像すると、結構イマイチな気がする
    • RMSPropという方法の方が良さそう
  • Adam
    • MomentumとAdaGradの融合
    • Qiitaなどをみていても、未だにAdamが鉄板だと思う。ライブラリでAdamを使えば良い
  • 初期値はとりあえずランダムで良い?←あとから、ダメという話がある
    • 何か学習済みのパラメータがあればそれを流用するのが良い
  • 勾配消失問題
    • 微分値が0になってしまうと、重みパラメータが更新できないという話
    • シグモイドならば0付近と1付近
  • 「表現力の制限」の問題は、逆にニューラルネットをコンパクトにしたい際に使用されている気がする
    • ニューロンが違う挙動しないと、ニューロンがたくさんある意味がないという話なので、逆に性能が出ているのに同一挙動のニューロンがあればそれは減らせる、みたいな
  • 初期値について
    • Xavierの初期値という考え方がある
      • できるだけ偏りなく勾配消失しない形でアクティベーションされることを目指したのかな
      • ところで、活性化関数に用いる関数は、原点対象であることが望ましい性質として知られているらしい
    • 活性化関数にReLUを使う場合は、「Heの初期値」を用いると良い
      • 考え方はほとんどXavierと変わらない
  • Batch Nomalization
    • 恥ずかしいことに、バッチノーマライゼーションとミニバッチ学習を混同していたが、全然違う
    • ミニバッチ学習
      • (ちょっとまだ自信がないが)ミニバッチ学習をせずに一つのデータだけで勾配を計算してしまうと、勾配方法が信用できなくなってしまうという話だと思う
      • 100個とか適当にサンプリングしたデータの塊を全データの近似とみなすということは、勾配方向がそこそこだ正しいとみなすことかな?
      • なので、ミニバッチ学習のサンプリング数は小さぎてはいけないと思う
    • Batch Normalizationは、ニューラルネットにBatch Nomaizationレイヤを挿入する
    • 角層でのアクティベーションの分布を適度な広がりになるように調整する専用の層を設計するということ
      • ミニバッチごとに正規化を行う
      • データの分布が平均が0で分散が1になるように正規化
      • 逆伝播の解説は省略されていたが、定性的な理解をしたうえで、基本的にライブラリを信じれば良いだろう
  • 過学習を抑制する手段として下の手法が有名
    • Weidht decay
      • 重みパラメータにペナルティをつける
      • 割と昔からある考え方
    • Dropout
      • 訓練時に、わざとランダムに使用しないニューロンを設定する
      • 擬似的に、アンサンブル学習を行っているという解釈になる
  • 最近はBatch Normalizationの方が有力ということなんだろうか
  • ハイパーパラメータの最適化
    • 今後重要な領域だろうが、今は興味外なので省略
    • ハイパーパラメータを遺伝的アルゴリズムで最適化とかあった気がする

すごい久々だけど大したことは書けない

すごいどうでも良い話だけど、久々に勉強しようとした際にメモをどこに残そう?と少し悩んだ。 要求仕様としては、

  • 基本的にはweb上に残したい
    • DesktopとノートPCの両方でアクセスしたいので
  • いざというときに、オフラインでローカルで編集したい

これだけ。そこで、以下の記事を見つけた。

d.hatena.ne.jp

要するに、全部GitHubで管理すれば良しちゃえということ。 これは凄く良いと思うので、早速レポジトリを作った。

とにかくここにメモをマークダウンで残してある程度まとまったら、記事にするとかありかもしれない。

深層学習の超基礎知識を勉強した(ニューラルネットワークの学習)

  • 「ゼロから作るDeep Learning」の4章「ニューラルネットワークの学習」を読んで勉強したときの自分用メモです
    • 実際にPythonを走らせて、手を動かす勉強はまだ
  • 認識の大雑把な変遷
    1. 昔は人が全て設計
    2. 一時期は、SIFT + SVMなどが流行った
    3. 全てニューラルネットで行うのが現在流行っている
      • 深層学習の真骨頂は、「end-to-end」な学習
      • 生データから目的の結果を得るということ
      • とはいえ、データの前処理の重要性はかなりのウェイトを占めている印象
  • 機械学習は、汎化能力が大事で、訓練データではないテストデータで、性能を評価する
  • 基本的には損失関数で学習を行う
    • 例えば、正解率が80%のような「認識精度」を直接上げるようにしない理由
      • 認識精度が改善されたとしても、(テストデータが整数なので)離散値になってしまう
        • 連続値でないと微分を使って学習を行う、機械学習の枠組みと相性が良くない
      • 私見だが、明らかに、一回一回のテストデータでフィードバックが入ったほうが、効率が良い
    • 個人的には、強化学習の枠組みでは、どちらかという「認識精度」を上げるように学習するイメージに近い
      • どのように性能を上げるかについては、今は不明なので将来的に勉強する
  • 損失関数は主に、2乗和誤差と交差エントロピー誤差がある

    • 多分、出力層がソフトマックスなため、総和が1.0に正規化されていることが重要?
    • 2乗和誤差  \displaystyle E = \frac{1}{2}\sum_{k}(y_k - t_k)^2
    • 交差エントロピー誤差  \displaystyle E = - \sum_{k}t_k log y_k
      • tが0 or 1で、0 <= y <= 1なので、-∞ < logy <= 0であることがポイント。正解ラベルに対する結果yが0に近いと、損失が非常に大きいという特徴がある
      • 正解ラベル以外は気にしなくて良いので、多分こっちの方が好まれているのではないか?と思う
  • ミニバッチ処理

    • ある程度まとめた訓練データ、例えば100個にまとめたデータを基に学習を行うという話
    • 詳しくは書かれていないが、多分 n^2とかそういう指数オーダーで、計算量が増えてしまうので、全ての訓練データをまとめて計算するのは現実的でないため
  • ただし、個人的な見解では、ミニバッチは小さすぎてはいけない
  • 以下、そう思う理由

    • 後述するが、結局微分をといて学習をといている、つまりある訓練データあったときに、(嘘を恐れずいえば)
      1. まず現在のパラメータ(重み)を使って損失計算をする
      2. 暫定的にあるパラメータに着目して、ちょっとだけ値を変える(+h)
      3. 損失計算を再計算
      4. 損失関数の変化からそのパラメータ(重み)を大きくしたほうが良いのか小さくした方が良いのか判断する
    • という流れになるが、ここで、(パラメータがかなり多く冗長であるので)あるデータ1に対しては大きくしたほうが良いが、他のデータ2〜10に対しては小さくした方が良いということが多発する。
    • ミニバッチをある程度大きさのデータとすることで、全体としてはパラメータを小さくしたほうが良いという見解が得られる
    • 機械学習の常識はわからないが、少なくともLM法などで数値的に非線形問題を解くときに、冗長性は敵である(解が見つからない!)
  • 勾配法で学習する話

    • 学習が深層学習のコアだが、多分、数学的には深層学習のことを知らない人が想像しているよりも遥かに簡単だと思う
    • 層の設計とかいろいろ難しいことはあるのだろうが、この初期導入および深層学習を始める際の最初の数学的敷居の低さは、今の深層学習ブームに一役買っていると思う
    • 特に、この「ゼロから作るDeep Learning」は本当に解りやすい!おすすめ!
      • 「やってみた」がしやすい←まさに数学が得意でないのに、できそうな気がしてほいほいやっています
    • 大まかにいうと、関数の各パラメータに対する微分偏微分)を計算して、損失関数が小さくなる方にパラメータを更新する。さらに、関数の正解は不明で、解析的な微分はできないので、数値的な微分値を使用する
    • 要するに局所的にf(x + h)を実際に計算しみて、各パラメータの変化にたいするf(損失関数)の変化からどのようにパラメータを変えたら良いか決定する
    • 勾配法なので、更新量を決定する学習率ηが存在する
      • 上の話は、一次近似なのでどこまで更新したらよいかわからないため
      • ガウス・ニュートン的な)2次近似して、学習率ηをなくすというな方法を聞いたことがないのが疑問だが、パラメータが多すぎて解けないため、という理解で良いのだろうか?
  • 理解が正しければ、収束計算なので、一通り訓練データを学習ステップにいれただけでは全然最適解にたどり着いていない

    • 1次近似なのでその効率も全く不明?
    • そこで、ミニバッチの組み合わせを変えながら何回も訓練データを学習の際に使用する
    • 一通りデータを使い終えた(とみなせる)時点で、1エポックという単位が使われる
    • 数エポックで、学習がうまく行っているかどうかちゃんとチェックするのが、実用上は大事
  • 誤差逆伝播

    • 今度またしっかり読むが、読み飛ばした感じでは、深層学習は理論的には勾配法(確率的勾配効果法、SGD)なのは変わらない
    • それを(ほとんど結果を変えずに)高速に算出するのが誤差伝播法

深層学習の超基礎知識を勉強した(パーセプトロンからニューラルネットによる推論まで)

  • ゼロから作るDeep Learningの2〜3章を読んだ
  • ここまでは簡単で、基本的にpythonで手を動かす練習をしているだけ
  • パーセプトロンで、OR, AND, NANDを作れる
    • それを二層にすることで、XOR(非線形)を作れる
  • 深層学習で、層を重ねて非線形の問題を解くためには、活性化関数を非線形にする必要がある
    • 言われてみると当たり前
    • シグモイド関数とかReLU関数とか
    • ReLUの方がよく使われているだろうか?
  • pythonでは、A * Bが行列の内積ではないことに注意。以下のように記述する必要がある。
    • np.dot(A, B)
  • ニューラルネットワークで、実際に推論してみる
    • お馴染みのMNISTデータ
    • 簡単にデータをロードできてよかった
      • 機械学習を使おうとすると、ほとんどこの辺のデータ準備の作業ばかりになりそうで怖い
  • 層の計算は、行ベクトルと行列の内積で算出できる
  • pickleは絶対便利
    • オブジェクトは'wb'で書き込んで、'rb'で読み込む
data = {}
data['name'] = "hoge"
...

with open(file_name, 'wb') as f:
  pickle.dump(data, f)

で保存して、

with open(file_name, 'rb') as f:
   data = pickle.load(f)

で読み込む。

  • 時間測定は、timeをimportすれば良い
start = time.time()
...
end = time.time()
print(str(end - start) + "[sec]"

時間は秒のようだ。

  • batch処理に関して
    • 要するに、1データが行ベクトルだったものを、複数データを行列とすることで、まとめて計算を行って高速化する
    • 簡単に10000テストデータで時間計測したところ、
      • バッチサイズを100とすることで、処理時間が10倍速くなったが、その後、バッチサイズを1000や10000にしてもほぼ同じだった
    • バッチサイズは大きければ大きいほどよいというものでもないようだ

ゼロから作るDeep Learningの一章を読んでみた

概略

  • ゼロから作るDeepLearningの一章を読んだので、そのログを残す
  • 一章は、pythonの話
    • pythonはあまり触ったことがなかったので、素直に手を動かした
    • pythonを使っている人からしてみたら、多分つまらない話

アナコンダのインストール

Anaconda を利用した Python のインストール (Ubuntu Linux) – Python でデータサイエンス

メモ

  • pythonには!がないので、notを使う
  • 配列の長さはa.lengthではなく、len(a)
  • コンストラクトが__init__
  • 階層が、:とインデントで、決まるのがなかなか慣れない気がする。
  • 「str1 + int + str2」みたいにして自動で文字列化するのはできない
    • str関数を使う
  • for文はCになれていると最初ちょっと困りそう
  • NumPyはMATLABみたいだ
    • braodcast計算が賢い
  • 配列は、ポインタ渡し?ではないみたいだ
    • 以下のように書いたときに
A = np.array([[1, 2], [3, 4]])
B = A
B = B.flatten()
print(A)
print(B)
  • 以下のような結果になる
[[1 2]
 [3 4]]
[1 2 3 4]

その他