web-dev-qa-db-ja.com

Pythonのnumpy.random.Randとnumpy.random.randnの違い

numpy.random.Randnumpy.random.randnの違いは何ですか?

ドキュメントから、それらの間の唯一の違いは各数が引き出される確率分布からであることを知っていますが、全体の構造(次元)と使用されるデータ型(float)は同じです。これを信じているため、ニューラルネットワークのデバッグに苦労しています。

具体的には、 Neural Network and Deep Learning book by Michael Nielson で提供されているニューラルネットワークを再実装しようとしています。元のコードは here にあります。私の実装は、元のnumpy.random.Randではなく、init関数のnumpy.random.randnで重みとバイアスを定義および初期化したことを除いて、元の実装と同じでした。

ただし、random.Randを使用してweights and biasesを初期化するコードは、ネットワークが学習せず、重みとバイアスが変更されないため機能しません。

2つのランダム関数の違いは、この奇妙さを引き起こしますか?

35
Phuc Le

最初に、ドキュメントからわかるように、numpy.random.randnは正規分布からサンプルを生成しますが、numpy.random.Randはunifrom(範囲[0,1))から生成します。

第二に、なぜ均一分布が機能しなかったのですか?この主な理由は、特にシグモイド関数を使用する場合のアクティベーション関数です。シグモイドのプロットは次のようになります。

enter image description here

したがって、入力が0から離れている場合、関数の勾配は非常に速く減少し、その結果、小さな勾配と小さな重みの更新が得られることがわかります。また、レイヤーが多数ある場合-これらのグラデーションはバックパスで何度も乗算されるため、乗算後の「適切な」グラデーションでさえ小さくなり、影響を与えなくなります。そのため、入力をこれらの地域にもたらす多くの重みがある場合、ネットワークはほとんどトレーニングできません。そのため、ネットワーク変数をゼロ値付近で初期化するのが通常の方法です。これは、適切な勾配(1に近い)を取得してネットをトレーニングするために行われます。

ただし、均一な分布は完全に望ましくないものではなく、範囲を小さくしてゼロに近づけるだけで済みます。 Xavierの初期化を使用することをお勧めします。このアプローチでは、次の方法で重みを初期化できます。

1)正規分布。ここで、meanは0およびvar = sqrt(2. / (in + out))で、in-はニューロンへの入力の数、outは出力の数です。

2)範囲[-sqrt(6. / (in + out)), +sqrt(6. / (in + out))]のUnifrom分布

52
asakryukin
  • np.random.Randは均一な配布用です(半開間隔[0.0, 1.0)
  • np.random.randnは、標準正規(別名ガウス)分布(平均0および分散1)用です。

これら2つの違いを視覚的に簡単に調べることができます。

import numpy as np
import matplotlib.pyplot as plt

sample_size = 100000
uniform = np.random.Rand(sample_size)
normal = np.random.randn(sample_size)

pdf, bins, patches = plt.hist(uniform, bins=20, range=(0, 1), density=True)
plt.title('Rand: uniform')
plt.show()

pdf, bins, patches = plt.hist(normal, bins=20, range=(-4, 4), density=True)
plt.title('randn: normal')
plt.show()

どのプロデュース:

enter image description here

そして

enter image description here

3
YaOzI