我正在努力完成我在Python中的第一次最大似然估计。其中一个步骤要求我计算模型参数的可能性。我找到了一些可以在这里总结的样本数据:
import numpy as np
import pandas as pd
life_test = pd.DataFrame(columns=['points', 'time'])
life_test['points'] = np.linspace(1,14,14)
life_test['time'] = np.concatenate((np.linspace(5,40,8), np.linspace(50,100,6)), axis=0)
如果我通过statsmodels.api运行一个简单的模型。我从results.summary()获得了-14.601的值。
import statsmodels.api as sm
endog=np.array(life_test['points'])
exog=np.array(life_test['time'])
exog = sm.add_constant(exog)
results = sm.OLS(endog, exog).fit()
results.summary()
查看OLS的来源,似乎这是对数似然的基本计算
params = np.array(results.params)
nobs2=results.nobs/2.0 # decimal point is critical here!
-nobs2*np.log(2*np.pi)-nobs2*np.log(1.0/(2*nobs2) *\
np.dot(np.transpose(endog - np.dot(exog, params)),\
(endog - np.dot(exog,params)))) - nobs2
当我尝试用PyMC实现这个时,我会得到不同的结果。我可能会对loc和scale进行一些错误的计算。
import pymc.distributions as dist
mu = exog.mean()
sigma = exog.std()
dist.normal_like(exog, mu, 1/sigma**2)
这里我得到的值为-135.29。我觉得我必须错误地计算我的比例和loc值,但在我的实现中可能还有其他一些错误。也许OLS除了正常的对数似然之外还在使用其他一些可能性?我对statsmodels,PyMC和MLE都很陌生。有谁知道我在这里做错了什么?
答案 0 :(得分:3)
您可以使用以下内容将statsmodels
的结果与sklearn
进行比较:
>>> x=sklearn.linear_model.LinearRegression(fit_intercept=False).fit(exog,endog)
>>> x.coef_
array([ 1.45714286, 0.13428571])
与
相当>>> sm.OLS(endog, exog).fit().params
array([ 1.45714286, 0.13428571])
结果是一致的。另一方面,您似乎只计算了拟合gaussian
到exog
数据的可能性,这与linear-reqression
不同。
要使用linear regression
重新创建pymc
,您需要执行以下操作:
Gaussian
可能性因此pymc的实现是:
life_test = pd.DataFrame(columns=['points', 'time'])
life_test['points'] = np.linspace(1,14,14)
life_test['time'] = np.concatenate((np.linspace(5,40,8), np.linspace(50,100,6)), axis=0)
endog=np.array(life_test['points'])
exog=np.array(life_test['time'])
alpha = pm.Normal('alpha', mu=0, tau=2)
beta = pm.Normal('beta', mu=0, tau=2)
sigma = pm.Uniform('sigma', lower=0, upper=1)
y_est = alpha + beta * exog
radon_like = pm.Normal('y', mu=y_est, tau=sigma, observed=True,value=endog)
model = dict(rand_like=radon_like,alpha=alpha,beta=beta,sigma=sigma)
S = pm.MCMC(model)
S.sample(iter=100000,burn=1000)
pm.Matplot.plot(S)
如果您使用以下步骤计算对数似然,则可以使用pm.normal_like
分布获得结果:
>>> results = sm.OLS(endog, exog).fit()
>>> y_est = results.params[0] + results.params[1] * exog[:,1]
>>> pm.normal_like(endog, y_est, 1/np.sqrt(y_est.std()))
-19.348540432740464