MLE for Multinomial Distribution
a.values/a.values.sum() # point estimates for p = x/n
# array([[0. ], [0.02941176], [0.05882353], [0.08823529],
# [0.05882353], [0.02941176], [0.17647059], [0. ],
# [0.02941176], [0.02941176], [0.20588235], [0.29411765]])
scipy.optimize.minimize
import pandas as pd
import numpy as np
import scipy.optimize as sciopt
# bounds for parameters to lie between (0,1),
# absolute zero (0) for lower bound avoided as log takes an infinite value
bnds = [(0.001e-12,1) for i in range(12)]
# Initializing parameters value for optimization
init_parameters = np.asarray([0.1 for i in range(12)])
# Negative Log Likelihood Function
neg_log_lik = lambda p: -np.sum([a.values[i]*np.log(p[i]) for i in range(12)])
# Constraint sum(p) = 1
cons = {'type': 'eq', 'fun': lambda p: (sum([p[i] for i in range(12)]) - 1) }
# Minimizing neg_log_lik
results = sciopt.minimize(neg_log_lik, x0 = init_parameters,
method='SLSQP', bounds= bnds, constraints= cons)
results.x # point estimates for p
# array([1.00000000e-15, 2.94179308e-02, 5.88243586e-02, 8.82394605e-02,
# 5.88243586e-02, 2.94059735e-02, 1.76454713e-01, 1.00000000e-15,
# 2.94134577e-02, 2.94135714e-02, 2.05849197e-01, 2.94156978e-01])
scipy.optimize.minimize