'For computing marginal effects returns dF(XB) / dX where F(.) is
the predicted probabilities
transform can be \'dydx\', \'dyex\', \'eydx\', or \'eyex\'.
Not all of these make sense in the presence of discrete regressors,
but checks are done in the results in get_margeff.
For Multinomial models the marginal effects are
P[j] * (params[j] - sum_k P[k]*params[k])
It is returned unshaped, so that each row contains each of the J
equations. This makes it easier to take derivatives of this for
standard errors. If you want average marginal effects you can do
margeff.reshape(nobs, K, J, order=\'F).mean(0) and the marginal effects
for choice J are in column J'

def _derivative_exog(self, params, exog=None, transform='dydx', dummy_idx=None, count_idx=None):

    J = int(self.J)
    K = int(self.K)
    if (exog is None):
        exog = self.exog
    if (params.ndim == 1):
        params = params.reshape(K, (J - 1), order='F')
    zeroparams = np.c_[(np.zeros(K), params)]
    cdf = self.cdf(np.dot(exog, params))
    margeff = np.array([(cdf[:, [j]] * (zeroparams[:, j] - np.array([(cdf[:, [i]] * zeroparams[:, i]) for i in range(int(J))]).sum(0))) for j in range(J)])
    margeff = np.transpose(margeff, (1, 2, 0))
    if ('ex' in transform):
        margeff *= exog
    if ('ey' in transform):
        margeff /= self.predict(params, exog)[:, None, :]
    if (count_idx is not None):
        from statsmodels.discrete.discrete_margins import _get_count_effects
        margeff = _get_count_effects(margeff, exog, count_idx, transform, self, params)
    if (dummy_idx is not None):
        from statsmodels.discrete.discrete_margins import _get_dummy_effects
        margeff = _get_dummy_effects(margeff, exog, dummy_idx, transform, self, params)
    return margeff.reshape(len(exog), (-1), order='F')
