def _assign(self, x): # Assignment should be biased towards treatments that help more. assert self.centroids is not None, "Must call __fit__ before __assign__." distances = self.get_centroid_weights(x) expected_responses = [] for treatment in range(self.num_treatments + 1): _, response_mean, response_std = self.centroids[treatment] y_this_treatment = self.random_generator.normal( response_mean, response_std) expected_responses.append( clip_percentage( y_this_treatment + self.random_generator.normal(0.0, self.epsilon_std))) expected_responses = np.array(expected_responses) y = [] control_response, control_distance = expected_responses[-1], distances[ -1] if self.with_exposure: treatment_means = [0.6, 0.65, 0.4] treatment_strengths = [] for treatment_idx in range(self.num_treatments): dose_response_curve, d, d0_mean, d0_std, d0_min, d1_mean, d1_std, d1_min \ = self.get_dose_response_curve(x, treatment_idx, return_all=True) treatment_mean = treatment_means[treatment_idx] \ if treatment_idx < len(treatment_means) else treatment_means[-1] if treatment_mean is None: treatment_strength = self.random_generator.uniform() else: treatment_strength = clip_percentage( self.random_generator.normal(treatment_mean, 0.1)) treatment_strengths.append(treatment_strength) this_y = dose_response_curve(treatment_strength) y.append(this_y * expected_responses[treatment_idx]) treatment_strengths = np.array(treatment_strengths) else: for treatment_idx in range(self.num_treatments): this_response, this_distance = expected_responses[ treatment_idx], distances[treatment_idx] y.append(this_response * (this_distance + control_distance)) y = np.array(y) # Invert the expected responses, because a lower percentage of recurrence/death is a better outcome. treatment_chosen = self.random_generator.choice( self.num_treatments, p=stable_softmax(self.strength_of_assignment_bias * y)) if self.with_exposure: return treatment_chosen, self.scaling_offset + self.scaling_constant * y, treatment_strengths else: return treatment_chosen, self.scaling_offset + self.scaling_constant * y
def _assign(self, x): # Assignment should be biased towards treatments that help more. assert self.centroids is not None, "Must call __fit__ before __assign__." if not self.is_v2: # TODO: Assignment and Y are independent = no assignment bias. expected_responses = np.dot(self.centroids.T, x[7:]) + self.random_generator.normal( 0, 0.1) treatment_chosen = self.random_generator.binomial( 1, p=sigmoid(expected_responses)) lighter_sex, heavier_sex = x[3], x[4] if self.num_treatments == 2: outcomes = [x[5], x[6]] else: outcomes = [None, None, None, None] if lighter_sex == DataAccess.GENDER_MALE: outcomes[0] = x[5] else: outcomes[2] = x[5] if heavier_sex == DataAccess.GENDER_MALE: outcomes[1] = x[6] else: outcomes[3] = x[6] if (treatment_chosen == 0 and lighter_sex == DataAccess.GENDER_FEMALE) or\ (treatment_chosen == 1 and heavier_sex == DataAccess.GENDER_FEMALE): treatment_chosen += 2 return treatment_chosen, outcomes else: distances = self.get_centroid_weights(x) y = [] control_distance = distances[-1] for treatment_idx in range(self.num_treatments): this_distance = distances[treatment_idx] y.append(50 * (this_distance + control_distance) + self.random_generator.normal(0.0, 1.0)) y = np.array(y) # Invert the expected responses, because a lower percentage of recurrence/death is a better outcome. choice_percentage = stable_softmax( self.strength_of_assignment_bias * distances[:-1]) treatment_chosen = self.random_generator.choice( self.num_treatments, p=choice_percentage) return treatment_chosen, y
def _assign(self, x): # Assignment should be biased towards treatments that help more. assert self.centroids is not None, "Must call __fit__ before __assign__." distances = self.get_centroid_weights(x) expected_responses = [] for treatment in range(self.num_treatments + 1): _, response_mean, response_std = self.centroids[treatment] y_this_treatment = self.random_generator.normal(response_mean, response_std) expected_responses.append( clip_percentage(y_this_treatment + self.random_generator.normal(0.0, self.epsilon_std)) ) expected_responses = np.array(expected_responses) control_response, control_distance = expected_responses[-1], distances[-1] y = [] if self.with_exposure: treatment_strengths = [] for treatment_idx in range(self.num_treatments): dose_response_curve, d, d0_mean, d0_std, d0_min, d1_mean, d1_std, d1_min \ = self.get_dose_response_curve(x, treatment_idx, return_all=True) treatment_strength = clip_percentage( self.random_generator.exponential(scale=0.25) ) treatment_strengths.append(treatment_strength) this_y = dose_response_curve(treatment_strength) y.append(this_y * expected_responses[treatment_idx]) treatment_strengths = np.array(treatment_strengths) else: for treatment_idx in range(self.num_treatments): this_response, this_distance = expected_responses[treatment_idx], distances[treatment_idx] y.append(this_response * (this_distance + control_distance)) y = np.array(y) treatment_chosen = self.random_generator.choice(self.num_treatments, p=stable_softmax( self.strength_of_assignment_bias * y) ) if self.with_exposure: return treatment_chosen, self.scaling_constant*y, treatment_strengths else: return treatment_chosen, self.scaling_constant*y
def get_dose_response_curve(self, z, treatment_idx, return_all=False): dosage_distances = self.get_centroid_weights(z, centroids=self.dosage_centroids[treatment_idx]) normalised_distances = stable_softmax(self.strength_of_assignment_bias * dosage_distances) d = normalised_distances _, d0_mean, d0_std, d0_min = self.dosage_centroids[treatment_idx][0] _, d1_mean, d1_std, d1_min = self.dosage_centroids[treatment_idx][1] def dose_response_curve(treatment_strength): this_y = d[0] * gaussian(treatment_strength - d0_min, d0_mean, d0_std) + \ d[1] * gaussian(treatment_strength - d1_min, d1_mean, d1_std) return this_y if return_all: return dose_response_curve, d, d0_mean, d0_std, d0_min, d1_mean, d1_std, d1_min else: return dose_response_curve