docstr: Finds the set of parameters that gives the best matching result.
  
  Score = (number of features with SMD > max_smd)
          + (sum of deviations for important variables
             * deviation factor)
  
  The logic behind the scoring is that we are most concerned with
  minimizing the number of features where SMD is lower than a certain
  threshold (max_smd). However, we would also like the matched dataset
  not deviate too much from the original dataset, in terms of key
  variable(s), so that we still retain a similar userbase.
  
  Args:
      - treatment_col (str): name of the treatment column
      - ps_col (str): name of the propensity score column
      - max_smd (float): maximum acceptable SMD
      - max_deviation (float): maximum acceptable deviation for
          important variables
      - caliper_range (tuple): low and high bounds for caliper search
          range
      - max_pihat_range (tuple): low and high bounds for max pihat
          search range
      - max_iter_per_param (int): maximum number of search values per
          parameters
      - min_users_per_group (int): minimum number of users per group in
          matched set
      - smd_cols (list): score is more sensitive to these features
          exceeding max_smd
      - dev_factor (float): importance weight factor for dev_cols
          (e.g. dev_factor=1 means a 10% deviation leads to penalty of 1
          in score)
      - dev_cols_transformations (dict): dict of transformations to be
          made on dev_cols
      - verbose (bool): boolean flag for printing statements
  
  Returns:
      The best matched dataset (pd.DataFrame)
docstr_tok: ["Finds","the","set","of","parameters","that","gives","the","best","matching","result",".","Score","=","(","number","of","features","with","SMD",">","max_smd",")","+","(","sum","of","deviations","for","important","variables","*","deviation","factor",")","The","logic","behind","the","scoring","is","that","we","are","most","concerned","with","minimizing","the","number","of","features","where","SMD","is","lower","than","a","certain","threshold","(","max_smd",")",".","However",",","we","would","also","like","the","matched","dataset","not","deviate","too","much","from","the","original","dataset",",","in","terms","of","key","variable","(","s",")",",","so","that","we","still","retain","a","similar","userbase",".","Args",":","-","treatment_col","(","str",")",":","name","of","the","treatment","column","-","ps_col","(","str",")",":","name","of","the","propensity","score","column","-","max_smd","(","float",")",":","maximum","acceptable","SMD","-","max_deviation","(","float",")",":","maximum","acceptable","deviation","for","important","variables","-","caliper_range","(","tuple",")",":","low","and","high","bounds","for","caliper","search","range","-","max_pihat_range","(","tuple",")",":","low","and","high","bounds","for","max","pihat","search","range","-","max_iter_per_param","(","int",")",":","maximum","number","of","search","values","per","parameters","-","min_users_per_group","(","int",")",":","minimum","number","of","users","per","group","in","matched","set","-","smd_cols","(","list",")",":","score","is","more","sensitive","to","these","features","exceeding","max_smd","-","dev_factor","(","float",")",":","importance","weight","factor","for","dev_cols","(","e.g",".","dev_factor=1","means","a","10","%","deviation","leads","to","penalty","of","1","in","score",")","-","dev_cols_transformations","(","dict",")",":","dict","of","transformations","to","be","made","on","dev_cols","-","verbose","(","bool",")",":","boolean","flag","for","printing","statements","Returns",":","The","best","matched","dataset","(","pd.DataFrame",")"]
code: def __init__(
      self,
      treatment_col="is_treatment",
      ps_col="pihat",
      user_col=None,
      matching_covariates=["pihat"],
      max_smd=0.1,
      max_deviation=0.1,
      caliper_range=(0.01, 0.5),
      max_pihat_range=(0.95, 0.999),
      max_iter_per_param=5,
      min_users_per_group=1000,
      smd_cols=["pihat"],
      dev_cols_transformations={"pihat": np.mean},
      dev_factor=1.0,
      verbose=True,
  ):
      """Finds the set of parameters that gives the best matching result.
  
      Score = (number of features with SMD > max_smd)
              + (sum of deviations for important variables
                 * deviation factor)
  
      The logic behind the scoring is that we are most concerned with
      minimizing the number of features where SMD is lower than a certain
      threshold (max_smd). However, we would also like the matched dataset
      not deviate too much from the original dataset, in terms of key
      variable(s), so that we still retain a similar userbase.
  
      Args:
          - treatment_col (str): name of the treatment column
          - ps_col (str): name of the propensity score column
          - max_smd (float): maximum acceptable SMD
          - max_deviation (float): maximum acceptable deviation for
              important variables
          - caliper_range (tuple): low and high bounds for caliper search
              range
          - max_pihat_range (tuple): low and high bounds for max pihat
              search range
          - max_iter_per_param (int): maximum number of search values per
              parameters
          - min_users_per_group (int): minimum number of users per group in
              matched set
          - smd_cols (list): score is more sensitive to these features
              exceeding max_smd
          - dev_factor (float): importance weight factor for dev_cols
              (e.g. dev_factor=1 means a 10% deviation leads to penalty of 1
              in score)
          - dev_cols_transformations (dict): dict of transformations to be
              made on dev_cols
          - verbose (bool): boolean flag for printing statements
  
      Returns:
          The best matched dataset (pd.DataFrame)
      """
      self.treatment_col = treatment_col
      self.ps_col = ps_col
      self.user_col = user_col
      self.matching_covariates = matching_covariates
      self.max_smd = max_smd
      self.max_deviation = max_deviation
      self.caliper_range = np.linspace(
          *caliper_range, num=max_iter_per_param
      )
      self.max_pihat_range = np.linspace(
          *max_pihat_range, num=max_iter_per_param
      )
      self.max_iter_per_param = max_iter_per_param
      self.min_users_per_group = min_users_per_group
      self.smd_cols = smd_cols
      self.dev_factor = dev_factor
      self.dev_cols_transformations = dev_cols_transformations
      self.best_params = {}
      self.best_score = 1e7  # ideal score is 0
      self.verbose = verbose
      self.pass_all = False
  
imports: import argparse
  import logging
  import sys
  import numpy
  import pandas
  from sklearn.neighbors import NearestNeighbors
  from sklearn.preprocessing import StandardScaler
  from sklearn.utils import check_random_state
label_desc: Use image node_id 1 to create a new MatchOptimizer object from inherited base classes: object with example: obj = MatchOptimizer(treatment_col, ps_col, user_col, matching_covariates, max_smd, max_deviation, caliper_range, max_pihat_range, max_iter_per_param, min_users_per_group, smd_cols, dev_cols_transformations, dev_factor, verbose)