def _credit_clusters():
     return distributions.Mixture(
         components=[
             _single_credit_cluster(idx) for idx in range(feature_dim)
         ],
         weights=cluster_probs,
     )
def two_group_credit_clusters(
        group_likelihoods=(0.5, 0.5),
        cluster_probabilities=DELAYED_IMPACT_CLUSTER_PROBS,
        success_probabilities=DELAYED_IMPACT_SUCCESS_PROBS):
    """Returns a mixture of two credit cluster distributions.

  Args:
    group_likelihoods: Probabilities of choosing from each group.
      Should be non-negative and sum to one.
    cluster_probabilities: cluster_probabilities[i][j] gives the probability of
      being drawn from credit cluster j conditioned on being from group i.
    success_probabilities: success_probabilities[j] gives the probability of
      successfully paying back a loan conditioned on being from being from
      credit cluster j.
  """
    components = []
    for idx in [0, 1]:
        # Use a one-hot encoding of group-id.
        group_vec = np.zeros(2)
        group_vec[idx] = 1
        components.append(
            _credit_cluster_builder(
                group_membership=tuple(group_vec),
                cluster_probs=tuple(cluster_probabilities[idx]),
                success_probs=tuple(success_probabilities))())
    return distributions.Mixture(components=components,
                                 weights=group_likelihoods)
Beispiel #3
0
 def test_mixture_returns_components(self):
     my_distribution = distributions.Mixture(components=[
         distributions.Constant((0, )),
         distributions.Constant((1, ))
     ],
                                             weights=[0.1, 0.9])
     rng = np.random.RandomState(seed=100)
     samples = [my_distribution.sample(rng) for _ in range(1000)]
     self.assertSetEqual(set(samples), {(0, ), (1, )})
     self.assertAlmostEqual(np.mean(samples), 0.9, delta=0.1)
Beispiel #4
0
    def test_improper_distributions_raise_errors(self):
        for p in [-10, -0.9, 1.3]:
            with self.assertRaises(ValueError):
                _ = distributions.Bernoulli(p=p)

        for vec in [
            [0.1, 0.3, 0.5],  # Does not sum to one.
            [0.5, 0.9, -0.4],  # Has negative values.
        ]:
            with self.assertRaises(ValueError):
                _ = distributions.Mixture(
                    weights=vec,
                    components=[distributions.Constant(mean=(0, ))] * len(vec))
 def _single_gmm():
   """Returns a mixture of gaussian applicant distributions."""
   return distributions.Mixture(
       components=[
           ApplicantDistribution(
               features=distributions.Gaussian(mean=mean, std=0.5),
               group_membership=distributions.Constant(group),
               will_default=distributions.Bernoulli(p=default_likelihoods[0])),
           ApplicantDistribution(
               features=distributions.Gaussian(
                   mean=np.array(mean) + np.array(intercluster_vec), std=0.5),
               group_membership=distributions.Constant(group),
               will_default=distributions.Bernoulli(p=default_likelihoods[1]))
       ],
       weights=[0.3, 0.7])
    def _rotated_gmm():
        """Returns a mixture of applicant distributions.

    The second applicant distribution is a rotated version of the first.
    """
        return distributions.Mixture(components=[
            _gmm_applicant_builder(mean=mean,
                                   intercluster_vec=intercluster_vec,
                                   default_likelihoods=default_likelihoods,
                                   group=[1, 0])(),
            _gmm_applicant_builder(mean=_rotate(mean, degrees),
                                   intercluster_vec=_rotate(
                                       intercluster_vec, degrees),
                                   default_likelihoods=default_likelihoods,
                                   group=[0, 1])(),
        ],
                                     weights=group_likelihoods)
Beispiel #7
0
    def test_measure_distribution_change_measurement(self):

        # The lower cluster has a 100% success rate and the upper cluster has a 0%
        # success rate. This causes applicants to move constantly between clusters.
        clusters = distributions.Mixture(
            components=[
                lending_params._credit_cluster_builder(
                    group_membership=[1, 0],
                    cluster_probs=[0.1, 0.9],
                    success_probs=[1.0, 0.0])(),
                lending_params._credit_cluster_builder(
                    group_membership=[0, 1],
                    cluster_probs=[0.8, 0.2],
                    success_probs=[1.0, 0.0])(),
            ],
            weights=(0.5, 0.5),
        )

        env = lending.DelayedImpactEnv(
            lending_params.DelayedImpactParams(
                applicant_distribution=clusters))
        initial_distribution = lending_metrics.CreditDistribution(env, 0)
        final_distribution = lending_metrics.CreditDistribution(env, -1)

        # Giving a loan should change the distribution.
        env.step(np.asarray(1))
        # Take another step to move current state into history. This step does not
        # change the distribution because the loan is rejected.
        env.step(np.asarray(0))

        self.assertEqual({
            "0": [0.1, 0.9],
            "1": [0.8, 0.2]
        }, initial_distribution.measure(env))
        self.assertNotEqual({
            "0": [0.1, 0.9],
            "1": [0.8, 0.2]
        }, final_distribution.measure(env))