Wat zijn de verschillen tussen numpy.random.rand
en numpy.random.randn
?
Uit de documentatie weet ik dat het enige verschil tussen beide de probabilistische verdeling is waaruit elk getal is afgeleid, maar de algehele structuur (dimensie) en het gebruikte gegevenstype (float) is hetzelfde. Ik heb hierdoor moeite met het debuggen van een neuraal netwerk.
In het bijzonder probeer ik het neurale netwerk uit het Neural Network and Deep Learning-boek van Michael Nielson opnieuw te implementeren . De originele code vindt u hier. Mijn implementatie was hetzelfde als het origineel; ik heb echter in plaats daarvan gewichten en vooroordelen gedefinieerd en geïnitialiseerd met numpy.random.rand
in de functie init
, in plaats van de numpy.random.randn
functioneren zoals weergegeven in het origineel.
Mijn code die random.rand
gebruikt om weights and biases
te initialiseren, werkt echter niet. Het netwerk zal niet leren en de gewichten en vooroordelen zullen niet veranderen.
Wat zijn de verschillen tussen de twee willekeurige functies die deze gekheid veroorzaken?
Antwoord 1, autoriteit 100%
Ten eerste, zoals je kunt zien in de documentatie, genereert numpy.random.randn
steekproeven uit de normale verdeling, terwijl numpy.random.rand
uit een uniforme verdeling (in de bereik [0,1)).
Ten tweede, waarom werkte de uniforme verdeling niet? De belangrijkste reden is de activeringsfunctie, vooral in het geval dat u de sigmoid-functie gebruikt. De plot van de sigmoid ziet er als volgt uit:
Je kunt dus zien dat als je invoer weg is van 0, de helling van de functie vrij snel afneemt en als resultaat krijg je een kleine gradiënt en een kleine gewichtsupdate. En als je veel lagen hebt – die gradiënten worden vele malen vermenigvuldigd in de back-pass, dus zelfs “juiste” gradiënten na vermenigvuldigingen worden klein en hebben geen invloed meer. Dus als je veel gewichten hebt die je input naar die regio’s brengen, is je netwerk nauwelijks te trainen. Daarom is het gebruikelijk om netwerkvariabelen rond de nulwaarde te initialiseren. Dit wordt gedaan om ervoor te zorgen dat u redelijke hellingen (bijna 1) krijgt om uw net te trainen.
Een uniforme verdeling is echter niet iets volledig ongewenst, je moet het bereik alleen kleiner maken en dichter bij nul. Een van de goede praktijken is het gebruik van Xavier-initialisatie. In deze benadering kunt u uw gewichten initialiseren met:
-
Normale verdeling. Waar het gemiddelde 0 is en
var = sqrt(2. / (in + out))
, waarbij in – het aantal inputs voor de neuronen is en out – het aantal outputs. -
Uniforme verdeling in bereik
[-sqrt(6. / (in + out)), +sqrt(6. / (in + out))]
Antwoord 2, autoriteit 45%
np.random.rand
is voor uniforme distributie (in het halfopen interval[0.0, 1.0)
)np.random.randn
is voor Standaard Normale (ook wel Gaussiaanse) distributie (gemiddelde 0 en variantie 1)
Je kunt de verschillen tussen deze twee heel gemakkelijk visueel ontdekken:
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()
Welke producten:
en
Antwoord 3
1) numpy.random.rand
van uniform(binnen bereik [0,1))
2) numpy.random.randn
genereert voorbeelden van de normale verdeling