Я моделирую рассредоточение завода, используя обобщенное нормальное распределение ( запись в Википедии ), которое имеет функцию плотности вероятности:
где - пройденное расстояние, - параметр масштаба, а - параметр формы. Среднее пройденное расстояние определяется стандартным отклонением этого распределения:б
Это удобно, потому что учитывает экспоненциальную форму, когда , гауссову форму, когда , и лептокуротическое распределение, когда . Это распределение регулярно встречается в литературе по рассеиванию растений, хотя в целом оно встречается довольно редко и, следовательно, трудно найти информацию.
Наиболее интересными параметрами являются и среднее расстояние разгона.
Я пытаюсь оценить и используя MCMC, но я изо всех сил пытаюсь эффективный способ для отбора значений предложений. До сих пор я использовал «Метрополис-Гастингс» и опирался на равномерное распределение и , и я получил средние расстояния рассеяния около 200-400 метров, что имеет биологический смысл. Однако конвергенция действительно медленная, и я не уверен, что она исследует все пространство параметров.
Сложно придумать лучшее распределение предложений для и , потому что они зависят друг от друга, не имея большого значения сами по себе. Среднее расстояние рассеивания имеет четкое биологическое значение, но данное среднее расстояние рассеяния может быть объяснено бесконечным числом комбинаций и . Как таковые и коррелируют сзади.
До сих пор я использовал Metropolis Hastings, но я открыт для любого другого алгоритма, который бы работал здесь.
Вопрос: Может ли кто-нибудь предложить более эффективный способ получения значений предложений для и ?
Изменить: Дополнительная информация о системе: я изучаю популяцию растений вдоль долины. Цель состоит в том, чтобы определить распределение расстояний, пройденных пыльцой между донорскими растениями и растениями, которые они опыляют. У меня есть данные:
- Расположение и ДНК для каждого возможного донора пыльцы
- Семена, собранные из образца 60 материнских растений (т.е. приемников пыльцы), которые были выращены и генотипированы.
- Расположение и ДНК для каждого материнского растения.
Я не знаю идентичности донорских растений, но это можно сделать из генетических данных, определив, какие доноры являются отцами каждого сеянца. Допустим, эта информация содержится в матрице вероятностей G со строкой для каждого потомства и столбцом для каждого донора-кандидата, который дает вероятность того, что каждый кандидат является отцом каждого потомка, основываясь только на генетических данных. Для вычисления G требуется около 3 секунд, и он должен пересчитываться на каждой итерации, что значительно замедляет процесс.
Поскольку мы обычно ожидаем, что более близкие кандидаты в доноры с большей вероятностью будут отцами, вывод отцовства будет более точным, если вы совместно сделаете вывод об отцовстве и расселении. Матрица D имеет те же размеры, что и G , и содержит вероятности отцовства, основанные только на функции расстояний между матерью и кандидатом и некоторого вектора параметров. Умножение элементов в D и G дает общую вероятность отцовства с учетом генетических и пространственных данных. Произведение умноженных значений дает вероятность дисперсии модели.
Как описано выше, я использовал GND для моделирования разгона. На самом деле, я фактически использовал смесь GND и равномерного распределения, чтобы учесть вероятность того, что очень отдаленные кандидаты имеют более высокую вероятность отцовства из-за одного случая (генетика грязная), которая раздула бы видимый хвост GND, если его игнорировать. Так что вероятность разгона расстояния равна:
где - вероятность рассеивания расстояния от GND, N - количество кандидатов, а ( ) определяет, какой вклад GND вносит в рассеяние.
Поэтому есть два дополнительных соображения, которые увеличивают вычислительную нагрузку:
- Расстояние разгона неизвестно, но должно быть выведено на каждой итерации, и создание G для этого стоит дорого.
- Существует третий параметр, , для интегрирования.
По этим причинам мне показалось, что это слишком сложно для интерполяции сетки, но я рад быть убежденным в обратном.
пример
Вот упрощенный пример кода Python, который я использовал. Я упростил оценку отцовства по генетическим данным, поскольку это потребовало бы большого количества дополнительного кода, и заменил его матрицей значений от 0 до 1.
Сначала определим функции для расчета GND:
import numpy as np
from scipy.special import gamma
def generalised_normal_PDF(x, a, b, gamma_b=None):
"""
Calculate the PDF of the generalised normal distribution.
Parameters
----------
x: vector
Vector of deviates from the mean.
a: float
Scale parameter.
b: float
Shape parameter
gamma_b: float, optional
To speed up calculations, values for Euler's gamma for 1/b
can be calculated ahead of time and included as a vector.
"""
xv = np.copy(x)
if gamma_b:
return (b/(2 * a * gamma_b )) * np.exp(-(xv/a)**b)
else:
return (b/(2 * a * gamma(1.0/b) )) * np.exp(-(xv/a)**b)
def dispersal_GND(x, a, b, c):
"""
Calculate a probability that each candidate is a sire
assuming assuming he is either drawn at random form the
population, or from a generalised normal function of his
distance from each mother. The relative contribution of the
two distributions is controlled by mixture parameter c.
Parameters
----------
x: vector
Vector of deviates from the mean.
a: float
Scale parameter.
b: float
Shape parameter
c: float between 0 and 1.
The proportion of probability mass assigned to the
generalised normal function.
"""
prob_GND = generalised_normal_PDF(x, a, b)
prob_GND = prob_GND / prob_GND.sum(axis=1)[:, np.newaxis]
prob_drawn = (prob_GND * c) + ((1-c) / x.shape[1])
prob_drawn = np.log(prob_drawn)
return prob_drawn
Далее имитируют 2000 кандидатов и 800 потомков. Также смоделируйте список расстояний между матерями потомства и отцами-кандидатами, а также фиктивную матрицу G.
n_candidates = 2000 # Number of candidates in the population
n_offspring = 800 # Number of offspring sampled.
# Create (log) matrix G.
# These are just random values between 0 and 1 as an example, but must be inferred in reality.
g_matrix = np.random.uniform(0,1, size=n_candidates*n_offspring)
g_matrix = g_matrix.reshape([n_offspring, n_candidates])
g_matrix = np.log(g_matrix)
# simulate distances to ecah candidate father
distances = np.random.uniform(0,1000, 2000)[np.newaxis]
Установите начальные значения параметров:
# number of iterations to run
niter= 100
# set intitial values for a, b, and c.
a_current = np.random.uniform(0.001,500, 1)
b_current = np.random.uniform(0.01, 3, 1)
c_current = np.random.uniform(0.001, 1, 1)
# set initial likelihood to a very small number
lik_current = -10e12
Обновите a, b и c по очереди и вычислите коэффициент метрополии.
# number of iterations to run
niter= 100
# set intitial values for a, b, and c.
# When values are very small, this can cause the Gamma function to break, so the limit is set to >0.
a_current = np.random.uniform(0.001,500, 1)
b_current = np.random.uniform(0.01, 3, 1)
c_current = np.random.uniform(0.001, 1, 1)
# set initial likelihood to a very small number
lik_current = -10e12
# empty array to store parameters
store_params = np.zeros([niter, 3])
for i in range(niter):
a_proposed = np.random.uniform(0.001,500, 1)
b_proposed = np.random.uniform(0.01,3, 1)
c_proposed = np.random.uniform(0.001,1, 1)
# Update likelihood with new value for a
prob_dispersal = dispersal_GND(distances, a=a_proposed, b=b_current, c=c_current)
lik_proposed = (g_matrix + prob_dispersal).sum() # lg likelihood of the proposed value
# Metropolis acceptance ration for a
accept = bool(np.random.binomial(1, np.min([1, np.exp(lik_proposed - lik_current)])))
if accept:
a_current = a_proposed
lik_current = lik_proposed
store_params[i,0] = a_current
# Update likelihood with new value for b
prob_dispersal = dispersal_GND(distances, a=a_current, b=b_proposed, c=c_current)
lik_proposed = (g_matrix + prob_dispersal).sum() # log likelihood of the proposed value
# Metropolis acceptance ratio for b
accept = bool(np.random.binomial(1, np.min([1, np.exp(lik_proposed - lik_current)])))
if accept:
b_current = b_proposed
lik_current = lik_proposed
store_params[i,1] = b_current
# Update likelihood with new value for c
prob_dispersal = dispersal_GND(distances, a=a_current, b=b_current, c=c_proposed)
lik_proposed = (g_matrix + prob_dispersal).sum() # lg likelihood of the proposed value
# Metropolis acceptance ratio for c
accept = bool(np.random.binomial(1, np.min([1, np.exp(lik_proposed - lik_current)])))
if accept:
c_current = c_proposed
lik_current = lik_proposed
store_params[i,2] = c_current