아래 그림은 앞서 다뤘던 운동 여부에 따른 콜레스테롤 수치 비교 사례로, 일반적으로 처치집단에는 성향점수가 높은 개체가, 비교집단에는 성향점수가 낮은 개체가 과대표집 되었을 가능성이 큽니다.
따라서 과대표집에 대한 균형을 맞추고자 각 집단에 다른 가중치를 부여해 처치효과를 추정합니다.
Copy # dowhy.causal_estimators.propensity_score_weighting_estimator _estimate_effect 함수 코드 일부
# ips_weight
self . _data [ 'ips_weight' ] = ( 1 / num_units) * (
self . _data [ self . _treatment_name [ 0 ]] / self . _data [ 'ps' ] +
( 1 - self . _data [ self . _treatment_name [ 0 ]] ) / ( 1 - self . _data [ 'ps' ] )
)
self . _data [ 'tips_weight' ] = ( 1 / num_treatment_units) * (
self . _data [ self . _treatment_name [ 0 ]] +
( 1 - self . _data [ self . _treatment_name [ 0 ]] ) * self . _data [ 'ps' ] / ( 1 - self . _data [ 'ps' ] )
)
self . _data [ 'cips_weight' ] = ( 1 / num_control_units) * (
self . _data [ self . _treatment_name [ 0 ]] * ( 1 - self . _data [ 'ps' ] ) / self . _data [ 'ps' ] +
( 1 - self . _data [ self . _treatment_name [ 0 ]] )
)
# ips_normalized_weight
self . _data [ 'ips_normalized_weight' ] = (
self . _data [ self . _treatment_name [ 0 ]] / self . _data [ 'ps' ] / ipst_sum +
( 1 - self . _data [ self . _treatment_name [ 0 ]] ) / ( 1 - self . _data [ 'ps' ] ) / ipsc_sum
)
ipst_for_att_sum = sum (self._data[self._treatment_name[ 0 ]])
ipsc_for_att_sum = sum (( 1 - self._data[self._treatment_name[ 0 ]]) / ( 1 - self._data[ 'ps' ]) * self._data[ 'ps' ] )
self . _data [ 'tips_normalized_weight' ] = (
self . _data [ self . _treatment_name [ 0 ]] / ipst_for_att_sum +
( 1 - self . _data [ self . _treatment_name [ 0 ]] ) * self . _data [ 'ps' ] / ( 1 - self . _data [ 'ps' ] ) / ipsc_for_att_sum
)
ipst_for_atc_sum = sum (self._data[self._treatment_name[ 0 ]] / self._data[ 'ps' ] * ( 1 - self._data[ 'ps' ]))
ipsc_for_atc_sum = sum (( 1 - self._data[self._treatment_name[ 0 ]]))
self . _data [ 'cips_normalized_weight' ] = (
self . _data [ self . _treatment_name [ 0 ]] * ( 1 - self . _data [ 'ps' ] ) / self . _data [ 'ps' ] / ipst_for_atc_sum +
( 1 - self . _data [ self . _treatment_name [ 0 ]] ) / ipsc_for_atc_sum
)
# ips_stabilized_weight
p_treatment = sum (self._data[self._treatment_name[ 0 ]]) / num_units
self . _data [ 'ips_stabilized_weight' ] = ( 1 / num_units) * (
self . _data [ self . _treatment_name [ 0 ]] / self . _data [ 'ps' ] * p_treatment +
( 1 - self . _data [ self . _treatment_name [ 0 ]] ) / ( 1 - self . _data [ 'ps' ] ) * ( 1 - p_treatment)
)
self . _data [ 'tips_stabilized_weight' ] = ( 1 / num_treatment_units) * (
self . _data [ self . _treatment_name [ 0 ]] * p_treatment +
( 1 - self . _data [ self . _treatment_name [ 0 ]] ) * self . _data [ 'ps' ] / ( 1 - self . _data [ 'ps' ] ) * ( 1 - p_treatment)
)
self . _data [ 'cips_stabilized_weight' ] = ( 1 / num_control_units) * (
self . _data [ self . _treatment_name [ 0 ]] * ( 1 - self . _data [ 'ps' ] ) / self . _data [ 'ps' ] * p_treatment +
( 1 - self . _data [ self . _treatment_name [ 0 ]] ) * ( 1 - p_treatment)
)
# ATE, ATT, ATC 에 따라 다른 가중치 부여 방법
if self . _target_units == "ate" :
weighting_scheme_name = self . weighting_scheme
elif self . _target_units == "att" :
weighting_scheme_name = "t" + self . weighting_scheme
elif self . _target_units == "atc" :
weighting_scheme_name = "c" + self . weighting_scheme
else :
raise ValueError ( "Target units string value not supported" )
# 처치효과 계산
self . _data [ 'd_y' ] = ( # 처치집단 가중치 * outcome
self . _data [ weighting_scheme_name ] *
self . _data [ self . _treatment_name [ 0 ]] *
self . _data [ self . _outcome_name ]
)
self . _data [ 'dbar_y' ] = ( # 비교집단 가중치 * outcome
self . _data [ weighting_scheme_name ] *
( 1 - self . _data [ self . _treatment_name [ 0 ]] ) *
self . _data [ self . _outcome_name ]
)
est = self . _data [ 'd_y' ]. sum () - self . _data [ 'dbar_y' ]. sum ()
성향점수 가중 방법은 성향점수의 역수를 가중치로 적용하여 처치집단과 비교집단에 배치될 확률을 동일하게 만듭니다. 예를 들어 ATE 를 추정하는 경우, 아래 식과 같이 성향점수(PS(X))가 높을수록 처치집단(T)에 속한 개체는 작은 가중치(W)를, 비교집단(1-T)에 속한 개체는 큰 가중치(W)를 갖게 합니다.
이렇듯 성향점수의 역수를 활용하여 통계적 의미에서 실험적 설계 상황을 설정하게 함으로써 데이터가 관심 모집단 특성을 갖추도록 하는데 용이합니다. 다만 극단적 가중치의 영향을 받을 수 있어, 10보다 큰 가중치는 제외하고 분석하거나 성향점수의 상·하위 각 2.5%에 해당하는 개체를 제외하고 분석하는 방법이 있습니다.