최적의 할인율을 어떻게 구할 수 있을까? - 회귀 분석

Robin_UPDATA·2023년 5월 21일

머신러닝

목록 보기
2/4
post-thumbnail

00. 할인율 / 할인금액을 어떻게 정할 수 있을까?

모두가 그러지는 않을 수 있습니다. 하지만 적어도 저는 아직 이커머스에서 고객에게 혜택을 제공할 때 그 혜택내용을 크게 고민하지는 않고 업무를 진행했던 것 같습니다. 이전에는 10% 할인쿠폰을 사용했으니까, 지난 번에는 1만원 할인쿠폰 사용했는데 결과가 잘 나왔으니까 또 같은 형식으로 프로모션을 진행했던 적이 꽤 많았습니다. 비용 시뮬레이션을 한다고는 하지만 크게 고민하고 진행하지는 않았습니다.
그러다가 문득 이런 생각이 들었습니다. 지금 내가 만들고 있는 혜택이 정말 최선의 혜택인가? 이렇게 쿠폰 스킴을 기획해도 되는걸까? 그래서 고민을 하기 시작했습니다. 어떤 혜택이 정말 최선의 결과를 나을 수 있는 혜택일까? 어떻게 혜택을 설정해야 더 적합한 프로모션을 진행할 수 있을까? 하는 생각들을요. 그래서 찾아보기로 했습니다.

최적의 할인율을 어떻게 구할 수 있을까?

시간이 충분하다면 A/B 테스트를 진행하는 것이 가장 좋은 방법이라고 생각합니다. 여러 그룹을 나누고 각각 나눠서 어떤 혜택이 가장 최선일지 보는 것이 쉽고 직관적으로 이러한 문제에 대한 해답을 낳을 수 있다고 생각합니다. 그러나 시간이 충분히 필요하고 예산을 집행해야 하는 상황에서 A/B 테스트는 제가 선택할 수 있는 선택지에는 존재하지 않았습니다. 따라서 저는 과거에 진행했던 데이터를 바탕으로 최적 할인율을 구하는 방식을 진행하기로 했습니다. 데이터를 더욱 확인해봐야 정확하겠지만 일반적으로 할인율과 구매고객수는 선형관계를 취할 것이라고 가정하고 회귀 모델에 기반하여 최적의 할인율을 구하기로 했습니다.

01. 어떻게 해야 더 정확한 최적 할인율을 구할 수 있을까?

현재 해결해야 하는 문제를 다시 구체화해보도록 하겠습니다. 특정 쿠폰을 고객에게 지급했을 때, 구매고객수가 가장 많이 발생하는 최적의 할인율을 구하고 싶습니다. 따라서 다른 목표(구매액, 구매건수 등)는 일단 무시하고 구매고객수만 고려하도록 하겠습니다. 또한 쿠폰에는 할인율 뿐만 아니라 다른 여러 가지 조건이 존재합니다. 이러한 조건들도 최적 할인율을 구할 때 같이 고려해야 합니다. 이러한 조건에는 최소구매액, 최대할인금액, 전체 예산, 쿠폰지급수가 존재합니다. 쿠폰에 따라서 쿠폰지급수가 차이가 있을 수도 있기 때문에 변수로 사용하기에는 구매고객수보단 쿠폰구매율(구매고객수/쿠폰지급수)을 고려하는 것이 더욱 적합할 듯 합니다.

일단 최적 할인율을 구하기 위해서는 회귀모델을 사용하고자 합니다. 이 때 회귀에 대해서 간단히 정리를 하도록 하겠습니다. 회귀는 이전 글에서 다룬 분류와 마찬가지로 대표적인 머신러닝 지도학습입니다. 분류가 결과를 클래스, 즉 카테고리로 나누는 모델이었다면 회귀는 결과가 연속형 숫자 값이 나오게 됩니다. 이러한 회귀 중 대표적인 모델이 선형 회귀입니다. 선형 회귀는 실제 값과 예측 값의 차이를 최소화하는 직선형 회귀선을 최적화하는 방식으로 이 안에서도 일반 선형 회귀, 릿지, 라쏘, 엘라스틱넷, 로지스틱 회귀 등이 존재합니다.

다양한 회귀 모델에 대해서는 이후 알아보도록 하고 이번 최적 할인율 예측에서는 최대한 간단한 선형 회귀모델을 사용하도록 하겠습니다. 이 때 모델에 사용되는 독립변수가 하나 이상이므로 다중 선형 회귀 모델로 진행을 하도록 하겠습니다. 다중 선형 회귀는 종속 변수와 둘 이상의 독립 변수 간의 관계를 모델링하는 통계적 기법입니다. 이는 선형 회귀의 확장된 형태로, 하나의 종속 변수에 여러 개의 독립 변수가 영향을 미치는 경우에 사용됩니다. 다중 선형 회귀의 기본적인 아이디어는 종속 변수와 독립 변수들 간의 선형 관계를 가정하는 것입니다. 종속 변수는 예측하고자 하는 변수이며, 독립 변수들은 종속 변수에 영향을 주는 변수들입니다.

다중 선형 회귀는 여러 개의 독립 변수들이 종속 변수에 영향을 미치는 경우에 유용합니다. 예를 들어, 집 가격을 예측하는 모델을 만들고자 할 때, 방의 개수, 욕실의 개수, 주택 면적 등 여러 독립 변수들이 종속 변수인 집 가격에 영향을 미칠 수 있습니다. 이러한 경우에 다중 선형 회귀를 사용하여 종속 변수와 독립 변수들 간의 관계를 모델링하고, 새로운 독립 변수 값에 대한 종속 변수 값을 예측할 수 있습니다.

현재로서는 해당 분석을 통해서 스터디를 우선적으로 하는 게 목적이기 때문에 가장 간단한 모델을 사용하면서 업무를 정리해보도록 하겠습니다.

02. 회귀분석

본격적인 내용을 다루기에 앞서 먼저 회귀분석에 대해서 간략하게 이해하고 넘어가도록 하겠습니다. 회귀 분석은 종속 변수와 독립 변수 사이의 관계를 모델링하는 방법입니다. 종속 변수는 예측하고자 하는 변수이며, 독립 변수는 종속 변수에 영향을 주는 변수들입니다. 회귀 분석은 이러한 변수들 간의 관계를 통계적인 모델로 나타내어 예측, 해석, 인과 관계 추론 등 다양한 분석 목적을 달성할 수 있습니다.

회귀 분석의 중요성은 다음과 같은 이유로 설명될 수 있습니다

  1. 변수 간의 관계 이해

회귀 분석을 통해 변수 간의 관계를 이해할 수 있습니다. 독립 변수와 종속 변수 사이의 선형, 비선형, 양의 또는 음의 상관 관계 등을 파악할 수 있습니다. 이를 통해 도메인 지식을 획득하고 데이터에 대한 통찰력을 얻을 수 있습니다.

  1. 예측 및 추론

회귀 분석은 종속 변수의 값을 예측하는 데 사용됩니다. 학습된 회귀 모델을 통해 독립 변수 값을 입력하면 종속 변수의 예상 값을 얻을 수 있습니다. 또한 회귀 분석은 인과 관계를 추론하는 데에도 사용될 수 있습니다.

  1. 변수 영향력 파악

회귀 분석은 독립 변수가 종속 변수에 미치는 영향력을 파악하는 데 도움을 줍니다. 각 독립 변수의 회귀 계수를 통해 변수의 상대적인 중요성을 알 수 있으며, 이를 통해 변수의 가중치나 중요도를 평가하고 비교할 수 있습니다.

  1. 이상치 탐지 및 처리

회귀 분석은 이상치를 탐지하고 처리하는 데에도 사용됩니다. 이상치는 데이터의 정확성과 모델의 정확도에 부정적인 영향을 미칠 수 있으므로, 회귀 분석을 통해 이상치를 식별하고 조치를 취할 수 있습니다.

단순 선형 회귀는 독립 변수와 종속 변수 사이의 선형 관계를 모델링하는 회귀 분석 방법입니다. 이는 종속 변수와 독립 변수 간의 최적의 직선을 찾아내어 예측과 해석을 가능하게 합니다. 단순 선형 회귀 모델은 다음과 같은 형태로 표현됩니다. Y = β₀ + β₁X + ε
여기서 Y는 종속 변수, X는 독립 변수, β₀와 β₁는 회귀 계수(coefficients)이고, ε는 오차 항(error term)입니다. β₀는 y 절편(intercept)을 나타내며, β₁은 독립 변수 X의 기울기(slope)를 나타냅니다.

회귀 분석에서 가장 일반적으로 사용되는 추정 방법은 최소 제곱법(Ordinary Least Squares, OLS)입니다. 최소 제곱법은 오차 제곱의 합을 최소화하여 회귀 계수를 추정하는 방법입니다. 이를 통해 β₀와 β₁을 구하게 됩니다.

회귀 모델의 성능 평가는 여러 가지 지표를 사용할 수 있습니다. 대표적으로는 다음과 같은 지표들이 사용됩니다:

  1. 평균 제곱 오차(Mean Squared Error, MSE) : 실제 값과 예측 값의 오차를 제곱하여 평균한 값입니다. 작을수록 모델의 예측이 정확합니다.
  2. 결정 계수(Coefficient of Determination, R²) : 종속 변수의 총 변동 중 모델이 설명하는 변동의 비율을 나타냅니다. 0과 1 사이의 값이며, 1에 가까울수록 모델이 데이터를 잘 설명합니다.
  3. t-검정(t-test) 및 p-값(p-value) : 회귀 계수의 유의성을 평가하기 위해 사용됩니다. t-검정은 각 회귀 계수의 t-통계량을 계산하고, p-값은 해당 계수가 유의한지를 판단하는 데 사용됩니다.

03. 데이터 수집 및 전처리

가장 중요한 파트입니다. 우선적으로 독립 변수들의 데이터를 수집하고자 하는데 이 때 쿠폰의 스킴(최대할인금액, 최소구매액, 쿠폰지급수)와 전체 예산, 그리고 쿠폰사용수를 정리해야 합니다. 또한 쿠폰의 형태 또한 고려해야 하는데 할인율이 정해져있는 쿠폰 (10% 할인 쿠폰)이 있는 반면 할인금액이 정해져있는 쿠폰 (1만원 할인 쿠폰)이 있기 때문에 이러한 쿠폰의 형태 또한 구분해야 합니다. 또한 쿠폰의 세부조건이 있을 수도 있습니다. 특정 카테고리만 적용이 가능한 쿠폰, 한 개의 상품에만 적용 가능한 쿠폰, 장바구니 전체에 적용이 가능한 쿠폰처럼 여러 조건을 정리해야 합니다. 추가적으로 쿠폰이 특정 대상에게 지급된 것인지 아니면 누구나 사용가능한 쿠폰인지도 구분해야 합니다. vip고객에게만 제공된 쿠폰이라면 당연히 사용률도 높을 것이고 전체 대상이 사용 가능한 쿠폰이라면 사용률이 낮을 것이기 때문입니다.

이렇게 다양한 데이터를 다루게 되면 진행해야 하는 업무가 달라지게 됩니다. 예를 들어 카테고리 별로 적용 가능 여부를 보기 위해서 해당 데이터를 넣게 된다면 더 많은 전처리 과정을 거쳐야 하고 모델 또한 더욱 복잡해지는 경우가 많아집니다. 단순 회귀모델로 보기 어려우며 트리 기반 모델(예: 랜덤포레스트, XGBoost, LightGBM)을 통해 비선형 및 복잡한 상호 작용을 처리하는 게 더욱 효과적입니다.

이러한 실제적인 업무에 대해서는 다음 글에서 더욱 자세하게 살펴보도록 하고 이번에는 일반 회귀모델에 집중해서 내용을 진행해보도록 하겠습니다.

04. 선형 회귀 모델 생성 및 평가

가상의 데이터를 바탕으로 선형 회귀 모델을 생성하고 평가 또한 해보도록 하겠습니다.

import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error

# 가상의 데이터 생성
data = pd.DataFrame({'discount_rate': np.random.rand(100),
                     'promotion_length': np.random.randint(1, 30, 100),
                     'max_discount_amount': np.random.randint(1000, 5000, 100),
                     'min_purchase_amount': np.random.randint(1000, 10000, 100),
                     'number_of_coupons': np.random.randint(50, 200, 100),
                     'total_budget': np.random.randint(10000, 100000, 100),
                     'used_coupons': np.random.randint(1, 200, 100)})

# 쿠폰 사용률 계산 (used_coupons / number_of_coupons)
data['coupon_usage_rate'] = data['used_coupons'] / data['number_of_coupons']

위와 같은 코드를 통해서 가상의 데이터를 생성해보도록 하겠습니다. 변수는 더욱 다양할 수 있지만 효율성을 위해서 대략적인 변수로만 이를 확인해보도록 하겠습니다. X는 독립 변수를 나타내는 DataFrame으로, 'discount_rate', 'promotion_length', 'max_discount_amount', 'min_purchase_amount', 'number_of_coupons', 'total_budget' 열을 포함합니다. y는 종속 변수를 나타내는 Series로, 'number_of_customers' 열을 포함합니다.

X = data[['discount_rate', 'promotion_length', 'max_discount_amount', 'min_purchase_amount', 'number_of_coupons', 'total_budget']]
y = data['coupon_usage_rate']

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

linear_regression = LinearRegression()
linear_regression.fit(X_train, y_train)

y_pred = linear_regression.predict(X_test)

mse = mean_squared_error(y_test, y_pred)

train_test_split 함수를 사용하여 데이터를 훈련 세트와 테스트 세트로 분할합니다. test_size=0.2는 테스트 세트의 비율을 20%로 설정하고, random_state=42는 분할을 재현 가능하도록 난수 생성기의 시드를 설정합니다. mean_squared_error 함수를 사용하여 예측값과 실제값 간의 평균 제곱 오차(MSE)를 계산합니다. MSE는 모델의 예측 오차를 측정하는 지표로, 값이 작을수록 예측 성능이 높음을 의미합니다.

X = data.drop(['coupon_usage_rate', 'used_coupons'], axis=1)
y = data['coupon_usage_rate']

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

rf_regressor = RandomForestRegressor(n_estimators=100, random_state=42)
rf_regressor.fit(X_train, y_train)

y_pred = rf_regressor.predict(X_test)

best_discount_rate = 0
best_usage_rate = 0

for discount_rate in np.arange(0.1, 1, 0.1):
    X_scenario = X.copy()
    X_scenario['discount_rate'] = discount_rate
    
    y_scenario_pred = rf_regressor.predict(X_scenario)
    mean_usage_rate = np.mean(y_scenario_pred)
    
    if mean_usage_rate > best_usage_rate:
        best_discount_rate = discount_rate
        best_usage_rate = mean_usage_rate

print(f"The optimal discount rate is: {best_discount_rate:.2f}")

이런 식으로 랜덤포레스트 회귀모델을 생성해볼 수 있습니다.

이후에는 일반 선형회귀 뿐 아니라 다른 모델도 살펴보면서 실제로 어떻게 최적 할인율을 구할 수 있는지 구체적인 글을 작성해보도록 하겠습니다.


Reference.

파이썬 머신러닝 완벽 가이드 - 권철민 지음(위키북스)

0개의 댓글