Tôi đang lập mô hình phân tán thực vật bằng cách sử dụng phân phối chuẩn tổng quát ( mục nhập wikipedia ), có hàm mật độ xác suất:
Trong đó là quãng đường đi được, là tham số tỷ lệ và là tham số hình dạng. Khoảng cách trung bình đi được cho bởi độ lệch chuẩn của phân phối này:
Điều này thuận tiện vì nó cho phép hình dạng hàm mũ khi , hình dạng Gaussian khi và cho phân phối leptokurtic khi . Phân phối này mọc lên thường xuyên trong tài liệu phân tán thực vật, mặc dù nói chung nó khá hiếm, và do đó rất khó tìm thấy thông tin.
Các tham số thú vị nhất là và khoảng cách phân tán trung bình.
Tôi đang cố gắng ước tính và bằng MCMC, nhưng tôi đang cố gắng đưa ra một cách hiệu quả để lấy mẫu các giá trị đề xuất. Cho đến nay, tôi đã sử dụng Metropolis-Hastings và rút ra từ các bản phân phối thống nhất và , và tôi nhận được khoảng cách phân tán trung bình sau khoảng 200-400 mét, điều này có ý nghĩa sinh học. Tuy nhiên, sự hội tụ thực sự rất chậm và tôi không tin nó đang khám phá không gian tham số đầy đủ.
Thật khó khăn để đưa ra một phân phối đề xuất tốt hơn cho và , bởi vì chúng phụ thuộc vào nhau, mà không có nhiều ý nghĩa riêng. Khoảng cách phân tán trung bình có ý nghĩa sinh học rõ ràng, nhưng khoảng cách phân tán trung bình nhất định có thể được giải thích bằng vô số kết hợp của và . Như vậy và có tương quan ở phía sau.
Cho đến nay tôi đã sử dụng Metropolis Hastings, nhưng tôi mở cho bất kỳ thuật toán nào khác sẽ hoạt động ở đây.
Câu hỏi: Bất cứ ai cũng có thể đề xuất một cách hiệu quả hơn để vẽ các giá trị đề xuất cho và ?
Chỉnh sửa: Thông tin bổ sung về hệ thống: Tôi đang nghiên cứu một quần thể thực vật dọc theo thung lũng. Mục đích là để xác định sự phân bố khoảng cách di chuyển giữa phấn hoa giữa các nhà tài trợ và các nhà máy mà họ thụ phấn. Dữ liệu tôi có là:
- Vị trí và DNA cho mọi nhà tài trợ phấn hoa có thể
- Hạt giống được thu thập từ một mẫu của 60 cây mẹ (tức là máy thu phấn hoa) đã được trồng và có kiểu gen.
- Vị trí và DNA cho từng cây mẹ.
Tôi không biết danh tính của các nhà tài trợ, nhưng điều này có thể được suy ra từ dữ liệu di truyền bằng cách xác định nhà tài trợ nào là cha đẻ của mỗi cây con. Giả sử thông tin này được chứa trong một ma trận xác suất G với một hàng cho mỗi đứa con và một cột cho mỗi người hiến tặng, điều đó đưa ra xác suất mỗi ứng cử viên là cha của mỗi đứa con chỉ dựa trên dữ liệu di truyền. G mất khoảng 3 giây để tính toán và cần phải tính toán lại ở mỗi lần lặp, điều này làm mọi thứ chậm lại đáng kể.
Vì chúng tôi thường mong đợi các nhà tài trợ ứng cử viên gần gũi hơn có nhiều khả năng là cha, nên suy luận về quan hệ cha con sẽ chính xác hơn nếu bạn cùng suy luận về quan hệ cha con và phân tán. Ma trận D có cùng kích thước với G và chứa xác suất làm cha chỉ dựa trên hàm khoảng cách giữa mẹ và ứng cử viên và một số vectơ tham số. Các yếu tố nhân trong D và G đưa ra xác suất chung về quan hệ cha con với dữ liệu di truyền và không gian. Sản phẩm của các giá trị nhân cho khả năng mô hình phân tán.
Như đã mô tả ở trên, tôi đã sử dụng GND để phân tán mô hình. Trong thực tế, tôi thực sự đã sử dụng hỗn hợp GND và phân phối đồng đều để cho phép các ứng cử viên ở rất xa có khả năng làm cha cao hơn do chỉ có cơ hội (di truyền lộn xộn) sẽ làm phồng cái đuôi rõ ràng của GND nếu bị bỏ qua. Vậy xác suất của khoảng cách phân tán là:
Trong đó là xác suất khoảng cách phân tán từ GND, N là số lượng ứng cử viên và ( ) xác định mức độ đóng góp của GND cho phân tán.
Do đó, có hai cân nhắc bổ sung làm tăng gánh nặng tính toán:
- Khoảng cách phân tán không được biết nhưng phải được suy ra ở mỗi lần lặp và tạo G để thực hiện việc này rất tốn kém.
- Có một tham số thứ ba, , để tích hợp hơn.
Vì những lý do này, dường như tôi đã quá phức tạp để thực hiện phép nội suy lưới, nhưng tôi rất vui khi được thuyết phục bằng cách khác.
Thí dụ
Dưới đây là một ví dụ đơn giản về mã python tôi đã sử dụng. Tôi đã đơn giản hóa ước tính quan hệ cha con từ dữ liệu di truyền, vì điều này sẽ liên quan đến rất nhiều mã bổ sung và thay thế nó bằng một ma trận các giá trị từ 0 đến 1.
Đầu tiên, xác định các hàm để tính 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
Tiếp theo mô phỏng 2000 ứng cử viên, và 800 con. Cũng mô phỏng một danh sách khoảng cách giữa mẹ của con cái và cha ứng cử viên, và một ma trận G giả .
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]
Đặt giá trị tham số ban đầu:
# 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
Cập nhật lần lượt a, b và c và tính tỷ lệ đô thị.
# 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