はじめに
ゼロから作るDeep Learningを購入していたのですが、よい本だなーと思いつつも放置していました。
ところで最近、Luaを使う機会があったのですが、Luaでも深層学習のライブラリとしてTorchというものがあり、なおかつ行列計算にも幅広く対応しているということでした。
なので自分の勉強も兼ねて「ゼロから作るDeep Learning」で紹介されている手法をLuaバージョンで書いていこうと思います。
本記事はどちらかというと自分用のメモ書きに近く、なおかつ私はディープラーニングの専門家でもなければ情報科学系出身でさえないアマチュアなので、至らない部分が多いかもしれませんがご了承いただけると助かります。気になる点がありましたらぜひご意見をいただきたいと思っております。
今回はTorchをすでにインストールした前提で話を進めます。
Torchのインストールに関しては以下の記事をご参照ください。
インストール後パスを再度読み込むのを忘れないようにしましょう。マックならば
source ~/.profile
もしくは、bashの再起動が必要です。
パスを読み込んだら以下のコマンドを入力し、
th
以下の表示がだせたら大丈夫です。(終了はexit
)
______ __ | Torch7
/_ __/__ ________/ / | Scientific computing for Lua.
/ / / _ \/ __/ __/ _ \ | Type ? for help
/_/ \___/_/ \__/_//_/ | https://github.com/torch
| http://torch.ch
論理ゲートの実装
まず基礎事項の説明の1章は飛ばして2章から入ります。
論理ゲートを実装しましょう。
---ANDゲート関数.
-- 入力1、2の両方が入力されたときに1を返す
-- @param x1 入力1
-- @param x2 入力2
-- @return 1 or 0
function AND(x1, x2)
local x = torch.Tensor({x1, x2})
local w = torch.Tensor({0.5,0.5}) --重み
local b = -0.7 --バイアス
local temp = w:dot(x)+b -- torch.sum(w:cmul(x))+b とも書ける
if temp <= 0 then
return 0
else
return 1
end
end
---NANDゲート関数.
-- 入力1、2の両方が入力されたときに0を返す
-- @param x1 入力1
-- @param x2 入力2
-- @return 1 or 0
function NAND(x1, x2)
local x = torch.Tensor({x1, x2})
local w = torch.Tensor({-0.5,-0.5}) --重み
local b = 0.7 --閾値
local temp = w:dot(x)+b
if temp <= 0 then
return 0
else
return 1
end
end
---ORゲート関数.
-- 入力1、2のいずれかが入力されたときに1を返す
-- @param x1 入力1
-- @param x2 入力2
-- @return 1 or 0
function OR(x1, x2)
local x = torch.Tensor({x1, x2})
local w = torch.Tensor({0.5,0.5}) --重み
local b = -0.2 --閾値
local temp = w:dot(x)+b
if temp <= 0 then
return 0
else
return 1
end
end
---XORゲート関数.
-- 入力1、2のいずれかが入力されたときのみ1を返す
-- @param x1 入力1
-- @param x2 入力2
-- @return 1 or 0
function XOR(x1, x2)
local s1 = NAND(x1, x2)
local s2 = OR(x1, x2)
local y = AND(s1, s2)
return y
end
--確認
print("ANDゲート")
print("AND(0, 0):"..AND(0, 0))
print("AND(1, 0):"..AND(1, 0))
print("AND(0, 1):"..AND(0, 1))
print("AND(1, 1):"..AND(1, 1))
print("NANDゲート")
print("NAND(0, 0):"..NAND(0, 0))
print("NAND(1, 0):"..NAND(1, 0))
print("NAND(0, 1):"..NAND(0, 1))
print("NAND(1, 1):"..NAND(1, 1))
print("ORゲート")
print("OR(0, 0):"..OR(0, 0))
print("OR(1, 0):"..OR(1, 0))
print("OR(0, 1):"..OR(0, 1))
print("OR(1, 1):"..OR(1, 1))
print("XORゲート")
print("XOR(0, 0):"..XOR(0, 0))
print("XOR(1, 0):"..XOR(1, 0))
print("XOR(0, 1):"..XOR(0, 1))
print("XOR(1, 1):"..XOR(1, 1))
Torchがnumpyと違う点についていくつか列挙していきます。
内積<A,B>は、numpyではnumpy.sum(A*B)
ですがTorchでは
A:dot(B)
一次元ベクトルの積ABは、numpyではA*B
ですがTorchでは
A:cmul(B)
一次元ベクトルの定義はテーブル型{}
を用いて
torch.Tensor({a11, a12, ..., a1n})
また、行列の定義だと{}が増えて
torch.Tensor({{a11, a12, ..., a1n},{a21, a22, ..., a2n}})
で2×n行列となります。
この辺りは以下のマニュアルに詳しい記載があります。
それでは実行してみましょう。
th logic_gate.lua
ANDゲート
AND(0, 0):0
AND(1, 0):0
AND(0, 1):0
AND(1, 1):1
NANDゲート
NAND(0, 0):1
NAND(1, 0):1
NAND(0, 1):1
NAND(1, 1):0
ORゲート
OR(0, 0):0
OR(1, 0):1
OR(0, 1):1
OR(1, 1):1
XORゲート
XOR(0, 0):0
XOR(1, 0):1
XOR(0, 1):1
XOR(1, 1):0
大丈夫ですね。
今回は以上です。引き続き記事を書いていくので宜しくお願い致します。
ありがとうございました。