web-dev-qa-db-fra.com

Différences entre numpy.random.Rand et numpy.random.randn dans Python

Quelles sont toutes les différences entre numpy.random.Rand et numpy.random.randn?

Docs, je sais que la seule différence entre eux provient de la distribution probabiliste à partir de laquelle chaque nombre est tiré, mais la structure globale (dimension) et le type de données utilisé (float) sont les mêmes. J'ai du mal à déboguer un réseau de neurones à cause de cela.

Plus précisément, j'essaie de ré-implémenter le réseau de neurones fourni dans le livre sur les réseaux de neurones et l'apprentissage en profondeur de Michael Nielson . Le code original peut être trouvé ici . Mon implémentation était la même que celle d'origine, sauf que j'ai défini et initialisé des poids et des biais avec numpy.random.Rand dans init fonction, plutôt que numpy.random.randn comme dans l'original.

Cependant, mon code qui utilise random.Rand pour initialiser weights and biases ne fonctionne pas car le réseau n’apprendra pas et les poids et les biais ne changeront pas.

Quelle différence (s) entre deux fonctions aléatoires provoque cette étrangeté?

35
Phuc Le

Tout d’abord, comme vous le voyez dans la documentation, numpy.random.randn Génère des échantillons de la distribution normale, tandis que numpy.random.Rand Provient de unifrom (dans la plage [0,1)].

Deuxièmement, pourquoi la distribution uniforme n'a pas fonctionné? La raison principale dans cette fonction d'activation, en particulier dans le cas où vous utilisez la fonction sigmoïde. L'intrigue du sigmoïde ressemble à ceci:

enter image description here

Ainsi, vous pouvez voir que si votre entrée est éloignée de 0, la pente de la fonction diminue assez rapidement et vous obtenez ainsi un très petit gradient et une mise à jour minime du poids. Et si vous avez plusieurs couches - ces gradients se multiplient plusieurs fois dans le passage arrière, de sorte que même les gradients "appropriés" après multiplications deviennent petits et cessent d'influer. Donc, si vous avez beaucoup de poids qui apportent votre contribution à ces régions, votre réseau est difficilement entraînable. C’est pourquoi il est courant d’initialiser les variables réseau autour de la valeur zéro. Ceci est fait pour vous assurer que vous obtenez des gradients raisonnables (près de 1) pour entraîner votre filet.

Cependant, la distribution uniforme n'est pas complètement indésirable, il vous suffit de réduire la plage et de la rapprocher de zéro. L'une des bonnes pratiques consiste à utiliser l'initialisation de Xavier. Dans cette approche, vous pouvez initialiser vos poids avec:

1) Distribution normale. Où moyenne est 0 et var = sqrt(2. / (in + out)), où - est le nombre d'entrées dans les neurones et le nombre de sorties.

2) Distribution Unifrom dans la plage [-sqrt(6. / (in + out)), +sqrt(6. / (in + out))]

52
asakryukin
  • np.random.Rand Est destiné à la distribution uniforme (dans l'intervalle semi-ouvert [0.0, 1.0))
  • np.random.randn Correspond à la distribution normale normale (gaussienne) (moyenne 0 et variance 1)

Vous pouvez explorer visuellement les différences entre ces deux très facilement:

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()

Quel produit:

enter image description here

et

enter image description here

3
YaOzI