質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
深層学習

深層学習は、多数のレイヤのニューラルネットワークによる機械学習手法。人工知能研究の一つでディープラーニングとも呼ばれています。コンピューター自体がデータの潜在的な特徴を汲み取り、効率的で的確な判断を実現することができます。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

3383閲覧

『自動微分』に関する実装原理

leilei

総合スコア39

深層学習

深層学習は、多数のレイヤのニューラルネットワークによる機械学習手法。人工知能研究の一つでディープラーニングとも呼ばれています。コンピューター自体がデータの潜在的な特徴を汲み取り、効率的で的確な判断を実現することができます。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2018/08/17 06:14

編集2018/08/18 23:01

NNの神髄は目標関数を微分で極値に到達させる(これでback propagationの形でweightの最適化を行う)ことだと思います。
その微分の実現法として『自動微分』法が良く紹介されています。
しかし、『自動微分』の方法を調べても[例えば↓]、関数が数式(解析式,symbolic format)である例を説明されたばかりですが(これで"forward and reverse accumulation"を論ずる)、現実の関数は皆programming言語で定義されるわけですから、内容や形式が様々で、if文やloop文さえ入れている事もあり、解析的な数式表現とは全然異なりますね!

結局、**どうやって、『自動微分』が実装されたの?**という質問がずーと分かっていません。

この辺明るい方是非ご教授お願い申し上げます。

[例えば↑] <<Automatic differentiation>>

===================
【面白いidea 1】
What is Automatic Differentiation?

Automatic differentiation is really just a jumped-up chain rule.
When you implement a function on a computer, you only have a small number of primitive operations available (e.g. addition, multiplication, logarithm). Any complicated function, like log(x^2)/x.
is just a combination of these simple functions.

In other words, any complicated function f can be rewritten as the composition of a sequence of primitive functions fk:

f = f0∘f1∘f2∘…∘fn

Because each primitive function fk
has a simple derivative, we can use the chain rule to find df/dx pretty easily.

Although I've used a single-variable function f:R→R
as my example here, it's straightforward to extend this idea to multivariate functions f:Rn→Rm.

【面白いidea 2】
Automatic differentiation computes derivatives based on computational functions (which in turn are broken down into basic operations such as addition/subtraction and multipliation/division).

Since TensorFlow does differentiation based on a computation graph of operations, I'd intuitively say that it's automatic differentiation (I don't know of any other technique that would be appropriate here; I think the possibility that TensorFlow is converting the computation graph into a mathematical equation that is then parsed to compute the derivative of that equation is prob. out of question). The authors say "symbolic differentiation" in the TensorFlow whitepaper though -- however, I think this may be a misnomer similar to "Tensor" instead of "(multi-dimensional) data array" if you'd ask a mathematician.

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

人がキーボード叩いて実装されてはいると思います。

結局微分は一般的な形式が存在するので難しくはなさそうですが。

自動微分が普通では書けないと思う理由はなんですか?

http://ailaby.com/chainer_foward_backward/

https://github.com/tensorflow/tensorflow/blob/master/tensorflow/cc/gradients/math_grad.cc


ちなみに微分できないと自動微分できません。


define-and-runだとif文を挟んだ際にif文の分岐分だけグラフのパターンが分かれてしまうため、一般に論理構造を含む実装は困難です。
TensorflowのEagerモードなど、define-by-runで動的にグラフを形成する場合は実装が少々簡単になります。
グラフを計算するときは具体的に入力値が定まっているときなので常にグラフは分岐しない一本道になります。

以下コメント欄を転記。

http://tensorflow.classcat.com/2018/07/17/tensorflow-tutorials-automatic-differentiation/
https://www.tensorflow.org/guide/eager#computing_gradients

上の2つのリンクをたどってみてください。

Eagerの場合逐次実行できるのでGradientTapeというもので計算のフローをたどることができます。
遅延評価されるので、入力を実際に与えたときに初めてフローが形成されます。
なので、実は途中でif文を大量に挟んでも問題ありません。
if文があっても、特別な入力に対しては一つのフローにならなければならないからです。
これは動的にグラフ形成を許すEagerモードならではの実装だと思われます。

結論としては、
①シンボリックには計算していません
②特定の値に対して計算フローを形成するので、必ず一本道になり、単純な自動微分に帰結します

投稿2018/08/17 09:26

編集2018/08/19 04:03
mkgrei

総合スコア8560

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

leilei

2018/08/18 05:12 編集

mkgreiさん 有難うございます。 >自動微分が普通では書けないと思う理由はなんですか? 純粋に数式の形で表現されている関数(数学意味上の関数)なら、勿論その導関数が簡単に利用できると思いますが、 ところが、予め予約していないユーザ定義の任意数学関数を計算機言語で表現しようとすると、特定の計算機言語においての『関数』になり、即ちコードになりますね。その中にsin,cos expが含まれても、分岐文やループ文によって相当複雑の『数式・関数式』になるわけですから、そのようなコードで表現している数学関数の導関数をLIBはどうやって自動的に導出してくれるの? という質問です。 (『自動微分』は数値微分ではないことにご注意いただきたいのです。)
oookabe

2018/08/18 09:54 編集

leileiさんがおっしゃっているのは、恐らくTensorFlow流の導関数の求め方ですね。 要はユーザがコードで計算機言語の『関数』の形で任意の"数学関数"を定義し、そしてユーザ定義の計算機言語の『関数』の名前をTensorFlowの導関数を求める関数に渡せば、(自動微分で)ユーザ定義関数の導関数を返してくれます。確かに、TensorFlowの導関数を求める関数はどうやってユーザ定義の関数の微分を計算するのはなぞですね。{この場合、解析式(symbol)の形での微分ではない同時に「数値微分」でもないですから}
mkgrei

2018/08/18 13:53

自動微分は任意の関数を微分するものではありません。 多層ニューラルネットワークにおいて、各層において逐次微分されることを考えると、チェーンルールが適応できることをたいそれた言葉で表現しているだけです。 「それぞれの基本的な関数に対する導関数を予め用意」しておけば、「基本的な関数によって構成された複雑なネットワークの微分を自動的にできる」、ということになります。 tensorflowのリンクのコードを読めばわかりますが、単純関数の導関数は人の手で定義されます。 独自の関数を使いたいのであれば、導関数を自分で書く必要があります。 wikipediaを引用すると > 自動微分は複雑なプログラムであっても加減乗除などの基本的な算術演算や基本的な関数(指数関数・対数関数・三角関数など)のような基本的な演算の組み合わせで構成されていることを利用し、これらの演算に対して連鎖律を繰り返し適用することによって実現される。自動微分を用いることで偏導関数値を少ない計算量で自動的に求めることができる。 --- 複雑ものの場合、ものによっては微分が定義されていません。 そのような関数を使うと、損失関数を処理できず、エラーを吐きます。 top-kを独自実装しようとすると過去にそのようになっていましたが、今はもしかしたら実装されてできるようになっているかもしれません。 難しい関数、特に論理構造があると微分をうまく定義できないことは珍しくありません。 そのような場合には、スコアは難しい関数で順方向だけ計算して、誤差伝搬するときに解析的となる近似表現を用いてネットワークを最適化します。
leilei

2018/08/19 01:39 編集

mkgreiさん 本当にお世話になっております。 仰った事良く理解できます。 ただ、現にユーザ自作の関数(プログラミング言語のコードで表現されているやつ)も簡単に導関数を得られるらしいですね。これこそ理解に困ります。 実例:<<https://github.com/tensorflow/tensorflow/issues/15418>> import tensorflow as tf import tensorflow.contrib.eager as tfe tfe.enable_eager_execution() #↓自作関数で、人間なら、symbolic数式に変換できるが、マシンにとって相当難しいはず。("・・"は space) def loss(w): ・・ prediction = 2 * w + 1 ・・ true_value = 11 ・・ return tf.cast((true_value - prediction)**2, tf.float32) tfe.gradients_function(loss)(0.1) # ← loss関数の導関数を得る! ↑lossはユーザ定義の関数で(内容的に限定されてないようです)、それにlossの導関数をユーザが定義していません。  このgradients_functionはどうやってlossの導関数を算出可能になっているでしょうか。
mkgrei

2018/08/19 03:58

Eagerでの計算方法について詳しく知りませんでした。 ので、調べてみました。 なかなかにおもしろい話でした。ありがとうございます。 --- http://tensorflow.classcat.com/2018/07/17/tensorflow-tutorials-automatic-differentiation/ https://www.tensorflow.org/guide/eager#computing_gradients 上の2つのリンクをたどってみてください。 Eagerの場合逐次実行できるのでGradientTapeというもので計算のフローをたどることができます。 遅延評価されるので、入力を実際に与えたときに初めてフローが形成されます。 なので、実は途中でif文を大量に挟んでも問題ありません。 if文があっても、特別な入力に対しては一つのフローにならなければならないからです。 これは動的にグラフ形成を許すEagerモードならではの実装だと思われます。 結論としては、 ①シンボリックには計算していません ②特定の値に対して計算フローを形成するので、必ず一本道になり、単純な自動微分に帰結します 実装については下の2つです。 https://www.tensorflow.org/api_docs/python/tf/contrib/eager/gradients_function https://github.com/tensorflow/tensorflow/blob/r1.9/tensorflow/python/eager/backprop.py
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問