維基百科頁面給出表達式爲observed mean and variance,我們可以用它來反轉,找出什麼樣的價值觀,我們應該傳遞給truncnorm
給我們我們想要的結果。
我們不會利用基於標準正常工作的任何簡化,部分原因是一般原因,部分原因是我還沒有吃過早餐,所以我不想做任何算術。可能你可以用一個簡單的計算來代替整個最小化。
import numpy as np
import scipy.stats as stats
import scipy.optimize
def truncated_mean_std(mu, sigma, lower, upper):
# N.B. lower/upper are the actual values, not Z-scaled
alpha = (lower - mu)/sigma
beta = (upper - mu)/sigma
d_pdf = (stats.norm.pdf(alpha) - stats.norm.pdf(beta))
wd_pdf = (alpha * stats.norm.pdf(alpha) - beta * stats.norm.pdf(beta))
d_cdf = stats.norm.cdf(beta) - stats.norm.cdf(alpha)
mu_trunc = mu + sigma * (d_pdf/d_cdf)
var_trunc = sigma**2 * (1 + wd_pdf/d_cdf - (d_pdf/d_cdf)**2)
std_trunc = var_trunc**0.5
return mu_trunc, std_trunc
def trunc_samples(mu, sigma, lower, upper, num_samples=1000):
n = stats.truncnorm((lower - mu)/sigma, (upper - mu)/sigma, loc=mu, scale=sigma)
samples = n.rvs(num_samples)
return samples
def corrector(mu, sigma, lower, upper):
target = np.array([mu, sigma])
result = scipy.optimize.minimize(
lambda x: ((target - truncated_mean_std(x[0], x[1], lower, upper))**2).sum(),
x0=[mu, sigma])
return result.x
這給了我:
In [79]: s = trunc_samples(mu=0, sigma=1, lower=-2, upper=2, num_samples=10**7)
In [80]: s.mean(), s.std()
Out[80]: (-9.8821067931585576e-05, 0.87951241887015619)
In [81]: mu_to_use, sigma_to_use = corrector(0, 1, -2, 2)
In [82]: mu_to_use, sigma_to_use
Out[82]: (-7.4553057719882245e-09, 1.3778928137492246)
In [83]: s = trunc_samples(mu=mu_to_use, sigma=sigma_to_use, lower=-2, upper=2, num_samples=10**7)
In [84]: s.mean(), s.std()
Out[84]: (0.0004091647648333381, 0.99991490259048865)
In [85]: s.min(), s.max()
Out[85]: (-1.9999995310631815, 1.9999997070340947)
的偉大工程,但對一些價值觀的校正給出負面性病。例如對於以下輸入:0,0.08838834764831845,-0.1767766952966369,0.1767766952966369 – Bob
@Bob在我看來,'truncated_mean_std'返回類似於平均值和std-like的值,即分別與'mu'和'sigma'兼容的值。這意味着在'校正器'中調用'最小化'時,你實際上希望最小化'[mu,sigma]'而不是'[mu,sigma ** 2]'。如果你在'corrector'的第一行刪除'target'的定義,你就會開始獲得合理的std值。 –
糟糕,固定。你甚至可以在代碼中看到我在最後一秒從差異切換到stddev - 我沒有發現錯誤,因爲1^2 = 1。:-)另外,不要忘記你沒有那麼多你可能想要的自由 - 被截斷的stddev總是比原來的要小,並且因爲方差只是平均值離平均值有多遠的一個度量標準,所以當你截斷時,你對此作了限制。有超出你無法去的差異 - 你可以通過傳遞更大和更大的西格馬來truncnorm來看待極限。 – DSM