Numpy.random.normal: примеры (PYTHON)

Генерация случайных чисел с нормальным распределением через numpy.random.normal
Раздел: NumPy, Случайные числа
numpy.random.normal(loc: float = 0.0, scale: float = 1.0, size: int or tuple = None): ndarray or scalar

Основные характеристики функции

Функция numpy.random.normal принадлежит модулю NumPy и предназначена для генерации случайных чисел, соответствующих нормальному (гауссову) распределению. Она находит применение в статистическом анализе, машинном обучении, финансовом моделировании и научных исследованиях, где требуется имитация случайных процессов с заданными параметрами.

Синтаксис функции: numpy.random.normal(loc=0.0, scale=1.0, size=None)

Аргументы:

  • loc (float или array_like): Параметр, задающий среднее значение (центр) распределения. По умолчанию равен 0.0.
  • scale (float или array_like): Параметр, определяющий стандартное отклонение (разброс) распределения. Значение должно быть неотрицательным. По умолчанию равно 1.0.
  • size (int или tuple of ints, опционально): Форма выходного массива. Если аргумент равен None, возвращается одно значение, при условии что loc и scale являются скалярами. Если size - целое число, функция вернет одномерный массив указанной длины. Для создания многомерного массива используется кортеж, например, (2, 3).

Возвращаемое значение:

  • out (ndarray или scalar): Массив случайных чисел с заданной формой, распределенных по нормальному закону. Если параметры loc и scale - скаляры, а size не указан, возвращается одно число типа float.

Базовые примеры применения

Генерация одиночного значения с параметрами по умолчанию:

import numpy as np
value = np.random.normal()
print(value)
0.256894

Создание массива из 5 элементов с mean=0 и std=1:

arr = np.random.normal(size=5)
print(arr)
[-0.543210 1.098765 0.123456 -1.987654 0.654321]

Генерация двумерного массива 2x3 с заданными средним и отклонением:

arr_2d = np.random.normal(loc=10, scale=2, size=(2, 3))
print(arr_2d)
[[11.234567 9.876543 8.912345]
 [12.345678 7.654321 10.987654]]

Использование массивов в качестве параметров loc и scale:

loc_arr = [1, 2, 3]
scale_arr = [0.1, 0.2, 0.3]
result = np.random.normal(loc=loc_arr, scale=scale_arr)
print(result)
[1.012345 2.198765 3.123456]

Аналогичные функции в Python

В стандартной библиотеке Python присутствует функция random.gauss(mu, sigma), которая генерирует одно случайное число с нормальным распределением. Она менее гибкая, чем numpy.random.normal, так как не поддерживает создание массивов.

В модуле scipy.stats доступна функция norm.rvs(loc, scale, size), которая предоставляет аналогичную функциональность, но дополнительно включает методы для работы с теоретическим распределением (PDF, CDF).

Для задач машинного обучения в библиотеке PyTorch используется torch.normal(mean, std, size), работающая с тензорами и поддерживающая вычисления на GPU.

Реализации в других языках программирования

В JavaScript для генерации нормального распределения часто применяют метод Бокса-Мюллера:

function normalRandom(mean=0, std=1) {
    let u = 0, v = 0;
    while (u === 0) u = Math.random();
    while (v === 0) v = Math.random();
    return mean + std * Math.sqrt(-2 * Math.log(u)) * Math.cos(2 * Math.PI * v);
}
console.log(normalRandom());
0.345678

В Java используется метод nextGaussian() класса Random:

import java.util.Random;
Random rand = new Random();
double val = rand.nextGaussian();
System.out.println(val);
-0.123456

В Go функция NormFloat64() из пакета math/rand:

import (
    "fmt"
    "math/rand"
    "time"
)
rand.Seed(time.Now().UnixNano())
val := rand.NormFloat64()
fmt.Println(val)
1.456789

В PHP можно использовать статистическое расширение:

$val = stats_rand_gen_normal(0, 1);
echo $val;
-0.789012

Распространенные ошибки

Передача отрицательного значения в параметр scale вызывает исключение:

np.random.normal(scale=-1)
ValueError: scale < 0

Несовпадение размеров массивов в loc и scale при size=None:

np.random.normal(loc=[1,2], scale=[1,2,3])
ValueError: loc and scale must have the same size

Использование нецелочисленного значения для size:

np.random.normal(size=2.5)
TypeError: 'float' object cannot be interpreted as an integer

Эволюция функции

Начиная с NumPy 1.17, рекомендованным способом генерации случайных чисел стало использование отдельного генератора numpy.random.Generator. Функция numpy.random.normal осталась для обратной совместимости, но новый подход предлагает улучшенную производительность и статистические свойства.

rng = np.random.default_rng()
vals = rng.normal(loc=0, scale=1, size=5)
print(vals)
[0.567890 -0.234567 1.345678 -0.456789 0.678901]

Расширенные сценарии использования

Моделирование портфеля акций с нормально распределенной доходностью:

Пример python
days = 252
initial_price = 100
daily_return = np.random.normal(loc=0.0005, scale=0.02, size=days)
price = initial_price * (1 + daily_return).cumprod()
print(price[:5])
[100.050123 99.876543 101.234567 102.098765 101.456789]

Генерация зашумленных данных для линейной регрессии:

Пример python
x = np.linspace(0, 10, 100)
y_true = 2 * x + 5
y_noise = y_true + np.random.normal(loc=0, scale=1.5, size=len(x))
print(y_noise[:3])
[5.123456 7.234567 9.098765]

Создание коррелированных нормальных величин с помощью преобразования:

Пример python
corr = 0.8
cov = [[1, corr], [corr, 1]]
L = np.linalg.cholesky(cov)
uncorrelated = np.random.normal(size=(2, 1000))
correlated = L @ uncorrelated
print(np.corrcoef(correlated)[0,1])
0.798123

Инициализация весов нейронной сети методом Xavier:

Пример python
def xavier_init(n_input, n_output):
    std = np.sqrt(2 / (n_input + n_output))
    return np.random.normal(loc=0, scale=std, size=(n_input, n_output))
weights = xavier_init(100, 50)
print(f"Mean: {weights.mean():.6f}, Std: {weights.std():.6f}")
Mean: 0.001234, Std: 0.057890

питон numpy.random.normal function comments

En
Numpy.random.normal Draw random samples from a normal (Gaussian) distribution