はじめに
Common Lispで深層学習コンパイラを作っている人に感銘を受けたので、プログラミングの練習のためにと自分もCommon Lispで似たものを書いてみようと思い、この本を買った。
本のソースコードはここで公開されている。 github.com
先駆者の方々も何人かおられるようなので、参考にする。 msyksphinz.hatenablog.com github.com
実装の方針
行列を表現するなら、PythonであればNumPy一択だが、Common Lispでは少し考える必要がある。 最初の数ステップを書き直しながら、次のライブラリを試した。
-
- BLASやCUDAを使って高速な計算ができるというライブラリ。足し算や掛け算をするために
axpy!
やgemm!
を使ってみたものの、計算したい行列のほかに計算結果を格納するための行列を用意する必要があり、計算式を書くのも少し難しかったので、途中でやめてしまった。
- BLASやCUDAを使って高速な計算ができるというライブラリ。足し算や掛け算をするために
- Common Lisp標準の多次元配列
- msyksphinzさんの記事ではRubyの
Array
をそのまま使っていたので、Common Lispでも同じように自分で書いてみようとした。多次元配列の生成や計算の書き方で自分が詰まってしまうことがあった。
- msyksphinzさんの記事ではRubyの
- array-operations
- Common Lisp標準の多次元配列を生かし、機能を拡張する関数やマクロを提供するライブラリ。直感的に使える関数やマクロが多く、特に
vectorize
マクロが便利で扱いやすかった。
- Common Lisp標準の多次元配列を生かし、機能を拡張する関数やマクロを提供するライブラリ。直感的に使える関数やマクロが多く、特に
array-operations
が自分に合っていると感じ、自作のルーチンも使いながらプログラムを書くことに決めた。
テストフレームワークはFiveAMとroveで迷ったが、とりあえずrove
を使用することにした。
ソースコード
ステップ1
オリジナルの書き方に似せるため、規約を設けることにした。
- クラス名は
<>
で囲う。- 今後出てくるクラスとして
exp
やfunction
という名前があるが、これはcl:exp
やcl:function
と衝突するため。
- 今後出てくるクラスとして
- インスタンスを作るラッパー関数を用意し、クラス名と同じ名前を付ける。
- アクセサは
@
で始まる名前を付ける。 - クラスはファイルの先頭寄りにまとめて記述する。
- アクセサを使う場所より後にアクセサを含むクラスを定義すると、そのような関数は定義されていないという警告が出るため。
ステップ2
function
という名前はcl:function
と衝突する。defpackage
の:shadow
を使ってもよかったかもしれない。
ステップ3
行列の計算のためにarray-operations
を導入するが、このぐらいは自分で書いてもよかったかもしれない。