앞선 포스팅에서 언급한 바이지만, 빈도론자는 주어진 데이터를 표상하는 고정된 모수(parameter)가 이미 존재한다고 생각합니다. 그러한 데이터를 발생시킬 가능성(likelihood)이 가장 높은 파라메터 값을 찾아낼 수 있는 방법론중의 하나가 바로 MLE(Maximum Likelihood Estimation; 최대가능도추정)입니다.
수식으로 표현하면 아래와 같이 먼저 likelihood function을 정의하고,
L(θ;x)
이를 최대화하는 파라메터 θ를 다음과 같이 추정하는 것입니다.
θ^=argθmaxL(θ;x)
TIP
실제로는 likelihood 보다 자연로그를 취한 log-likelihood를 많이 사용합니다.
ℓ(θ;x)=lnL(θ;x)
로그는 단조증가 함수이면서 곱셈을 덧셈으로 만들어 주는 성질을 가졌기 때문에 최적화 문제에서는 결론에 영향을 주지 않으면서도 계산의 부담을 덜어주기 때문입니다.
β를 maximum likelihood estimator를 이용해서 추정 할 수도 있습니다.
모델과 가정은 OLS estimator의 경우와 동일하게 출발합니다.
yi=xiβ+ϵi
y=Xβ+ϵ
ϵ∼N(0,σ2I)
Linear relationship between input and output
Full rank design matrix
Multivariate normal distribution of ϵ
Diagonal covariance matrix of ϵ
Equal diagonal entries of ϵ
단, 여기서는 N개의 샘플이 아래의 IID를 만족한다고 가정합니다. 왜냐하면 해당 가정이 있어야만 likelihood function을 product(∏)로 세울 수 있고, 여기에 log를 취해 sum(Σ)으로 바꾸어 계산할 수 있기 때문입니다.
Independent and Identically Distributed
이제 정규 확률 변수의 선형변환도 정규분포를 따른다는 성질에 따라 종속변수 yi 역시 평균 xiβ0, 분산 σ02의 조건부 정규분포를 따르게 되며, 해당 pdf는 아래의 식과 같이 표현할 수 있습니다.
위에서 정리한 내용을 파이썬 코드로 구현하면 아래와 같습니다. likelihood function의 경우엔 최대한 수식을 그대로 나타내려고 했습니다.
여담으로 Optimizer 부분을 보면 느끼시겠지만 실제로 scipy에는 다양한 최적화 알고리즘을 선택할 수 있습니다. 제 경우엔 BFGS(Broyden–Fletcher–Goldfarb–Shanno)를 사용해보았는데요, 이 부분을 구현하다가 우연히 제가 존경하는 다크프로그래머님의 최적화 기법의 직관적 이해라는 글을 읽게 되었는데, 다양한 최적화 기법들의 원리와 특징들을 저 같은 초심자를 위해 아주 잘 정리 해 주셨습니다.
import numpy as np
import statsmodels.api as sm
from scipy.optimize import minimize
from scipy.optimize import differential_evolution
df = sm.datasets.get_rdataset("Duncan","carData").data
y = df['prestige'].values.reshape(45,1)
X = df[['income','education']].values.reshape(45,2)
params0 =[1.,1.,1]
N =len(X)# Likelihood functiondefloglikelihood(params):
beta = np.array([params[0], params[1]]).reshape(2,1)
sigma_square = params[2]
error = y-np.matmul(X, beta)return-(-(N/2)*np.log(2*np.pi)-(N/2)*np.log(sigma_square)-(1/(2*sigma_square))*np.sum(error**2))# Optimizer
res = minimize(loglikelihood, params0, method='BFGS', options={'gtol':1e-4,'disp':True})# res = differential_evolution(loglikelihood, [(0, 1), (0, 1), (0, 1000)], tol=1e-4, mutation=(1e-4, 1e-1), disp=True, maxiter=1000)# Parametersprint(res.x)"""
[ 0.5482716 0.4957514 174.81864984]
"""# Analytical Beta & Sigma^2print(np.matmul(np.matmul(np.linalg.inv(np.matmul(X.T, X)), X.T), y))"""
[[0.54827173]
[0.49575132]]
"""print((1/N)*np.sum((y-np.matmul(X, np.array([res.x[0], res.x[1]]).reshape(2,1)))**2))"""
174.82031640531054
"""