Подтвердить что ты не робот

Различия между numpy.random.rand vs numpy.random.randn в Python

Каковы все различия между numpy.random.rand и numpy.random.randn?

Из документов я знаю, что единственное различие между ними заключается в вероятностном распределении, из которого взяты все числа, но общая структура (измерение) и используемый тип данных (с плавающей точкой) одинаковы. Мне трудно отлаживать нейронную сеть из-за веры в это.

В частности, я пытаюсь повторно реализовать нейронную сеть, представленную в книге " Нейронная сеть и глубокое обучение" Майкла Нильсона. Оригинальный код можно найти здесь. Моя реализация была такой же, как и оригинальная, за исключением того, что я определил и инициализировал веса и смещения с помощью numpy.random.rand в функции init, а не numpy.random.randn как в оригинале.

Однако мой код, который использует random.rand для инициализации weights and biases, не работает, потому что сеть не будет учиться, а весы и смещения не изменятся.

Какая разница между двумя случайными функциями вызывает эту странность?

4b9b3361

Ответ 1

Во-первых, как вы видите из документации, numpy.random.randn генерирует образцы из нормального распределения, а numpy.random.rand из unifrom (в диапазоне [0,1)).

Во-вторых, почему не работает равномерное распределение? Основной причиной этого является функция активации, особенно в том случае, когда вы используете сигмовидную функцию. Сюжет сигмовидной кишки выглядит следующим образом:

enter image description here

Таким образом, вы можете видеть, что если ваш ввод от 0, наклон функции уменьшается довольно быстро, и в результате вы получаете крошечный градиент и крошечное обновление веса. И если у вас много слоев - эти градиенты многократно умножаются на обратном проходе, поэтому даже "правильные" градиенты после умножения становятся маленькими и перестают оказывать какое-либо влияние. Так что, если у вас много весов, которые приносят ваш вклад в те регионы, ваша сеть вряд ли поддается обучению. Вот почему обычная практика - инициализировать сетевые переменные с нулевым значением. Это сделано для того, чтобы вы получили разумные градиенты (около 1) для обучения своей сети.

Однако равномерное распределение не является чем-то совершенно нежелательным, вам просто нужно уменьшить диапазон и приблизить его к нулю. Одной из хороших практик является использование инициализации Xavier. При таком подходе вы можете инициализировать свои веса с помощью:

1) Нормальное распределение. Где среднее значение равно 0, а var = sqrt(2./(in + out)), где in - количество входов в нейроны, а out - количество выходов.

2) равномерное распределение в диапазоне [-sqrt(6./(in + out)), +sqrt(6./(in + out))]

Ответ 2

  • np.random.rand для равномерного распределения (в полуоткрытом интервале [0.0, 1.0))
  • np.random.randn предназначен для стандартного нормального (он же гауссовского) распределения (среднее значение 0 и дисперсия 1).

Вы можете легко визуально изучить различия между этими двумя:

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