PythonClassの関数は、引数だけ更新しても駄目

機械学習 Python R

ニューラルネットワークを書いて遊んでいて気付いた事です。

ニューラルネットワークのコード

シンプルなニューラルネットワークは以下のコードで作れます。

例えば、

とかで動かす事が出来ます。1どのように値が移っていくか見たい時は、

とかやれば、values に値が入っています。

はまった問題

ここからが本題です。ニューラルネットワークのパラメーターを決めるのには、勾配を計算するわけですが、数学っぽく、ニューラルネットワークを行列やベクトルの関数
$$\begin{eqnarray}
NN_x (W1,b1,W2,b2 )=W2\cdot (\sigma (W1 \cdot x+b1 ) +b2
\end{eqnarray}$$
とみて勾配を計算したいと思ったわけです。
という訳で、以下のようなコードを書きました。

NN_1 が\(W_1 \)の(1,1)成分を少しだけ変化させたニューラルネットワークの関数のつもりです。なので、気持ちとしては
$$\begin{eqnarray}
d=\frac{ \partial NN_x }{\partial W1_{1,1} }
\end{eqnarray}$$
を計算しているつもりです。勿論この値は0にはなりませんが、上のように計算するとd=0が帰ってきます。

解決策

何故なのか調べます。

パラメーター自体はしっかり更新されているようです。2次に、順伝搬させて値をチェックします。

値を見てみると、NNでもNN_1 でも同じ値が返っています。パラメーターの値自体は更新されましたが、関数としては変更されてないみたいです。
解決は、以下のように1行書けば出来ます。

という訳で、関数みたいにクラスを使いたかったら、パラメーター自身でなくて層を更新してあげないといけませんでした。
簡単な解決策は、SimpleNet classのpredict関数を呼び出す毎に、層を更新させる事です。

これで勾配が計算出来ます。

困ったことの簡単な再現

単純なコードで、問題を再現します。問題は一言で言えば、関数の中だけ更新しても駄目という事でした次のような状況でした。

最後のmasamune.togetoge()では、masamune kawai と出力されてほしい訳ですが、
masa[“mune”]を更新した訳ではないので欲しい出力が得られなかったという訳です。これを解決するには、togetoge関数を呼び出すたびにmasa[“mune”]を更新すればいい訳です。

まとめ

  • 困ったことを紹介した
  • 解決策を紹介した
  • 困りごとを再現した
  • クラスの中の関数は、引数だけを更新しても駄目だと分かった。
  1. パラメーターも学習データも無いので、ただ値を返してくれるだけですが。
  2. deepcopyを使わないと、そもそもパラメーターが変更されません。
タイトルとURLをコピーしました