PyCallでMatplotlibを使う

O'Reilly Japan - ゼロから作るDeep LearningのP.17ページにある単純なグラフ。

plot.rb

require 'bundler'
Bundler.require

require 'pycall/import'
include PyCall::Import
pyimport 'numpy', as: :np
pyimport 'matplotlib', as: :mp

pyimport 'matplotlib.pyplot', as: :plt

x = np.arange.(0, 6, 0.1)
y = np.sin.(x)

plt.plot.(x, y)
plt.show.()
$ bundle exec ruby plot.rb 

動いた!

参考

ソース

https://github.com/tnantoka/hello-pycall

PyCallでNumPyを使う

O'Reilly Japan - ゼロから作るDeep LearningのP.12辺りのサンプルが動くか試してみる。

PyCallのインストール

$ ruby -v
ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-darwin15]

$ bundle init

# Gemfile
gem 'pycall'

$ bundle

numpy.rb

require 'bundler'
Bundler.require

require 'pycall/import'
include PyCall::Import
pyimport 'numpy', as: :np

x = np.array.([1.0, 2.0, 3.0])
y = np.array.([2.0, 4.0, 6.0])
p x + y # array([ 3.,  6.,  9.])

A = np.array.([[1, 2], [3, 4]])
p A # array([[1, 2],
    #        [3, 4]])
p A.shape # (2, 2)
p A.dtype # dtype('int64')

B = np.array.([[3, 0], [0, 6]])
p A + B # array([[ 4,  2],
        #        j[ 3, 10]])
$ bundle exec ruby numpy.rb 

普通に動いた!

参考

ソース

https://github.com/tnantoka/hello-pycall

PyCallをDockerで

Rubyist Magazine - PyCall があれば Ruby で機械学習ができる を呼んでいたら、Jupyter Notebookが簡単に触れるDocker環境が用意されているとういうことだったので試してみました。

$ docker --version
Docker version 17.03.0-ce, build 60ccb22

$ docker run -p 8888:8888 -it --rm --name iruby -v ~:/notebooks/local rubydata/pycall

何事も無く動きました。

[読書メモ] ゼロから作るDeep Learning: 第4章

O'Reilly Japan - ゼロから作るDeep Learning

学習

  • パラメータを自動で
    • 膨大な数な数。手作業でやるのは無理
  • 損失関数
    • 学習の指標
    • これが一番強い小さくなるパラメータを探す
  • パーセプトロン
    • 線形分離可能な問題は自動で学習可。収束定理。
    • 非線形分離問題は自動学習不可
  • データ駆動
    • 人の介入を避ける
    • ディープラーニングはそれがやりやすい手法
  • 5を識別する
    • 特徴量+機械学習のアプローチでは、特徴量を人が設計する
    • ディープラーニング(ニューラルネットワーク)ではそこも自動で
    • end to end machine learning
  • 過学習
    • 特定のデータセットにしか対応できない
    • 汎化能力がない
    • 訓練(教師)データとテストデータを分ける

損失関数

  • 任意の関数使える
    • 二乗和誤差や交差エントロピー誤差がよく使われる
  • 2乗和誤差
    • 出力と教師データの各要素の差を二乗してその総和を求める
  • 交差エントロピー誤差
    • 教師データを01のone hot表現にすれば出力結果のlog、自然対数を求めるだけになる
    • log(0)にならないように極小の値deltaを足す
  • ミニバッチ学習
    • 全訓練データを対象に損失関数を求めたい
    • 数が多いと無理
    • 無作為に一部を抽出してそれを対象に学習
    • 正確ではないが、全体の近似として扱う
  • バッチ版交差エントロピー
    • tが0のものは0になるので無視できる
    • 正確に対する出力だけ取ってくればよい
    • あとはそれを平均するだけ
  • なぜ損失関数が必要か
    • 認識精度を指標にすればいいのでは
    • 微分(勾配)を参考にパラメータを調整していく
    • 認識精度の微分は0になるので使えない
    • 認識精度はパラメータの微小な変化では変わらないステップ関数と同じ。
    • 損失関数ならパラメータを変えると連続的に変化するので、それを元にパラメータ調整できる

数値微分

  • ある瞬間の変化
  • 10分間に2km、1分間に0.2km…時間hを0に近づける
  • 小さすぎる値を使うを丸め誤差がおこる
  • 中心差分
    • f(x + h) - f(x)は前方差分。誤差が大きい
    • x(f+h) - x(f-h)を使う
  • 数式で解析的に解いた真の微分とは誤差があるがほとんど同じ値が得られる
  • 偏微分
    • 複数の変数からなる関数の微分
    • 片方の変数を固定してもう片方の変数を微分する
  • 勾配(gradient)
    • 全ての変数の偏微分をベクトルにまとめる
    • 各地点において関数の値を最も減らす方向を向いたベクトルになる(関数の最小値とは限らない)
  • 勾配法
    • 勾配を使って損失関数が小さくなるパラメータを探す
    • 勾配は最小値以外でも0になる。極小値や鞍点、プラトー。
    • 勾配方向への移動を繰り返して関数の値を減らしていく。勾配降下法。
    • 学習率。1回の移動量。正しく学習でいる値になっているか確認する必要がある。
    • ハイパーパラメータ。重みやバイアスのように自動で獲得されず、学習率のように人の手で設定するもの。

学習アルゴリズムの実装

  • SGD
    • 確率的勾配降下法
    • ミニバッチ × 勾配法
  • 前章のフォワード(推論)処理の実装と共通部分が多い
  • 1エポックごとにテストデータで評価
    • 10000個のデータを100個のミニバッチで学習するなら勾配法100回で全部見たことになるので100回がエポック

[読書メモ] ゼロから作るDeep Learning: 第3章

O'Reilly Japan - ゼロから作るDeep Learning

ニューラルネットワーク

  • パーセプトロンの章ではパラメータを手動で設定していた
  • ニューラルネットワークはデータから自動で適切なパラメータを学習できる
  • 入力層・中間(隠れ)層・出力層に分かれる。
  • 2層では第0層が入力、第1層が中間、第2層が出力。
  • パーセプトロンのバイアスを図示する
    • 重みがbで入力が常に1の信号
  • パーセプトロンの式を変換
    • h(x)は入力が0を超えたら1を返す関数。
    • y = h(b + w1x1 + w2x2)に変換
    • h(x)は活性化関数と呼ばれる。(入力の総和を出力に変換)
  • さらに変換
    • a = b + w1x1 + w2x2
    • y = h(a)
    • 重み付き信号の和がaとなり、活性化関数h()によってyに変換される
  • ステップ(階段)関数
    • 閾値を境に出力が変わる
    • パーセプトロンは、活性化関数にステップ関数を用いている、と言える
    • NumPyの配列に不等号を演算を行うとboolが返ってくる。それをintにすればステップ関数になる。
  • シグモイド関数
    • ステップ関数のように0か1ではなく連続的な実数を返す
    • 入力が小さい時は0に近く、大きい時は1に近づくのはステップと同じ
    • 出力が0から1の間におさまるのも同じ
  • 非線形関数
    • 関数とは変換器。出力が入力の定数倍になるものは線形関数
    • ステップもシグモイドも非線形。直線ではない。
    • ニューラルネットワークでは非線形を活性化関数として使う必要がある。層を重ねる恩恵を受けるため。
  • ReLU関数
    • 0以下なら0を返し、0より大きければ入力をそのまま返す。

多次元配列

  • np.dotで内積を計算できる
    • 次元数は合わせる必要がある
  • x1, x2からy1, y2, y3を求めるような計算が1度にできる
    • X = np.array([1, 2])
    • W = np.array([1, 3, 5], [2, 4, 6])
    • Y = np.dot(X, W)
    • print(Y) # [5, 11, 17]

3層ニューラルネットワーク

  • np.arrayを使うと簡単に実装できる
  • 恒等関数
    • 入力をそのまま出力する
    • 回帰問題では出力層の活性化関数にこれを使う
    • 2クラス分類ではシグモイド、多クラス分類ではソフトマックス
  • 分類問題
    • データがどのクラスに属するか
  • 回帰問題
    • データから予測を行う(写真から体重を当てるなど)
  • ソフトマックス
    • 全ての入力から影響を受ける
    • すぐオーバーフローするので実装する際は、入力の最大値を引くなどの対策をする
    • 出力の総和が1になる
    • 確率として扱える
    • 各出力間の大小関係は変わらない。無駄な計算資源使わないために推論時は省略する。学習時には使う。

手書き数字認識

  • MNISTのデータを使う
    • 28 x 28の画像
    • 訓練画像60000、テスト画像10000
  • 入力は784(28x28)
  • 出力は10(0〜9の10クラス分類)
  • 隠れ層は50と100(この数は任意)
  • 前処理
    • 入力データに対する変換
    • 正規化(データを決まった範囲に収める、今回は255段階のピクセルデータを0.0〜1.0にした)など
  • 学習済みの重みを使う
  • バッチ処理
    • 演算ライブラリは大きな配列を高速に処理できるように最適化されている
    • まとめて処理させることで高速化できる