Q1
1ネットでいろいろ『Computational Graphs』に関する説明例を調べたら、どうも『Computational Graphs』そのものは四則計算が発明された時点に存在したはずだと感じました。【そうでしょ?】
計算グラフは理論というより、プログラミングで出てくるスタックやリストなどと同様、データ構造 にあたります。
Wikipedia
1データ構造(データこうぞう、英: data structure)は、計算機科学において、
2データの集まりをコンピュータの中で効果的に扱うため、
3一定の形式に系統立てて格納するときの形式のことである。
計算グラフは演算や値をノード、データの流れをエッジで表したというだけの話です。そのようなデータ構造にすると、順伝搬、逆伝搬を行う計算ライブラリの設計がしやすいのです。
Q2
1単に、Neural network分野では四則計算の連続を『Computational Graphs』と名付けて、そのシーケンスの構造を解析し、Neural networkに対応するLibrary/Frameworkによって自動微分を実現してくれるということですね。
2当然、同じ『Computational Graphs』構造を持っても、解析せず、自動微分を実現してくれない Neural network Library/Framework も存在するはず。
微分の計算ができなければ、バックプロパゲーションができないので、ニューラルネットワークのライブラリに限れば、すべて自動微分できると思います。
Q3
1要は『Computational Graphs』という言葉が新しいものの、
2その自体は新しい技術や概念ではないのです。
Google トレンドを見ると、以前から言葉としてはあったように思いますが、TensorFlow が世に出てから目にするようになったと思います。
質問に対する追記1
TensorFlowの場合、四則計算の構成を『データ構造』に表現しておくというのは、四則計算を単に数値計算するのみならず、将来微分計算するために数式構造を保存してsymbolic数式的に解析しようとするのでしょうね?
バックプロパゲーションを行うのに、順伝搬時に計算した値が必要なので、保存しておく必要があります。
演算をノードで表現して、計算した値を保持しておく設計にしておくのは理にかなっていると思います。
つまり、数値微分ではなく、Neural network のLIBはsymbolic数式で偏微分を求めていくと考えて大丈夫でしょうか。
バックプロパゲーションで計算される値は数値解ではなく、解析解であるのは確かです。
しかし、微分を mathmatica や sympy でできるようなシンボル操作で行い、解析解を求めているわけではないです。予め、微分の解析解を計算する関数を用意しています。
例えば、シグモイド関数を例に考えると、f(x) = 1/(1+exp(-x)) なので、微分すると、d/dx f(x) = f(x)*(1-f(x)) になりますよね。
なので、シグモイドを計算する「ノード」では、f(x) と f'(x) を計算する処理を両方定義してあります。
python
1class Sigmoid:
2 def __init__(self):
3 self.out = None # 逆伝搬用に出力を保持しておく
4
5 def forward(self, x):
6 out = 1 / (1 + np.exp(-x))
7 self.out = out
8
9 return out
10
11 def backward(self, dout):
12 dx = dout * (1.0 - self.out) * self.out
13
14 return dx
DNNライブラリがどうなってるのか興味がお有りなら、他の回答者さんも進めていますが「ゼロから作る Deep Learning」という本を見てみるとよいですよ。
質問に対する追記2
ユーザ定義の数式にはやはり構造を解析して初めて解析形式の微分結果を得るでしょう。例えば、 y = x*x + z*x*exp(z) + z*sin(x)
exe(z) と sin(x) に関する導関数を予め用意できても、関数yの導関数が予め用意できないですから、、、?
symbolic 操作を行う必要はありません。
上記の例の場合、構成要素である「multiply(x, y)」「add(x, y)」「exp(x)」「sin(x)」の4つの演算について、微分の計算が定義されていれば、「連鎖律」を用いて、「合成関数 y」の微分の計算値を得ることができます。
納得できないようであれば、次の手順で勉強してみてください。
- (多変数関数の)連鎖律について理解する。
- 連鎖律を用いた逆伝播法 (バックプロパゲーション) について理解する。
バックプロパゲーションと計算グラフの関係は次の参考リンクを貼っておきます。
質問に対する追記3
Python では、C++ の演算子オーバーロードと同様のことができます。
公式リファレンス を見てください。
もし演算子オーバーロードができないと numpy 配列で普通にやっている演算とかもわざわざ np.add(array1 + array2) などとしなくてはいけなくなりますよね。
python
1class Point:
2 def __init__(self, x, y):
3 self.x = x
4 self.y = y
5
6 def __add__(self, other):
7 return Point(self.x + other.x,
8 self.y + other.y)
9
10 def __repr__(self):
11 return "({}, {})".format(self.x, self.y)
12
13a = Point(1, 2)
14b = Point(2, 3)
15print(a + b) # (3, 5)