我似乎一直在遇到pymc3:
的问题在这里,我试图将幂律适用于某些数据。也就是说,我正试图将幂律拟合到一些由于测量不确定性而可能变为负值的数据。
基本上我对记录的数量(logy = mlogx + c)拟合直线,但也利用幂律也使用负值。 (y = x ** m * 10 ** c)。这一切都非常顺利,直到我在z上引入测量不确定性,此时变分优先转出,并且采样时可能性不会改变。看起来没有负面的zs似乎不合适似乎无关紧要!
这是一个完全可运行的例子:
*一点注意事项:我适合测量比而不是单次测量。所以有R = x / y
)。因此,拟合方程为R = 10**intercept * z**gradient
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
from theano.tensor.basic import log10
import pymc3 as pm
# fit_data = pd.read_csv('data.csv').set_index('id').head(10)
# equation to fit: log10(ratio) = log10(1+z)*m + c
# some data is negative (unphysical logs) so to tak advantage of all data: ratio = 10**c * (1+z)**m
equation = lambda z, m, c: (10**c) * ((1+z)**m)
N = 20
C, M = 1, 0
true_z = np.linspace(0, 1, N)
true_ratio = equation(true_z, M, C)
noisy_ratio = np.random.normal(true_ratio, 0.5)
noisy_x = np.random.normal(5, 0.1, N)
noisy_y = noisy_x / noisy_ratio
noisy_z = np.random.normal(true_z, 0.001)
xerr = np.ones(N) * 0.5
yerr = np.ones_like(xerr) * 0.05
zerr = np.ones_like(xerr) * 0.1
fit_data = pd.DataFrame({'x': noisy_x, 'y': noisy_y, 'z': noisy_z, 'xerr': xerr, 'yerr': yerr, 'zerr':zerr})
def plot_data():
ratio = fit_data.x / fit_data.y
ratio_err = ratio * np.sqrt((fit_data.xerr / fit_data.x)**2. + (fit_data.yerr / fit_data.y)**2.)
print 0.434 * fit_data.zerr / fit_data.z
plt.errorbar(np.log10(fit_data.z+1), np.log10(ratio), 0.434 * ratio_err/ratio, 0.434 * fit_data.zerr / (1+fit_data.z), fmt='.')
_z = np.linspace(plt.xlim()[0], plt.xlim()[1], 1000)
plt.plot(_z, np.log10(equation(_z, M, C)))
with pm.Model() as normal_thin_sloped:
intercept = pm.Normal('intercept', 1.5, sd=20)
gradient = pm.Normal('gradient', 0, sd=20)
A = 10**intercept
epsilon = pm.HalfCauchy('epsilon', 5)
_ratios = (fit_data.x / fit_data.y)
_ratio_errs = _ratios * np.sqrt((fit_data.xerr / fit_data.x)**2. + (fit_data.yerr / fit_data.y)**2.)#
R = pm.Normal('ratio', mu=_ratios.values, sd=_ratio_errs.values, shape=len(fit_data))
Z = pm.Normal('z', mu=fit_data.z.values, sd=fit_data.zerr.values, shape=len(fit_data))
likelihood = pm.Normal('likelihood', mu=A * ((1 + fit_data.z.values) ** gradient), sd=epsilon, observed=R) # this works really well!
# likelihood = pm.Normal('likelihood', mu=A * ((1 + Z) ** gradient), sd=epsilon, observed=R) # this fails really badly!
mu, sds, elbo = pm.variational.advi(n=20000)
step = pm.NUTS(scaling=normal_thin_sloped.dict_to_array(sds), is_cov=True)
trace = pm.sample(1000, step=step, start=mu, progressbar=True)
pm.traceplot(trace, varnames=['gradient', 'intercept', 'z'])
plt.figure()
plot_data()
_x = np.linspace(*plt.xlim())
plt.plot(_x, np.median(trace['intercept']) + (_x*np.median(trace['gradient'])))
plt.show()
由于