コード例 #1
0
    def test_check_length_of_initial_values(self):
        """
        Ensure that a ValueError is raised when one passes an init_vals
        argument of the wrong length.
        """
        # Create a variable for the standard arguments to the MNL constructor.
        standard_args = [
            self.fake_df, self.alt_id_col, self.obs_id_col, self.choice_col,
            self.fake_specification
        ]

        # Create the mnl model object whose coefficients will be estimated.
        base_mnl = mnl.MNL(*standard_args)

        # Create the EstimationObj
        mapping_res = base_mnl.get_mappings_for_fit()
        ridge = None
        zero_vector = np.zeros(1)
        split_params = mnl.split_param_vec
        mnl_estimator = mnl.MNLEstimator(base_mnl, mapping_res, ridge,
                                         zero_vector, split_params)

        # Alias the function to be checked
        func = mnl_estimator.check_length_of_initial_values

        for i in [2, 3]:
            init_vals = np.ones(i)
            self.assertRaises(ValueError, func, init_vals)

        self.assertIsNone(func(np.ones(1)))

        return None
コード例 #2
0
    def test_ridge_warning_in_fit_mle(self):
        """
        Ensure that a UserWarning is raised when one passes the ridge keyword
        argument to the `fit_mle` method of an MNL model object.
        """
        # Create a variable for the standard arguments to the MNL constructor.
        standard_args = [
            self.fake_df, self.alt_id_col, self.obs_id_col, self.choice_col,
            self.fake_specification
        ]

        # Create the mnl model object whose coefficients will be estimated.
        base_mnl = mnl.MNL(*standard_args)

        # Create a variable for the fit_mle function's kwargs.
        # The print_res = False arguments are to make sure strings aren't
        # printed to the console unnecessarily.
        kwargs = {"ridge": 0.5, "print_res": False}

        # Test to make sure that the ridge warning message is printed when
        # using the ridge keyword argument
        with warnings.catch_warnings(record=True) as w:
            # Use this filter to always trigger the  UserWarnings
            warnings.simplefilter('always', UserWarning)

            base_mnl.fit_mle(self.fake_beta, **kwargs)
            self.assertGreaterEqual(len(w), 1)
            self.assertIsInstance(w[0].category, type(UserWarning))
            self.assertIn(mnl._ridge_warning_msg, str(w[0].message))

        return None
コード例 #3
0
    def test_outside_intercept_error_in_fit_mle(self):
        """
        Ensures that a ValueError is raised when users try to use any other
        type of initial value input methods other than the `init_vals`
        argument of `fit_mle()`. This prevents people from expecting the use
        of outside intercept or shape parameters to work with the MNL model.
        """
        # Create a variable for the standard arguments to the MNL constructor.
        standard_args = [
            self.fake_df, self.alt_id_col, self.obs_id_col, self.choice_col,
            self.fake_specification
        ]

        # Create the mnl model object whose coefficients will be estimated.
        base_mnl = mnl.MNL(*standard_args)

        # Create a variable for the arguments to the fit_mle function.
        fit_args = [self.fake_beta]

        # Create variables for the incorrect kwargs.
        # The print_res = False arguments are to make sure strings aren't
        # printed to the console unnecessarily.
        kwarg_map_1 = {"init_shapes": np.array([1, 2]), "print_res": False}
        kwarg_map_2 = {"init_intercepts": np.array([1]), "print_res": False}
        kwarg_map_3 = {"init_coefs": np.array([1]), "print_res": False}

        # Test to ensure that the kwarg ignore message is printed when using
        # any of these three incorrect kwargs
        for kwargs in [kwarg_map_1, kwarg_map_2, kwarg_map_3]:
            self.assertRaises(ValueError, base_mnl.fit_mle, *fit_args,
                              **kwargs)

        return None
コード例 #4
0
    def test_shape_ignore_msg_in_constructor(self):
        """
        Ensures that a UserWarning is raised when the 'shape_ref_pos' or
        'shape_names' keyword arguments are passed to the MNL model
        constructor. This warns people against expecting the MNL to work with
        shape parameters, and alerts them to the fact they are using an MNL
        model when they might have been expecting to instantiate a different
        choice model.
        """
        # Create a variable for the standard arguments to this function.
        standard_args = [
            self.fake_df, self.alt_id_col, self.obs_id_col, self.choice_col,
            self.fake_specification
        ]

        # Create a variable for the kwargs being passed to the constructor
        kwarg_map_1 = {"shape_ref_pos": 2}
        kwarg_map_2 = {"shape_names": OrderedDict([("x", ["foo"])])}

        # Test to ensure that the shape ignore message is printed when using
        # either of these two kwargs
        with warnings.catch_warnings(record=True) as context:
            # Use this filter to always trigger the  UserWarnings
            warnings.simplefilter('always', UserWarning)

            for pos, bad_kwargs in enumerate([kwarg_map_1, kwarg_map_2]):
                # Create an MNL model object with the irrelevant kwargs.
                # This should trigger a UserWarning
                mnl_obj = mnl.MNL(*standard_args, **bad_kwargs)
                # Check that the warning has been created.
                self.assertEqual(len(context), pos + 1)
                self.assertIsInstance(context[-1].category, type(UserWarning))
                self.assertIn(mnl._shape_ignore_msg, str(context[-1].message))

        return None
コード例 #5
0
    def test_just_point_kwarg(self):
        # Create a variable for the standard arguments to the MNL constructor.
        standard_args = [
            self.fake_df, self.alt_id_col, self.obs_id_col, self.choice_col,
            self.fake_specification
        ]

        # Create the mnl model object whose coefficients will be estimated.
        base_mnl = mnl.MNL(*standard_args)
        # Alias the function being tested
        func = base_mnl.fit_mle
        # Get the necessary kwargs
        kwargs = {"just_point": True}
        # Get the function results
        func_result = func(self.fake_beta, **kwargs)
        # Perform the desired tests to make sure we get back a dictionary with
        # an "x" key in it and a value that is a ndarray.
        self.assertIsInstance(func_result, dict)
        self.assertIn("x", func_result)
        self.assertIsInstance(func_result["x"], np.ndarray)
        return None
コード例 #6
0
    def make_clog_and_mnl_models(self):
        # The set up being used is one where there are two choice situations,
        # The first having three alternatives, and the second having only two
        # alternatives. There is one generic variable. Two alternative
        # specific constants and all three shape parameters are used.

        # Create the betas to be used during the tests
        fake_betas = np.array([-0.6])

        # Create the fake outside intercepts to be used during the tests
        fake_intercepts = np.array([1, 0.5])

        # Create names for the intercept parameters
        fake_intercept_names = ["ASC 1", "ASC 2"]

        # Record the position of the intercept that is not being estimated
        fake_intercept_ref_pos = 2

        # Create an array of all model parameters
        fake_all_params = np.concatenate((fake_intercepts, fake_betas))

        # Get the mappping between rows and observations
        fake_rows_to_obs = csr_matrix(
            np.array([[1, 0], [1, 0], [1, 0], [0, 1], [0, 1]]))

        # Create the fake design matrix with columns denoting X
        # The intercepts are not included because they are kept outside the
        # index in the scobit model.
        fake_design = np.array([[1], [2], [3], [1.5], [3.5]])

        # Create the index array for this set of choice situations
        fake_index = fake_design.dot(fake_betas)

        # Create the needed dataframe for the model constructor
        fake_df = pd.DataFrame({
            "obs_id": [1, 1, 1, 2, 2],
            "alt_id": [1, 2, 3, 1, 3],
            "choice": [0, 1, 0, 0, 1],
            "x": fake_design[:, 0],
            "intercept": [1 for i in range(5)]
        })

        # Record the various column names
        alt_id_col = "alt_id"
        obs_id_col = "obs_id"
        choice_col = "choice"

        # Create the index specification  and name dictionaryfor the model
        fake_specification = OrderedDict()
        fake_names = OrderedDict()
        fake_specification["x"] = [[1, 2, 3]]
        fake_names["x"] = ["x (generic coefficient)"]

        mnl_spec = OrderedDict()
        mnl_names = OrderedDict()
        mnl_spec["intercept"] = [1, 2]
        mnl_names["intercept"] = fake_intercept_names
        mnl_spec["x"] = fake_specification["x"]
        mnl_names["x"] = fake_names["x"]

        # Bundle args and kwargs used to construct the Asymmetric Logit model.
        clog_args = [
            fake_df, alt_id_col, obs_id_col, choice_col, fake_specification
        ]
        mnl_args = deepcopy(clog_args)
        mnl_args[-1] = mnl_spec

        # Create a variable for the kwargs being passed to the constructor
        clog_kwargs = {
            "names": fake_names,
            "intercept_ref_pos": fake_intercept_ref_pos,
            "intercept_names": fake_intercept_names
        }
        mnl_kwargs = {"names": mnl_names}

        # Initialize a basic Asymmetric Logit model whose coefficients will be
        # estimated.
        clog_obj = clog.MNCL(*clog_args, **clog_kwargs)
        mnl_obj = mnl.MNL(*mnl_args, **mnl_kwargs)

        # Create the desired model attributes for the clog log model
        clog_obj.coefs = pd.Series(fake_betas, index=fake_names["x"])
        clog_obj.intercepts =\
            pd.Series(fake_intercepts, index=fake_intercept_names)
        clog_obj.shapes = None
        clog_obj.nests = None
        clog_obj.params =\
            pd.concat([clog_obj.intercepts, clog_obj.coefs],
                      axis=0, ignore_index=False)

        mnl_obj.params = clog_obj.params.copy()
        mnl_obj.coefs = mnl_obj.params.copy()
        mnl_obj.intercepts = None
        mnl_obj.shapes = None
        mnl_obj.nests = None

        return clog_obj, mnl_obj