인과 관계 추론 파이썬 구현
저자: Akanksha Anand (Ak)
원래 이 사이트에 게시되었습니다.
제 표준 관행에 따라 인과 관계 영향의 Python 구현을 소개해 드립니다. 이 시리즈의 이전 글에 익숙하지 않더라도 현재 글을 이해하는 데 필요한 기초 지식이 포함되어 있으니 안심하시기 바랍니다.
인과 추론 - 게임 체인저
아는 것이 추측을 이길 때
medium.com
인과 추론의 방법
근거에 대한 방법론 조사하기
medium.com
데이터 세트
이 애플리케이션의 현재 인스턴스화에 활용된 앞서 언급한 판매 데이터 세트를 제공한 Kaggle에 감사를 표합니다.
데이터 세트: https://www.kaggle.com/datasets/manjeetsingh/retaildataset
데이터 세트에 있는 세 개의 파일 중 저는 Sales 데이터 세트를 사용했습니다. 이 과거 판매 데이터는 2010-02-05부터 2012-11-01까지의 판매 정보를 포함합니다. 이 데이터 집합의 열은 다음과 같습니다:
- Store - 매장 번호
- Dept - 부서 번호
- Date - 주
- Weekly_Sales - 지정된 매장의 지정된 부서 매출
- IsHoliday - 해당 주가 특별 휴일 주간인지 여부
가져오는 라이브러리
우리가 사용하는 데이터 세트는 시계열 데이터 세트이므로 Google에서 개발한 CausalImpact 라이브러리를 사용하고 있습니다. 이 알고리즘의 주요 목표는 예상되는 시계열 데이터와 관찰된 시계열 데이터의 차이를 분석하여 특정 개입(또는 어떤 행동)이 어떤 응답 변수에 미친 예상 효과를 추론하는 것입니다. 일반적으로 특정 캠페인의 예상 수익을 예측하거나 특정 채널을 완전히 비활성화하여 해당 채널에서 발생하는 수익을 더 정확하게 파악하는 등 마케팅 개입이 비즈니스에 미치는 영향을 추론하는 데 사용됩니다.
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from scipy import statsimport os
print(os.listdir("../input"))import warnings
warnings.filterwarnings("ignore")!pip install pycausalimpact
from causalimpact import CausalImpact
데이터 세트 로드 중
필요한 라이브러리를 성공적으로 가져왔으면 다음 단계는 분석의 기초가 될 데이터 세트를 도입하는 것입니다.
df = pd.read_csv("/kaggle/input/retaildataset/sales data-set.csv")
df.head()
Author의 이미지입니다: 데이터 세트 - 매출 데이터 세트
데이터 세트의 규모와 열의 데이터 유형과 같은 기본 데이터를 확보한 후, 향후 활용도를 높이기 위해 각 데이터 유형을 조정할 것입니다. 또한 데이터 세트 내의 고유한 매장 및 부서의 고유 개수를 조사할 것입니다.
df['Store'] = df['Store'].astype('category')
df['Dept'] = df['Dept'].astype('string')
df['Date'] = pd.to_datetime(df['Date'], format='%d/%m/%Y')print("Total number of stores:", df.Store.nunique())
print("Total number of departments:", df.Dept.nunique())
여러 매장 및 부서의 대량의 데이터를 관리하는 것은 특히 이러한 데이터를 효과적으로 분석하려고 할 때 상당한 어려움을 초래할 수 있습니다. 이 문제를 해결하려면 압도적이거나 다루기 힘들지 않으면서도 가치 있는 인사이트를 제공할 수 있는 일부 정보에 집중하는 것이 좋습니다. 분석가는 데이터에서 불필요한 변동을 걸러냄으로써 특정 목표와 관련된 패턴과 추세를 보다 쉽게 식별할 수 있습니다.
데이터 준비
데이터 집합의 명확성과 이해도를 높이기 위해 중복되거나 관련 없는 데이터 요소를 제거할 것입니다. 이 과정을 통해 데이터 집합에 포함된 정보를 보다 집중적으로 표현하여 시각적으로 분석하고 해석하기가 더 쉬워질 것입니다.
df_sales_new=df[(df['Store'] == 10) & (df['Dept'].isin(['1', '2', '3', '4','5' ]))].drop(columns=['IsHoliday'])
df_sales_new['Date'] = pd.to_datetime(df_sales_new['Date'])
plt.figure(figsize=(10, 5))
sns.lineplot(data=df_sales_new, x='Date', y='Weekly_Sales',hue="Dept")
plt.show()
매장 10 내 5개 부서에 대한 매출 데이터는 다음과 같습니다:
추세를 통해 다음과 같은 사실을 관찰할 수 있습니다:
부서 1은 4월 한 달 동안 매출이 크게 증가했으며, 11월과 12월에는 연말에 이어서 매출이 상승했습니다.
부서 2는 9월까지 꾸준한 상승세를 보이다가 12월에 눈에 띄는 큰 폭의 증가세를 보였습니다.
부서 3은 8월과 9월에 눈에 띄는 성장세를 보였고 12월과 1월에도 소폭 증가하며 꾸준한 판매 수치를 기록했습니다. 이 부서는 교육 및 문구용품을 전문으로 취급하는 것으로 보입니다.
부서 4는 시간이 지남에 따라 매출이 꾸준히 증가했으며, 가끔씩 그 규모가 미미한 편차를 보였습니다.
부서 5는 매년 연초에 이 특정 품목의 매출이 급증한 후 그 해의 마지막 달, 특히 12월에 수요가 크게 증가하는 것을 관찰했습니다.
인과 관계 추론 분석을 수행하기 위해 부서 4의 7월부터 9월까지의 분기 동안 마케팅 캠페인으로 인한 매출 증가와 같은 변경 사항을 도입하여 데이터 집합을 수정합니다. 이렇게 하면 이러한 변경이 부서의 전체 실적에 미치는 영향을 더 잘 이해할 수 있습니다.
이 목표를 달성하기 위해 다음 코딩 방식을 사용하여 데이터 집합에 새 열을 도입합니다.
df_dept4_marketing=df_sales_new.copy()
df_dept4_marketing['Marketing_Campaign'] = np.where((df_dept4_marketing['Dept'] == '4') & (df_dept4_marketing['Date'] > "2012-06-30") &
(df_dept4_marketing['Date'] < "2012-10-01"),'Active', 'Inactive')
변경 사항을 확인하려면 여기에 제공된 코드 스니펫을 활용하세요:
print(df_dept4_marketing[
(df_dept4_marketing['Date'] > "2012-06-01") &
(df_dept4_marketing['Date'] < "2012-12-01") &
((df_dept4_marketing['Dept'] == '2') U\\+007C (df_dept4_marketing['Dept'] == '4'))])
Image by Author
데이터 집합에 플래그를 지정하는 과정을 거친 후, 매출 수치를 45% 늘려서 개선하는 작업을 진행합니다. 제공된 정보가 주 단위라는 점을 감안할 때, 이 접근 방식은 그 효과를 보다 포괄적으로 이해할 수 있게 해줍니다.
new_sales = df_dept4_marketing.copy()
new_sales['New_sales']=np.where(new_sales['Marketing_Campaign']=="Active",new_sales['Weekly_Sales'] * 1.45 ,new_sales['Weekly_Sales'])
plt.figure(figsize=(10, 5))
sns.lineplot(
data=df_sales_new.query("Dept == '4'"),
x="Date", y="Weekly_Sales",label='Old sales'
)
sns.lineplot(
data=new_sales.query("Dept == '4'"),
x="Date", y="New_sales",label='Updated sales'
)
plt.show()
합성 데이터 집합을 생성한 후 라이브러리 기능의 요구 사항에 적합한 형태로 변환합니다. 데이터 세트에서 부서 번호는 개별 레코드 내에 포함되어 있으며 각 부서에 대한 주간 판매 보고서를 표시하기 위해 재배열되어야 합니다. 또한 잠재적인 모호성을 방지하기 위해 다양한 다른 열을 제거했습니다.
df_sales_causal=new_sales.pivot(index="Date", columns="Dept", values="New_sales")
df_sales_causal.columns=['Dept_1', 'Dept_2', 'Dept_3', 'Dept_4', 'Dept_5']
df_sales_causal=df_sales_causal.sort_values(by='Date')
df_final=df_sales_causal.drop(['Dept_1', 'Dept_2', 'Dept_3', 'Dept_5'],axis=1)
plt.figure(figsize=(10, 5))
sns.lineplot(data=df_final,x="Date", y="Dept_4")
plt.show()
Image by Author
인과 관계 분석
이제 인과 관계 분석을 위한 데이터 집합이 준비되었으므로 지정된 함수를 실행해야 합니다. 이를 위해서는 개입 전과 개입 후 기간에 대한 값을 지정해야 합니다. 구체적으로는 개입 또는 마케팅 캠페인을 실행하기 전의 기간과 그러한 활동이 시행되는 이후의 기간을 지정하는 것이 포함됩니다.
marketing_pre_period=['2010-02-05','2012-06-29']
marketing_post_period=['2012-07-06','2012-10-26']
impact = CausalImpact(df_final, marketing_pre_period, marketing_post_period)
print(impact.summary())
Image by Author
요약에 따르면, 분석 결과 대조군에 비해 예상 결과가 약 30% 증가한 것으로 나타났습니다. 그러나 데이터에 방법론을 적용했을 때는 45%라는 인상적인 상승률을 달성했습니다. 또한 이 추정치의 신뢰 구간은 27%에서 33% 사이로, 결과의 확실성이 매우 높다는 것을 알 수 있습니다.특히, 이러한 결과와 관련된 p-값이 매우 낮게 나타나 결론의 타당성과 통계적 유의성을 더욱 뒷받침하고 있습니다.
사용 가능한 옵션은 조사 결과에 대한 개요를 제공하는 ‘보고서’라고 하는 문서를 생성하는 것으로, 편의를 위해 결과를 요약한 것입니다.
print(impact.summary(output='report'))
Analysis report {CausalImpact}During the post-intervention period, the response variable had
an average value of approx. 63253.19. By contrast, in the absence of an
intervention, we would have expected an average response of 48680.53.
The 95% interval of this counterfactual prediction is [47212.46, 50129.88].
Subtracting this prediction from the observed response yields
an estimate of the causal effect the intervention had on the
response variable. This effect is 14572.65 with a 95% interval of
[13123.31, 16040.73]. For a discussion of the significance of this effect,
see below.Summing up the individual data points during the post-intervention
period (which can only sometimes be meaningfully interpreted), the
response variable had an overall value of 1075304.21.
By contrast, had the intervention not taken place, we would have expected
a sum of 827569.08. The 95% interval of this prediction is [802611.85, 852207.98].The above results are given in terms of absolute numbers. In relative
terms, the response variable showed an increase of \\+29.94%. The 95%
interval of this percentage is [26.96%, 32.95%].This means that the positive effect observed during the intervention
period is statistically significant and unlikely to be due to random
fluctuations. It should be noted, however, that the question of whether
this increase also bears substantive significance can only be answered
by comparing the absolute effect (14572.65) to the original goal
of the underlying intervention.The probability of obtaining this effect by chance is very small
(Bayesian one-sided tail-area probability p = 0.0).
This means the causal effect can be considered statistically
significant.
전체 코드는 여기에서 확인할 수 있습니다: Kaggle
여기까지입니다!
제 블로그가 마음에 드셨다면 박수를 보내주시고 팔로우해 주세요! LinkedIn
권위 있는 AI 뉴스레터에 이미 가입한 8만 명 이상의 구독자로 구성된 존경받는 커뮤니티에 진심으로 초대합니다. 이 플랫폼은 획기적인 연구 결과부터 혁신적인 프로젝트 구현 및 새로운 개념에 이르기까지 끊임없이 진화하는 인공지능 환경에 관한 최신 업데이트를 회원들에게 제공하기 위해 최선을 다하고 있습니다. AI 스타트업을 설립하거나 AI 중심 제품을 개발하거나 이 분야와 관련된 서비스를 제공하는 개인 및 조직을 포함한 다양한 고객층을 대상으로 합니다. 또한, 저희의 비전을 공유하고 파트너십 기회를 고려하여 저희의 사명을 지원하고자 하는 잠재적 후원자에게도 감사의 말씀을 전합니다.
이 사이트를 통해 게시됨