Source code for causeinfer.standard_algorithms.binary_transformation

"""
Binary Class Transformation
---------------------------

The Binary Class Transformation Approach (Influential Marketing, Response Transformation Approach).

Based on
    Kuchumov, A. pyuplift: Lightweight uplift modeling framework for Python. (2019).
    URL: https://github.com/duketemon/pyuplift.
    License: https://github.com/duketemon/pyuplift/blob/master/LICENSE.

    Lai, L.Y.-T. (2006). “Influential marketing: A new direct marketing strategy addressing
    the existence of voluntary buyers”. Master of Science thesis, Simon Fraser University School
    of Computing Science, Burnaby, BC,Canada. URL: https://summit.sfu.ca/item/6629

    Shaar, A., Abdessalem, T., and Segard, O. (2016). “Pessimistic Uplift Modeling”. ACM SIGKDD, August 2016,
    San Francisco, California USA, arXiv:1603.09738v1.
    URL:https://pdfs.semanticscholar.org/a67e/401715014c7a9d6a6679df70175be01daf7c.pdf.

    Devriendt, F. et al. (2018). A Literature Survey and Experimental Evaluation of the   State-of-the-Art in Uplift
    Modeling: A Stepping Stone Toward the Development of Prescriptive Analytics. Big Data, Vol. 6, No. 1,   March 1,
    2018, pp. 1-29. Codes found at: data-lab.be/downloads.php.

Contents
    BinaryTransformation Class
        _binary_transformation,
        _binary_regularization,
        fit,
        predict (Not available at this time),
        predict_proba
"""

import numpy as np
from causeinfer.standard_algorithms.base_models import TransformationModel


[docs]class BinaryTransformation(TransformationModel): def __init__(self, model=None, regularize=False): """ Checks the attributes of the control and treatment models before assignment. """ try: model.__getattribute__("fit") model.__getattribute__("predict") except AttributeError: raise AttributeError( "The passed model should contain both fit and predict methods." ) self.model = model self.regularize = regularize
[docs] def _binary_transformation(self, y, w): """ Derives which of the unknown Affected Positive or Affected Negative classes the unit could fall into based known outcomes. Parameters ---------- y : numpy.ndarray : (num_units,) : int, float Vector of unit responses. w : numpy.ndarray : (num_units,) : int, float Vector of original treatment allocations across units. Returns ------- np.array(y_transformed) : numpy.ndarray : an array of transformed unit classes. """ y_transformed = [] for i in range(y.shape[0]): # Favorable, possible Affected Positive units (TPs or CNs) if self.is_treatment_positive(y[i], w[i]) or self.is_control_negative( y[i], w[i] ): y_transformed.append(1) # Unfavorable, possible Affected Negative units (TNs or CPs) elif self.is_treatment_negative(y[i], w[i]) or self.is_control_positive( y[i], w[i] ): y_transformed.append(0) return np.array(y_transformed)
[docs] def _binary_regularization(self, y=None, w=None): """ Regularization of binary classes is based on the positive and negative binary affectual classes. Parameters ---------- y : numpy.ndarray : (num_units,) : int, float Vector of unit responses. w : numpy.ndarray : (num_units,) : int, float Vector of original treatment allocations across units. Returns ------- fav_ratio, unfav_ratio : float Regularized ratios of favorable and unfavorable classes. """ # Initialize counts for Favorable and Unfavorable Classes. fav_count, unfav_count = 0, 0 for i in range(y.shape[0]): # Favorable (TPs or CNs) - contains all APs. if self.is_treatment_positive(y[i], w[i]) or self.is_control_negative( y[i], w[i] ): fav_count += 1 # Unfavorable (TNs or CPs) - contains all ANs. elif self.is_treatment_negative(y[i], w[i]) or self.is_control_positive( y[i], w[i] ): unfav_count += 1 self.fav_ratio = fav_count / (fav_count + unfav_count) self.unfav_ratio = unfav_count / (fav_count + unfav_count)
[docs] def fit(self, X, y, w): """ Trains a model given covariates, responses and assignments. Parameters ---------- X : numpy.ndarray : (num_units, num_features) : int, float Matrix of covariates. y : numpy.ndarray : (num_units,) : int, float Vector of unit responses. w : numpy.ndarray : (num_units,) : int, float Vector of original treatment allocations across units. Returns ------- self : causeinfer.standard_algorithms.BinaryTransformation A trained model. """ y_transformed = self._binary_transformation(y, w) if self.regularize: self._binary_regularization(y, w) self.model.fit(X, y_transformed) return self
# def predict(self, X): # """ # Predicts a causal effect given covariates. # Parameters # ---------- # X : numpy.ndarray : (num_units, num_features) : int, float # New data on which to make predictions. # Returns # ------- # predictions : numpy.ndarray : (num_units, 2) : float # """ # return predictions
[docs] def predict_proba(self, X): """ Predicts the probability that a subject will be a given class given covariates. Parameters ---------- X : numpy.ndarray : (num_units, num_features) : int, float New data on which to make predictions. Returns ------- probas : numpy.ndarray : (num_units, 2) : float Predicted probabilities for being a favorable class and unfavorable class. """ pred_fav = self.model.predict_proba(X)[:, 1] pred_unfav = self.model.predict_proba(X)[:, 0] if not self.regularize: return np.array([(pred_fav[i], pred_unfav[i]) for i in range(len(X))]) pred_fav_regularized = pred_fav * self.fav_ratio pred_unfav_regularized = pred_unfav * self.unfav_ratio return np.array( [ (pred_fav_regularized[i], pred_unfav_regularized[i]) for i in range(len(X)) ] )