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é?
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:
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))]
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:
et