예제 #1
0
def test_log_likelihood():
    """
    Computes the log-likelihood "by hand" for a simple example and ensures
    that the one returned by xlogit is the same
    """
    P = 1  # Without panel data
    betas = np.array([.1, .1, .1, .1])
    X_, y_ = X.reshape(N, P, J, K), y.reshape(N, P, J, 1)

    # Compute log likelihood using xlogit
    model = MixedLogit()
    model._rvidx, model._rvdist = np.array([True, True]), np.array(['n', 'n'])
    draws = model._get_halton_draws(N, R, K)  # (N,Kr,R)
    panel_info = np.ones((N, P))
    obtained_loglik, _ = model._loglik_gradient(betas, X_, y_, panel_info,
                                                draws, None, None)

    # Compute expected log likelihood "by hand"
    Br = betas[None, [0, 1], None] + draws * betas[None, [2, 3], None]
    eXB = np.exp(np.einsum('npjk,nkr -> npjr', X_, Br))
    p = eXB / np.sum(eXB, axis=2, keepdims=True)
    expected_loglik = -np.sum(
        np.log((y_ * p).sum(axis=2).prod(axis=1).mean(axis=1)))

    assert pytest.approx(expected_loglik, obtained_loglik)
예제 #2
0
def test_log_likelihood():
    """
    Computes the log-likelihood "by hand" for a simple example and ensures
    that the one returned by xlogit is the same
    """
    betas = np.array([.1, .1, .1, .1])
    X_, y_ = X.reshape(N, J, K), y.reshape(N, J, 1)

    # Compute log likelihood using xlogit
    model = MixedLogit()
    model._rvidx, model._rvdist = np.array([True, True]), np.array(['n', 'n'])
    draws = model._generate_halton_draws(N, R, K)  # (N,Kr,R)
    obtained_loglik = model._loglik_gradient(betas,
                                             X_,
                                             y_,
                                             None,
                                             draws,
                                             None,
                                             None, {
                                                 'samples': N,
                                                 'draws': R
                                             },
                                             return_gradient=False)

    # Compute expected log likelihood "by hand"
    Br = betas[None, [0, 1], None] + draws * betas[None, [2, 3], None]
    eXB = np.exp(np.einsum('njk,nkr -> njr', X_, Br))
    p = eXB / np.sum(eXB, axis=1, keepdims=True)
    expected_loglik = -np.sum(np.log((y_ * p).sum(axis=1).mean(axis=1)))

    assert expected_loglik == pytest.approx(obtained_loglik)
예제 #3
0
def test__transform_betas():
    """
    Check that betas are properly transformed to random draws

    """
    betas = np.array([.1, .1, .1, .1])

    # Compute log likelihood using xlogit
    model = MixedLogit()
    model._rvidx, model._rvdist = np.array([True, True]), np.array(['n', 'n'])
    draws = model._get_halton_draws(N, R, K)  # (N,Kr,R)
    expected_betas = betas[None, [0, 1], None] + \
        draws*betas[None, [2, 3], None]
    _, obtained_betas = model._transform_betas(betas, draws)

    assert np.allclose(expected_betas, obtained_betas)
예제 #4
0
def test_predict():
    """
    Ensures that returned choice probabilities are consistent.
    """
    # There is no need to initialize a random seed as the halton draws produce
    # reproducible results
    P = 1  # Without panel data
    betas = np.array([.1, .1, .1, .1])
    X_ = X.reshape(N, P, J, K)

    model = MixedLogit()
    model._rvidx, model._rvdist = np.array([True, True]), np.array(['n', 'n'])
    model.alternatives = np.array([1, 2])
    model.coeff_ = betas
    model.randvars = randvars
    model._isvars, model._asvars, model._varnames = [], varnames, varnames
    model._fit_intercept = False
    model.coeff_names = np.array(["a", "b", "sd.a", "sd.b"])

    #model.fit(X, y, varnames, alts, ids, randvars, verbose=0, halton=True)
    y_pred, proba, freq = model.predict(X,
                                        varnames,
                                        alts,
                                        ids,
                                        n_draws=R,
                                        return_proba=True,
                                        return_freq=True)

    # Compute choice probabilities by hand
    draws = model._get_halton_draws(N, R, K)  # (N,Kr,R)
    Br = betas[None, [0, 1], None] + draws * betas[None, [2, 3], None]
    V = np.einsum('npjk,nkr -> npjr', X_, Br)
    V[V > 700] = 700
    eV = np.exp(V)
    e_proba = eV / np.sum(eV, axis=2, keepdims=True)
    expec_proba = e_proba.prod(axis=1).mean(axis=-1)
    expec_ypred = model.alternatives[np.argmax(expec_proba, axis=1)]
    alt_list, counts = np.unique(expec_ypred, return_counts=True)
    expec_freq = dict(
        zip(list(alt_list), list(np.round(counts / np.sum(counts), 3))))

    assert np.array_equal(expec_ypred, y_pred)
    assert expec_freq == freq