Saya memodelkan penyebaran tanaman menggunakan distribusi normal umum ( entri wikipedia ), yang memiliki fungsi kerapatan probabilitas:
di mana adalah jarak yang ditempuh, adalah parameter skala, dan adalah parameter bentuk. Berarti jarak yang ditempuh diberikan oleh standar deviasi dari distribusi ini:
Ini nyaman karena memungkinkan untuk bentuk eksponensial ketika , bentuk Gaussian ketika , dan untuk distribusi leptokurtik ketika . Distribusi ini muncul secara teratur dalam literatur penyebaran tanaman, meskipun secara umum jarang, dan karenanya sulit untuk menemukan informasi.
Parameter yang paling menarik adalah dan jarak penyebaran rata-rata.
Saya mencoba memperkirakan dan menggunakan MCMC, tetapi saya berjuang untuk menemukan cara yang efisien untuk sampel nilai proposal. Sejauh ini, saya telah menggunakan Metropolis-Hastings, dan diambil dari distribusi seragam dan , dan saya mendapatkan jarak penyebaran rata-rata posterior sekitar 200-400 meter, yang memang masuk akal secara biologis. Namun, konvergensi sangat lambat, dan saya tidak yakin sedang mengeksplorasi ruang parameter penuh.
Sulit untuk menghasilkan distribusi proposal yang lebih baik untuk dan , karena mereka bergantung satu sama lain, tanpa memiliki banyak makna sendiri. Jarak dispersal rata-rata memang memiliki arti biologis yang jelas, tetapi jarak dispersal rata-rata yang diberikan dapat dijelaskan oleh banyak kombinasi dan . Dengan demikian dan berkorelasi di posterior.
Sejauh ini saya telah menggunakan Metropolis Hastings, tetapi saya terbuka untuk algoritma lain yang akan bekerja di sini.
Pertanyaan: Adakah yang bisa menyarankan cara yang lebih efisien untuk menggambar nilai proposal untuk dan ?
Sunting: Informasi tambahan tentang sistem: Saya sedang mempelajari populasi tanaman di sepanjang lembah. Tujuannya adalah untuk menentukan distribusi jarak yang ditempuh antara serbuk sari antara tanaman donor dan tanaman yang diserbuki. Data yang saya miliki adalah:
- Lokasi dan DNA untuk setiap donor serbuk sari
- Benih dikumpulkan dari sampel 60 tanaman ibu (yaitu penerima serbuk sari) yang telah tumbuh dan genotipe.
- Lokasi dan DNA untuk setiap tanaman ibu.
Saya tidak tahu identitas tanaman donor, tetapi ini dapat disimpulkan dari data genetik dengan menentukan donor mana yang merupakan ayah dari setiap bibit. Katakanlah informasi ini terkandung dalam matriks probabilitas G dengan baris untuk setiap keturunan dan kolom untuk setiap kandidat donor, yang memberikan probabilitas setiap kandidat menjadi bapak dari masing-masing keturunan berdasarkan data genetik saja. G membutuhkan waktu sekitar 3 detik untuk menghitung, dan perlu dihitung ulang di setiap iterasi, yang memperlambat banyak hal.
Karena kami umumnya mengharapkan calon donor yang lebih dekat lebih cenderung menjadi ayah, kesimpulan ayah lebih akurat jika Anda bersama-sama menyimpulkan ayah dan penyebaran. Matriks D memiliki dimensi yang sama dengan G , dan berisi probabilitas ayah berdasarkan hanya fungsi jarak antara ibu dan kandidat dan beberapa vektor parameter. Mengalikan elemen dalam D dan G memberikan probabilitas gabungan ayah yang diberikan data genetik dan spasial. Produk dari nilai yang dikalikan memberikan kemungkinan model penyebaran.
Seperti dijelaskan di atas, saya telah menggunakan GND untuk memodelkan penyebaran. Sebenarnya saya benar-benar menggunakan campuran GND dan distribusi seragam untuk memungkinkan kemungkinan calon yang sangat jauh memiliki kemungkinan ayah yang lebih tinggi karena kebetulan saja (genetika berantakan) yang akan menggembungkan ekor nyata GND jika diabaikan. Jadi probabilitas jarak dispersal adalah:
di mana adalah probabilitas jarak penyebaran dari GND, N adalah jumlah kandidat, dan ( ) menentukan berapa banyak kontribusi yang dibuat oleh GND terhadap penyebaran.
Oleh karena itu ada dua pertimbangan tambahan yang meningkatkan beban komputasi:
- Jarak dispersi tidak diketahui tetapi harus disimpulkan pada setiap iterasi, dan membuat G untuk melakukan ini mahal.
- Ada parameter ketiga, , untuk diintegrasikan.
Untuk alasan ini, bagi saya agak terlalu rumit untuk melakukan interpolasi grid, tetapi saya senang diyakinkan sebaliknya.
Contoh
Ini adalah contoh sederhana dari kode python yang saya gunakan. Saya telah menyederhanakan estimasi ayah dari data genetik, karena ini akan melibatkan banyak kode tambahan, dan menggantinya dengan matriks nilai antara 0 dan 1.
Pertama, tentukan fungsi untuk menghitung 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
Selanjutnya, simulasikan 2000 kandidat, dan 800 keturunan. Juga mensimulasikan daftar jarak antara ibu dari keturunan dan calon ayah, dan matriks G dummy .
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]
Tetapkan nilai parameter awal:
# 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
Perbarui a, b, dan c pada gilirannya, dan hitung rasio Metropolis.
# 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