重みやバイアスを格納する配列の初期化に潜む罠
[python] [array]
MNIST手書き文字を認識するニューラルネットワークをkerasやtensorflowを使わずにすべて手書きでゴリゴリがいていた時、配列の初期化を間違えてひどい目にあったので二度と忘れないようにここに記します。
配列の初期化
<空の配列を初期化する>
array_a = []
<数値を直接入力して初期化>
array_b = [1, 2, 3, 4]
*文字や変数を入力することもできますが、今回は割愛
指定サイズ分(要素数)だけ0埋めして初期化
例えば、1行10列の配列を初期化したい場合
array1 = [0]*10
と入力すれば下記のように配列が出来上がります。
では、10行10列の場合はどうでしょう??
array2 = [[0]*10]*10
見事10行10列の配列が初期化されました、めでたし、めでたし
とはなりません。
少しこのarray2の配列をいじってみましょう。
例えば、5行4列目の値を48に変更してみます。
!!!!!!!
いやいや、これは何かの間違いに違いない、、、、
9行9列目の値を12に変更してみます。
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ピンポイントで値を更新したいのに、すべての列が更新されてしまう、、、
for i in rangeを使う
指定した要素のみを更新したい場合、配列の初期化は下記のようにします。
array3 = [[0 for i in range(10)]for i in range(10)]
5行4列目の値を48に変更してみます。
9行9列目の値を12に変更してみます。
値がピンポイントで更新されているのが確認できました。
まとめ
[[0]*10]*10のやり方は同じ配列を10個定義しているだけなので、要素の値を変更すると他の要素まで変わってしまいます。
[[0 for i in range(10)]for i in range(10)] の場合は内包表記を使って複数のリストを作っているので、指定した要素のみ値が変更されています。
ニューラルネットワークの重みやバイアスの初期値を設定するときに、[[0]*10]*10とかいてしまっていてひどい目にあいました。
皆様もお気を付けください。