2021年6月21日月曜日

Tensorflow2(2)微分計算で立ち止まるわたくし

Tensor計算してますか? 添え字が多いのでわたしには出来ません.

いつものように入門書「TensorFlow2プログラミング実装ハンドブック」の通りに動かしています.PythonとJupyter NBの使い方をあまり判っていません.

まだ3章「勾配降下法」のところです.TensorFlowオブジェクトが判らんちんです.

勾配降下法について少し説明します.
excelグラフの「XY散布図」に近似関数を表示させる機能があるでしょう.あれをやる計算方法の一つが勾配降下法です.(他のやり方もあるのでexcelが勾配降下法を活用しているとは思ってません)

「近似関数を作る」とは「近似関数の誤差を小さくする」事で達成されます.
それには誤差を計算せないけません.誤差は2乗誤差を採用します.他の誤差を使っても勾配降下法は動くでしょうけど、2乗誤差は分散や標準偏差に則った数式になるのと、2乗を微分するのはさほど苦労しないからだろうねぇ.

2乗誤差とはこういう物です.
散布図のXYペアはたくさんあります.それらを(Xi,Yi)とします.
ここでは近似関数を最も簡単な Y = a X + b  とします.直線近似ですね.
aとbを最適化するのが勾配降下法の仕事です.
すると誤差は、ei = Yi - ( a Xi + b) と定義されます.近似バッチリならei=0になる.
2乗誤差は ei を2乗したものです.
ただし、XYペアはたくさんあるので個々の2乗誤差eiを全て足したものを「2乗誤差」として採用します.
(式1)

次に「aを最適化する」とは「2乗誤差が小さくなるようにaを修正する事」ですから、
  (式2a)
このようにaを修正すればOKです.0.01は少しづつ修正する意味があり、このa修正式を100回ぐらい繰り返せば最適なaになるだろうとの目論見です.
bの修正式も同様です.
  (式2b)
修正後のaとbを使って求め直したEは次第にゼロに近づいてゆくはずです.実際にはE=0にはならなくて、減少ペースがサチったところで計算を打ち切ります.

a修正式とb修正式に登場する偏微分はやってみれば案外簡単に(高校数学で)解けます.具体的な修正式はこうなります.この式を見ると、for-next文で書きやすい形式だと判るでしょう.またhard logicに実装するのも楽な形式です.
 (式3)
以上が勾配降下法のアバウトな考え方です.


書籍ではこの修正式を動かすsample programがTensorFlowオブジェクトを活用して書かれています.なのですがブラックボックス的でかな~りイミフです.
1)近似関数y=ax+bのサブルーチン
def model(x):
    y = a*x + b
    return y

2)2乗誤差関数のサブルーチン.式1を記述している
def loss(y_pred, y_true):
    return tf.math.reduce_mean(tf.math.square(y_pred - y_true))

3)近似値配列を生成
    y_pred = model(train_x_std) 

4)2乗誤差配列を生成
    tmp_loss = loss(y_pred, train_y_std)

5)偏微分、さっぱり判らないのがここ.
    gradients = tape.gradient(tmp_loss, [a, b])
gradientへ渡しているのは2乗誤差配列と微分変数のaとbのみ.式3を計算するのに材料が不足しているのは何故ですか?

6)aとbの修正.learning_rate は上で述べた0.01のこと.
    a.assign_sub(learning_rate * gradients[0])
    b.assign_sub(learning_rate * gradients[1])

いったい何をやってるんだろうねぇ?
TensorFlowオブジェクトのソースを読む気はありません.
想像するに、式3の処理をやってるのでは無いんじゃないかね?
式2の処理を数値演算的にやってるのではないかな?
  (式2a)
  (式2b)
すなわち、TensorFlowオブジェクトにはloop各回のE,a,b,x,yのすべてがwork areaに記録されていると仮定する.そして微分の代わりに差分で計算しているんじゃないだろうか? この式のように.
  (式2’)
LSIにhard logicで実装するのならこのようなメモリを喰う実装はしないものですが、リソースリッチなPCならこういう実装もありなのでしょう.汎用性が高まって便利だし.


↓sample programをいじって2次関数近似にしてみました.なんかいい感じ~

小さなことをコツコツと.

かしこ

10 件のコメント:

  1. これ見てて思い出したのですが、
    世の中には、「暗号通信」というものがあります。
    では、この暗号通信は、どうやって「同期をとっている」か、ご存じでしょうか?
    「暗号通信」と言う位なので、もちろん、表立った「同期信号」なんてありません。
    (あったら、そこから解読されてしまう恐れがあります。)
    ※正確に言うと「同期信号」まで含めて「暗号化されている」感じ
    誰にも知られることなくひっそり「開始」して、
    誰にも知られることなくひっそり「終了」するイメージ

    答えは・・・・
    「とりあえず、来た信号を『復号』してみる」です。
    当然、最初は同期が合うはずないので「デタラメ」な値が出てきます。しかしここで、とりあえずは、
    「同期がとれていない」という状態がわかるので、次にデータをシフトして、もう一度「復号」してみる・・・・
    これを、「ちゃんと復号できるまで」繰り返します。
    ※一旦復号出来れば、同期がとれたことになるので、続いたデータは「正常に」復号できます。
    (何らかの理由で、また「復号できなくなった」場合は、最初からやり直します)
    ※例として「暗号通信」と、言いましたが、いわゆる「デジタル通信の同期」は、みな基本的には、このような仕組みで同期をとっています。
    (もちろん、平坂さんは専門家なので、こんなのはご存じと思いますが・・・)
    ※まだ自分が若いころ、最初にこのやり方を聞いたときには、
    「考えた人は、天才だ!」と、思いました。当時は、この「とりあえずやってみる」という考え方になじめなかったことを思い出します。一種の「パラダイムシフト」ですね。

    -----
    >式3を計算するのに材料が不足
    勝手な予測ですが、引数は「値」ではなくて「オブジェクト」っぽいので、わかりやすく言うと、
    「書かれてないものは、勝手にどこかから引っ張ってきてる」んじゃないですかね?
    >y = a*x + b
    の、a,b,x,y とも、全部(tensor)オブジェクトとして定義されていれば、これだけで
    「すべてがあらわされてる」ように思いますが。

    >微分の代わりに差分
    デジタルコンピュータは、真の「微分」は出来ないので、そうでしょうね。差分なんて、要素の「引き算」で、出来ますからね。
    (数学的にも「すべての微分方程式は、差分方程式に変換」できますからね。)
    ※(精度を別にすれば)「真の『微分』」ができるのは、アナログコンピュータだけです。

    返信削除
    返信
    1. >全部(tensor)オブジェクトとして定義されて

      引用はしませんでしたが、Tapeオブジェクトというなんでも保存オブジェクトでloopを回してます.そしてTapeの中にはなんでも入っていてなんでも引っ張れるみたいです.おっしゃるとーりで.
      ブラックボックス的ですわー

      削除
    2. 数式処理的にオブジェクト内部で数式微分してるのかとも思いましたけど、それは忘れることにしました.

      削除
    3. 暗号通信ってそんなですか、アバウトすぎて草生えるw

      いっそのこと原子時計でもつかってくれたら苦しゅうない...

      削除
    4. >数式処理的にオブジェクト内部で数式微分
      その昔「REDUCE」というのがありまして、
      X^2 の微分が、ちゃんと 2X って帰ってきて感動してたことがあります。

      まぁでも、最近のいわゆるAIは、これと全く方向性が逆で、
      「X^2 の微分は?」と聞くと、
      「ありとあらゆる関数」を試して、
      「2X のグラフが、一番近そうです」
      って、答えてる感じなんだよね。単に、
      「手あたり次第、試行錯誤するのが得意」
      なだけな気がする。

      削除
    5. >X^2 の微分が、ちゃんと 2X

      そうなんですよね.あれを最初にやった時は感動します.めちゃくちゃな式を微分して遊びました.

      >AIはこれと全く方向性が逆

      総当たりで結果オーライを見つけるAIさんです.
      それでレントゲン写真の肺がん病巣を人間の目よりも高確率で見つけられたりするんですから偉いもんです.

      削除
    6. >いっそのこと原子時計でもつかってくれたら
      実は、携帯が3Gの頃は、同期をとるために、基地局1つ1つに
      「原子時計」が、入ってました。(今でもあるけど)
      4G/5G になると、それでは間に合わなくなって、基地局1つ1つに
      「GPSのアンテナ」を,立てて「GPSで同期」を、取るようになったみたいです。
      ※もはや「数十ns」の、オーダーで、同期してるらしい。

      >暗号通信ってそんなですか
      いわゆる「デジタル通信(ケータイも地デジもWifiも)」は、みんな
      「何らかの形で暗号化」されてるので、原理的には「みーんな、こんな感じ」ですね。

      ※個人的には、この「とりあえずやってみる方式」が、主流になってから、世の中がおかしくなってきてる気がする。
      Ethernetも、「通信」って言ってるけど「受け手がいなくても、とりあえず送信してみる」なんですよね(なので、これは「放送」だって、言ってる人がいた)

      ※なんか「なんでもいいからやれ!」という、社会の風潮に呼応してるのだろうか?そりゃ、社会から何から「ブラックボックス化」するわな。
      何でも「力まかせ」に、やればいいってもんじゃない、と思うのは自分だけ?
      (だから、取り残されてしまうのか・・・)

      削除
    7. >とりあえずやってみる方式

      windowsのupdate →とりあえずuserで実験しよう
      コロナワクチン →とりあえず国民で治験しよう

      ethernet →とりあえず高速送信してダメだったら遅くして再送しよう(通信屋の発想)

      5G →条件が良ければ高速です (通信屋の発想)

      USBはNo errorな通信路を前提としている風に感じます.(コンピュータ屋の発想)

      削除
  2. >LSIにhard logicで実装するのならこのようなメモリを喰う実装はしないもの
    なんか最近は「メモリ付きCPLD」なんて、あたりまえなので、みんな
    「こんな実装ばかり」に、なってる気がします。
    ※HLDでも、簡単に「ループ構文」書けますものね。
    (もちろん、その分「ハードウエアリソース」を、喰うわけですが。

    返信削除
    返信
    1. CPLDにメモリかぁ.なんつうアンバランスなアーキテクチャかと思いぱしってしまいました.

      削除