def test_summary(): """ Ensures that calls to summary when the model has not been fit warns the user """ model = MultinomialLogit() with pytest.warns(UserWarning): model.summary()
def test__bfgs_optimization(): """ Ensure that the bfgs optimization properly processes the input for one iteration. The value of 0.276999 was computed by hand for comparison purposes """ X_, y_ = X.reshape(N, J, K), y.reshape(N, J) betas = np.array([.1, .1]) model = MultinomialLogit() res = model._bfgs_optimization(betas, X_, y_, None, None, 0, 1e-5) assert res['fun'] == approx(0.276999)
def test_predict(): """ Computes predictions "by hand" for a simple example and ensures that the probabilities returned by xlogit are the same """ X_ = X.reshape(N, J, K) betas = np.array([.1, .1]) #=== 1. Compute predictions using xlogit model = MultinomialLogit() model.alternatives = np.array([1, 2]) model.coeff_ = betas model._isvars, model._asvars, model._varnames = [], varnames, varnames model._fit_intercept = False model.coeff_names = np.array(["a", "b", "sd.a", "sd.b"]) ypred, proba, freq = model.predict(X, varnames, alts, ids, return_proba=True, return_freq=True) #=== 2. Compute predictions by hand eXB = np.exp(X_.dot(betas)) expec_proba = eXB / np.sum(eXB, axis=1, keepdims=True) 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)))) #=== 3. Assert predictions are the same assert np.allclose(expec_proba, proba) assert np.array_equal(expec_ypred, ypred) assert expec_freq == freq
def test__setup_design_matrix(): """ Ensures that xlogit properly adds an intercept when necessary """ model = MultinomialLogit() model._pre_fit(alts, varnames, isvars=None, base_alt=None, fit_intercept=True, maxiter=0) X_, Xnames_ = model._setup_design_matrix(X) assert X_.shape == (3, 2, 3) assert list(Xnames_) == ["_intercept.2", "a", "b"]
def test_fit(): """ Ensures the log-likelihood works for a single iterations with the default initial coefficients. The value of 0.4044 was computed by hand for comparison purposes """ model = MultinomialLogit() model.fit(X, y, varnames=varnames, alts=alts, ids=ids, maxiter=0, verbose=0) assert model.loglikelihood == approx(-0.40443136)
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 """ X_, y_ = X.reshape(N, J, K), y.reshape(N, J) betas = np.array([.1, .1]) # Compute log likelihood using xlogit model = MultinomialLogit() obtained_loglik = model._loglik_gradient(betas, X_, y_, None, None) # Compute expected log likelihood "by hand" eXB = np.exp(X_.dot(betas)) expected_loglik = -np.sum( np.log(np.sum(eXB / np.sum(eXB, axis=1, keepdims=True) * y_, axis=1))) assert obtained_loglik == approx(expected_loglik)
def test__format_choice_var(): """ Ensures that the variable y is properly formatted as needed by internal procedures regardless of the input data type. """ model = MultinomialLogit() expected = np.array([1, 0, 0, 1, 1, 0]) y1 = np.array([1, 1, 2, 2, 1, 1]) assert np.array_equal(model._format_choice_var(y1, alts), expected) y2 = np.array(['a', 'a', 'b', 'b', 'a', 'a']) alts2 = np.array([ 'a', 'b', 'a', 'b', 'a', 'b', ]) assert np.array_equal(model._format_choice_var(y2, alts2), expected)
def test__validate_inputs(): """ Covers potential mistakes in parameters of the fit method that xlogit should be able to identify """ model = MultinomialLogit() validate = model._validate_inputs with pytest.raises(ValueError): # match between columns in X and varnames validate(X, y, alts, varnames=["a"], isvars=None, ids=ids, weights=None) with pytest.raises(ValueError): # alts can't be None validate(X, y, None, varnames=varnames, isvars=None, ids=ids, weights=None) with pytest.raises(ValueError): # varnames can't be None validate(X, y, alts, varnames=None, isvars=None, ids=ids, weights=None) with pytest.raises(ValueError): # X dimensions validate(np.array([]), y, alts, varnames=None, isvars=None, ids=ids, weights=None) with pytest.raises(ValueError): # y dimensions validate(X, np.array([]), alts, varnames=None, isvars=None, ids=ids, weights=None)