皆さんはポテトチップスが好きでしょうか? ぼくは大好きです。今ドイツに住んでいますが、パプリカ味があったり、クリームオニオン味があったりしてたまりません。たまにプリングルスも手に取りますよ。
ある日、「ポテチってどうやって製造されてるんだろう?」と思ったので、ポテチとビールという最強のコンビを片手に、THE MAKING (55)ポテトチップができるまでを見ていました。ぼんやりポテチってこうやってできるんだ〜と見ていたのですが、ふと
これってTensorflowの考え方と同じじゃね??
と気づきました。
私自身Tensorflowに触れ始めたときは、「ネットワークやらを組んでからtf.Session()
でデータを流さないと計算できないよ〜」と教わったのですが、ネットワークという考え方自体慣れていなかったので、なかなか理解が難しかったんです。
そこで別のものに置き換えて理解しようとしていました。その例としてポテチの製造がいい理解の手助けになりました。
というわけで、以下の記事は上の動画を見てからポテチとビールを片手に読まれることをおすすめします。
コメント
- これはあくまでぼくがどういう風に理解したかをまとめたものなので、人によっては「ちゃんとニューラルネットワークから数学から理解すべきだ!」という方もいるかもしれませんが、はじめの直感的な理解の段階でこういう例もあるよ、と提供するものなので、ご了承ください。(あくまで自分用のメモだと言い訳しておきます(汗 )
- ネットワークとデータを別々に考えるのは、Tensorflowだけではなく、ディープラーニング全体の共通認識としてあると思いますが、とりあえずTensorflowを例として考えます。
ネットワークとデータは別々に考える
まずTensorflowの大きな特徴として、ネットワークを組むだけでは計算が実行されません。
import tensorflow as tf
### ネットワーク
a = tf.constant(1)
b = tf.constant(1)
add_op = tf.add(a, b) #加算
### 出力
print(add_op)
Tensor("Add:0", shape=(), dtype=int32)
さてこれをどう理解すればよいでしょうか? ある程度機械学習に慣れている方は「ネットワークとデータは別個のもので、ネットワークの組み方によって精度が変わるし、データ量(とか質)によっても精度が変わる」ことをご存知だと思います。
でも普通、計算するときはデータそのものに対する操作を考えますよね。たとえば1+1を計算するときは、1というデータと、1というデータを足す。それで2というデータが得られる。これが1+1=2です。でも機械学習やディープラーニングでは、●+△という演算を考えて、●や△にデータを入れて結果を得るという手順を踏むからですね。すなわち以下のように実装されるわけです:
import tensorflow as tf
### ネットワーク
a = tf.placeholder(tf.float32) # ●
b = tf.placeholder(tf.float32) # △
a_add_b = tf.add(a, b) # ● + △
with tf.Session() as sess:
a_, b_, a_add_b_ = sess.run([a, b, a_add_b], feed_dict={a: 1, b: 1})
### 出力
print("%i + %i = %i" % (a_, b_, a_add_b_))
1 + 1 = 2
ではポテチ製造の現場から、どのようにこれを理解すればいいか見てみましょう。
ポテトチップス工場
- じゃがいも入荷
- 皮むき
- 洗浄
- よりわけ
- つぶす
- スライス
- 揚げる
- (その他必要な工程)
- 袋に空気を入れてパック
- 安全検査等をして、段ボールにつめて出荷
=> これら一連の作業をするには、まずそれぞれの工程で必要な機械を揃える必要がある。 (皮むきする機械、よりわける人間、スライスする機械etc...) そのあとで、必要な順番に並べる。(ネットワークの構築)
もちろん、各工程ごとで必要となる機械は他の野菜にも使えるだろう。洗浄する工程は、野菜チップス全般にも使えるだろうし、つぶす作業ももっといろいろ使えるだろう(野菜ジュースを作る工程とか?)。だから一概にその工程の機械が、流される対象物(この場合はじゃがいも)と1対1に対応しているとも言えない。逆に言えば、他のモノを流すときもその機械が使える。(ネットワークのデータに対する非依存性)
Tensorflowも同じことをやっている。ただし、Tensorflowはそれぞれの工程で必要な機械は揃えてくれているので(API)、私達がどういうふうにそれらを組みあわせるか、なにを工程に流すか(じゃがいも?)を決めないといけない。そこで、Tensorflowでは、流される量をTensorと呼んでいる.その後で実際そのオブジェクトを流す必要がある。(そうじゃないとポテトチップスが食べられない(笑 ) 流すときは
tf.Session()
で電源を入れ、製造開始(笑
注意 ここでの「非依存性」とは、「ネットワークがデータに依存しないから、どんなデータでも最高の結果が得られるネットワークが存在する」ということではなくて、「データの内容(テキスト、画像 etc...)や入力・出力形状が一致すれば、同じネットワークを用いて計算を行うことができる」という可能性(Capability)を指しています。
このように考えれば、tf.placeholder
に入れるデータがだんだんじゃがいもに見えてきませんか? sess.run()
でポテチを食べたくなってきませんか?
・・・拙い例ですが、少しでも直感的な理解に役立つことがあれば大変光栄です。