のんびりしているエンジニアの日記

ソフトウェアなどのエンジニア的な何かを書きます。

Autogradで微分して、モデルを構築するとこまでの解説

Sponsored Links

皆さんこんにちは
お元気ですか。

Twitter上で突然賑わった、Autogradについて
書いてみることにします。

Autogradとは

Autogradについての説明

github.com
Autogradはnumpyらしく書くことができ、その記載した式を微分してくれるライブラリです。(in Python)
現状、Pythonとtorch(lua)にて実装があるようです。

Theanoとの違いはシンボルを定義せず、数値計算した内容を直接渡すことができます。といったところでしょうか。正直自動微分は新しくないものです。(Theanoがありますので)

悲しいことにPythonのAutogradは現状、GPU演算を行うことができません。
testの中にGPU関係の内容はあるようですが、
一応featureにGPU operationsのサポートとして掲載されていますね。

Install

sudo pip install autograd

How to use

次はこの便利ツールの使い方を見てみます。
Tutrialを参考に、autogradを使ってみましょう。

基本的な文法はnumpyと同じです。(一部使えない文法はあります。)
numpyでは import numpy as npとかでimportしますが、
autogradでは少々異なります。簡単な内容について試してみます。
今回はx ** 2を微分してみます。

Easy Example

Source Code
import autograd.numpy as np
from autograd import grad

def x_pow(x):
        return np.power(x,2)

grad_pow = grad(x_pow)
print grad_pow(2)
print (np.power(2.0001,2) - np.power(1.9999,2)) / 0.0002
標準出力
4.0
4.0

まず、インポートするのは以下が必要になります。
numpy を wrappingした内容、もうひとつは微分用のメソッドです。

import autograd.numpy as np
from autograd import grad

次に必要なのは、微分する関数です。gradの引数には関数を与えるので以下の通りに実装すれば問題ありません。
因みにもう一度、gradをすると、2次微分を実行することができます。

grad(x_pow)

Neural Network Example

こちらは実例を見てみましょう。ソースコード全体は以下を見ていただくとして
注目するべきコードを抽出します。

autograd/neural_net.py at master · HIPS/autograd · GitHub

モデルコード

def make_nn_funs(layer_sizes, L2_reg):
    shapes = zip(layer_sizes[:-1], layer_sizes[1:])
    N = sum((m+1)*n for m, n in shapes)

    def unpack_layers(W_vect):
        for m, n in shapes:
            yield W_vect[:m*n].reshape((m,n)), W_vect[m*n:m*n+n]
            W_vect = W_vect[(m+1)*n:]

    def predictions(W_vect, inputs):
        for W, b in unpack_layers(W_vect):
            outputs = np.dot(inputs, W) + b
            inputs = np.tanh(outputs)
        return outputs - logsumexp(outputs, axis=1, keepdims=True)

    def loss(W_vect, X, T):
        log_prior = -L2_reg * np.dot(W_vect, W_vect)
        log_lik = np.sum(predictions(W_vect, X) * T)
        return - log_prior - log_lik

    def frac_err(W_vect, X, T):
        return np.mean(np.argmax(T, axis=1) != np.argmax(predictions(W_vect, X), axis=1))

    return N, predictions, loss, frac_err

学習部の抽出

loss_grad = grad(loss_fun)
 for epoch in range(num_epochs):
        print_perf(epoch, W)
        for idxs in batch_idxs:
            grad_W = loss_grad(W, train_images[idxs], train_labels[idxs])
            cur_dir = momentum * cur_dir + (1.0 - momentum) * grad_W
            W -= learning_rate * cur_dir

モデル部分の関数(make_nn_funs)の部分で重要なのは、loss変数です。
このloss変数を定義し、微分するとWを更新する値を決定することができます。

つまり、Autogradはloss定義して微分して更新方法を決定することで、
あらゆるモデルを構築することができるライブラリです。科学技術演算のままできるのが良い。

感想

  1. 現状、GPUが使えないので、簡単な計算テストには向いているでしょう。
  2. 簡単にインストール、構築ができるので実験向き?
  3. 自動微分が新しいわけでは多分ない。
  4. Tutrialを読む限りnumpyの全てをサポートしているわけではないので、書き方に注意しましょう。