Как генерировать коррелированные случайные числа (с учетом средних, дисперсий и степени корреляции)?

53

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

Учитывая две псевдослучайные переменные роста и веса с известными средними и дисперсиями, а также данную корреляцию, я думаю, что я в основном пытаюсь понять, как должен выглядеть этот второй шаг:

   height = gaussianPdf(height.mean, height.variance)
   weight = gaussianPdf(correlated_mean(height.mean, correlation_coefficient), 
                        correlated_variance(height.variance, 
                        correlation_coefficient))
  • Как рассчитать коррелированное среднее значение и дисперсию? Но я хочу подтвердить, что это действительно актуальная проблема здесь.
  • Нужно ли прибегать к матричным манипуляциям? Или у меня есть что-то очень неправильное в моем базовом подходе к этой проблеме?
Иосиф Вайсман
источник
1
Не уверен, что я вас правильно понимаю, но вам не нужно вычислять «среднее значение и дисперсию». Если вы предполагаете, что переменные являются двумерными нормальными, этого должно быть достаточно, чтобы указать отдельные средние и дисперсии и корреляцию. Есть ли какое-то конкретное программное обеспечение, которое вы хотите использовать для этого?
mark999

Ответы:

44

Чтобы ответить на ваш вопрос о «хорошем, в идеале быстром способе генерирования коррелированных случайных чисел»: учитывая желаемую дисперсионно-ковариационную матрицу которая по определению является положительно определенной, ее разложение Холецкого имеет вид: C = L L T ; L - нижняя треугольная матрица.ССLLTL

Если вы теперь используете эту матрицу для проекции некоррелированного вектора случайных величин X , результирующая проекция Y = L X будет проекцией коррелированных случайных величин.LИксYзнак равноLИкс

Вы можете найти краткое объяснение, почему это происходит здесь .

usεr11852 говорит восстановить Monic
источник
Спасибо! Это было чрезвычайно полезно. Я думаю, что я, по крайней мере, лучше понимаю, что мне нужно смотреть дальше.
Джозеф Вайсман
7
Применяется ли этот метод только для гауссовых распределений (как указано в вопросе) или он может использоваться для генерации коррелированных переменных, которые следуют за другими распределениями? Если нет, знаете ли вы о методе, который можно использовать в этом случае?
user000001
1
@ Майкл: Да. Сказав, что данная является допустимой ковариационной матрицей, разложение Холецкого является самым быстрым способом. Вы также можете получить (симметричную) матрицу X квадратного корня из C , используя SVD (так что C = X X = X X T , где X = U S 0,5 V T от C = U S V T ), но это будет дороже слишком. СИксССзнак равноИксИксзнак равноИксИксTИксзнак равноUS0,5ВTСзнак равноUSВT
usεr11852 говорит восстановить Monic
1
@ Майкл: Конечно. Их ковариация будет (примерно) одинаковой, а не сами цифры.
usεr11852 говорит восстановить Monic
1
@Sid: Любое непрерывное распространение, не поддерживаемое на всей реальной линии, немедленно завершится неудачей. Например, если мы используем унифицированную мы не можем гарантировать, что «коррелированные числа» будут в [ 0 , 1 ] ; аналогично для Пуассона мы получим недискретные числа. Кроме того, любое распределение, в котором сумма распределений не является тем же распределением (например, суммирование t -распределения не приводит к t -распределениям), также будет неудачным. Во всех случаях , упомянутых, число , полученное будет коррелировать в соответствии с CU[0,1][0,1]TTСно они не будут соответствовать распределению, которое мы начали.
usεr11852 говорит восстановить Monic
36

+1 к @ user11852 и @ jem77bfp, это хорошие ответы. Позвольте мне подойти к этому с другой точки зрения, не потому, что я думаю, что это обязательно лучше на практике , а потому, что я думаю, что это поучительно. Вот несколько важных фактов, которые мы уже знаем:

  1. представляет собой наклон линии регрессиикогда оба Х и Y являютсястандартизированы, то есть N ( 0 , 1 ) , рИксYN(0,1)
  2. - доля дисперсии в Y, относящаяся к дисперсии в X , р2YИкс



    (также из правил для отклонений ):

  3. дисперсия случайной величины, умноженная на константу, представляет собой константу в квадрате, умноженную на исходную дисперсию:
    Var[aИкс]знак равноa2Var[Икс]
  4. дисперсии сложения , т. е. дисперсия суммы двух случайных величин (при условии, что они независимы) является суммой двух дисперсий:
    Var[Икс+ε]знак равноVar[Икс]+Var[ε]

Теперь мы можем объединить эти четыре факта, чтобы создать две стандартные нормальные переменные, популяции которых будут иметь заданную корреляцию (точнее, ρ ), хотя сгенерированные вами выборки будут иметь выборочные корреляции, которые различаются. Идея состоит в том, чтобы создать псевдослучайную переменную X , которая является стандартной нормалью, N ( 0 , 1 ) , а затем найти коэффициент a и дисперсию ошибки v e , такую, что Y N ( 0 , a 2 + v е ) , гдерρИксN(0,1)avеY~N(0,a2+vе) . (Обратите внимание, что | a | должно быть1, чтобы это работало, и, кроме того, a = r .) Таким образом, вы начинаете с r , который хотите; это твой коэффициент, а . Затем вы вычисляете дисперсию ошибки, которая вам понадобится, это 1 - r 2 . (Если ваше программное обеспечение требует, чтобы вы использовали стандартное отклонение, возьмите квадратный корень из этого значения.) Наконец, для каждогосгенерированного вамипсевдослучайного значения x i сгенерируйте псевдослучайное значение ошибки, e ia2+vезнак равно1|a| 1aзнак равноррa1-р2Иксяея, с соответствующей дисперсией ошибки , и вычислить коррелированную псевдослучайную переменную, y i , путем умножения и сложения. vеYя

Если вы хотите сделать это в R, следующий код может работать для вас:

correlatedValue = function(x, r){
  r2 = r**2
  ve = 1-r2
  SD = sqrt(ve)
  e  = rnorm(length(x), mean=0, sd=SD)
  y  = r*x + e
  return(y)
}

set.seed(5)
x = rnorm(10000)
y = correlatedValue(x=x, r=.5)

cor(x,y)
[1] 0.4945964

(Изменить: я забыл упомянуть :) Как я уже описал, эта процедура дает вам две стандартные нормальные коррелированные переменные. Если вам не нужны стандартные нормали, но вы хотите, чтобы переменные имели определенные средние значения (не 0) и SD (не 1), вы можете преобразовать их, не влияя на корреляцию. Таким образом, вы должны вычесть наблюдаемое среднее значение, чтобы убедиться, что среднее значение равно , умножить переменную на нужный вам SD и затем добавить среднее значение, которое вы хотите. Если вы хотите, чтобы наблюдаемое среднее значение обычно колебалось вокруг желаемого среднего, вы бы вернули начальную разницу обратно. По сути, это преобразование z-счета в обратном направлении. Поскольку это линейное преобразование, преобразованная переменная будет иметь ту же корреляцию с другой переменной, что и раньше. 0

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

Gung - Восстановить Монику
источник
Этот по существу регрессионный подход особенно хорош тем, что позволяет генерировать один случайный Y, коррелированный с любым количеством существующих X «предикторов». Прав ли я в таком понимании?
ttnphns
Это зависит от того, какой именно шаблон корреляций среди переменных вы хотите, @ttnphns. Вы можете повторять это один за другим, но это будет утомительно. Чтобы создать много коррелированных переменных с заданным шаблоном, лучше использовать разложение Холецкого.
gung - Восстановить Монику
gung, знаете ли вы, как использовать Cholesky для генерации одного Y-коррелированного (приблизительно, как в вашем методе) в соответствии с вектором корреляций с несколькими существующими (не имитированными) Xs?
ttnphns
@ttnphns, вы хотите сгенерировать один Y с заданной корреляцией популяции с набором X, а не с набором p переменных, которые все имеют заранее определенные корреляции популяции? Простым способом было бы написать уравнение регрессии, чтобы сгенерировать одну Y-шляпу из ваших X, а затем использовать метод выше, чтобы сгенерировать Y как коррелят вашей Y-шляпы. Вы можете задать новый вопрос об этом, если хотите.
gung - Восстановить Монику
1
Вот что я имел в виду в своем первоначальном комментарии: этот метод будет прямым продолжением того, о чем вы говорите в своем ответе: по сути, это регрессионный (Hat) метод.
ttnphns
16

В общем, это не простая вещь, но я считаю, что есть пакеты для многофакторной генерации нормальной переменной (по крайней мере, в R, см. mvrnormВ MASSпакете), где вы просто вводите ковариационную матрицу и средний вектор.

Есть и еще один «конструктивный» подход. Допустим, мы хотим смоделировать случайный вектор и у нас есть его функция распределения F ( x 1 , x 2 ) . Первый шаг - получить функцию предельного распределения; т.е. интегрировать F по всем x 2 : F X 1 ( x 1 ) = - F ( x 1 , x 2 ) d x 2(Икс1,Икс2)F(Икс1,Икс2)FИкс2 Затем мы находим F - 1 X 1 - обратную функцию от F X 1 - и включаем случайную величину ξ 1, которая равномерно распределена на интервале [ 0 , 1 ] . На этом шаге мы создаем первую координату х 1 = F - 1 X 1 ( £ , ) .

FИкс1(Икс1)знак равно-F(Икс1,Икс2)dИкс2,
FИкс1-1FИкс1ξ1[0,1]Икс^1знак равноFИкс1-1(ξ)

Теперь, так как мы получили одну координату, необходимо подключить его к исходной функции распределения , а затем получить условную функцию распределения с условием х 1 = х 1 : F ( х 2 | X 1 = х 1 ) = Р ( х 1 , х 2 )F(Икс1,Икс2)Икс1знак равноИкс^1 гдеFХ1является функцией плотности вероятности предельногоХ1распределение; то естьF ' X 1 (x1)=fX1(x1).

F(Икс2|Икс1знак равноИкс^1)знак равноF(Икс^1,Икс2)еИкс1(Икс^1),
еИкс1Икс1FИкс1'(Икс1)знак равноеИкс1(Икс1)

ξ2[0,1]ξ1F(Икс2|Икс1знак равноИкс^1)Икс^2знак равно(F(Икс2|Икс1знак равноИкс^1))-1(ξ)Икс^2F(Икс^2|Икс1знак равноИкс^1)знак равноξ

Если вы не понимаете смысла включения равномерной переменной в функцию обратного распределения вероятностей, попробуйте сделать набросок одномерного случая и затем запомните, какова геометрическая интерпретация обратной функции.

jem77bfp
источник
Умная идея! Имеет простую интуитивную привлекательность. Но да, кажется дорогим в вычислительном отношении.
MichaelChirico,
еИкс,Y(Икс,Y)знак равноеИкс(Икс)еY|Икс(Y)
1

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

{Икся}язнак равно1N{Yя}язнак равно1NС

соLdзнак равносорр({Икся},{Yя})

N1N2:1N1,2N

ИксN1ИксN2

сNевесзнак равносорр({Икся},{Yя})

|С-сNевес|<|С-соLd|

|С-с|<ε

Икся

Удачи!

Ф. Джатпил
источник
Иксясорр(Икся,Yя)
Икся{Икся}Yсорр(Икся,Yя)сорр({Икся},{Yя})знак равно(1/N)Σязнак равно1N(Икся-Икс¯)(YY-Y¯)
{}сорр({Икся},{Yя})