해커톤) 부동산 허위매물 분류

최광일·2025년 2월 10일
post-thumbnail

점수: 0.87095점 (f1-macro), 전체 소스코드: Github

부동산 허위매물 분류 해커톤

해커톤에서는 부동산 데이터와 AI 기술을 활용하여 허위매물을 분류하는 AI 알고리즘을 개발하는 것을 목표로 합니다.

해커톤에서 제공하는 데이터는 아래와 같습니다.

ID매물확인방식보증금월세전용면적해당층...중개사무소게재일허위매물여부
1현장확인402500000.0470000NaNNaN...t93Nt6I2I02024-10-090
2현장확인170500000.0200000NaN3...q39iV5J4E62024-12-260
3전화확인114000000.0380000NaN2...b03oE4G3F62024-11-280
4현장확인163500000.03000036.33...G52Iz8V2B92024-11-260
5현장확인346000000.0530000NaN3...N45gM0M7R02024-06-251
..............................

데이터를 확인해보니, 부동산 매물별로 특징이 다르며, 허위매물여부를 확인할 수 있습니다.

어떤 특징을 가진 부동산 매물을 허위매물로 분류할 수 있을까요?

AI 모델은 대량의 데이터를 입력받아 패턴을 학습하여 주어진 문제를 해결할 수 있도록 합니다.

하지만, 데이터를 그냥 입력하면 알아서 해결해 주는것이 아니라, 문제 해결에 중요한 데이터들을 사람이 파악하여 컴퓨터가 잘 이해할 수 있도록 제공하는 것이 중요합니다.

따라서, 앞으로 다음의 순서로 허위매물을 분류하는 모델을 개발해보겠습니다.

  • 1 데이터 분석
  • 2 데이터 전처리
  • 3 피쳐 엔지니어링
  • 4 모델 엔지니어링

1 데이터 분석


먼저, 데이터를 요약해보면 다음과 같습니다.

import pandas as pd

df = pd.read_csv('train.csv')

# 데이터 요약 정보 확인
df.info()

# 전체 데이터 개수 확인
len(df)

# 중복 데이터 개수 확인
df.duplicated().sum()

# 결측 데이터 개수 확인
df.isna().sum()

# 불필요 데이터 개수 확인
for column in df.columns:
	# 칼럼 별 unique 종류 개수 확인
    print(column, len(df[column].unique()))
    
# 숫자형 칼럼 개수 확인
list_numerical_columns = list(df.select_dtypes(include=['int', 'float']).columns)
print('numerical', len(list_numerical_columns), list_numerical_columns)

# 범주형 칼럼 개수 확인
list_categorical_columns = list(df.select_dtypes(include=['object']).columns)
print('categorical', len(list_categorical_columns), list_categorical_columns)

# 타겟 데이터 개수 확인
target_column = '허위매물여부'
df[target_column].value_counts()
  • 전체 데이터 개수: 2452개
  • 중복 데이터 개수: 0개
  • 결측 데이터 개수: 전용면적(787개), 총주차대수(696개), 해당층(229개), ...
  • 불필요 데이터 개수: 1개 (ID)
  • 숫자형 칼럼 개수: 9개 (보증금, 월세, 전용면적, 총층, ...)
  • 범주형 칼럼 개수: 6개 (매물확인방식, 중개사무소, 게재일, ...)
  • 타겟 데이터 개수: 298개 (12%가 허위매물)

다음으로, 요약한 데이터들을 시각화를 통해 자세히 분석해보겠습니다.

  • 1-1 타겟 데이터 분석
  • 1-2 범주형 데이터 분석
  • 1-3 숫자형 데이터 분석
  • 1-4 결측 데이터 분석

1-1 타겟 데이터 분석

전체 매물 중 허위매물 개수가 298개로 불균형함을 확인할 수 있습니다.

1-2 범주형 데이터 분석

범주형 칼럼은 6개가 있었습니다.

  • 매물확인방식, 뱡향, 주차가능여부, 중개사무소, 제공플랫폼, 게재일

각 칼럼별 숫자 분포와 비율 분포를 시각화해서 확인해보겠습니다.

그래프를 통해 아래와 같이 확인해볼 수 있었습니다.

  • 매물확인방식
    • 현장확인 매물이 가장 많지만, 각 확인방식의 허위매물 비율은 비슷함
  • 뱡향
    • 남향과 동향의 매물이 가장 많지만, 북향과 서향의 허위매물비율이 높음
  • 주차가능여부
    • 주차 가능과 불가능의 허위매물 비율이 비슷함
  • 중개사무소
    • 중개사무소의 개수가 많아서 그래프 확인이 힘듦
  • 제공플랫폼
    • A > B > C 플랫폼 순으로 매물개수가 많지만, 허위매물 비율은 전부 비슷함
  • 게재일
    • 게재일의 개수가 많아서 그래프 확인히 힘듬

중개사무소와 게재일은 종류가 많아서 다음과 같이 처리 후 시각화를 진행하겠습니다.

  • 중개사무소
    • 총 276개의 중개사무소 존재
    • -> 매물 개수가 많은 상위 15개의 중개사무소 확인
  • 게재일
    • 일별 약 500개의 게재일 존재
    • -> 월별 매물 개수 및 비율 확인

처리 후 시각화 해보니 다음과 같이 확인해 볼 수 있었습니다.

  • 중개사무소
    • 특정 중개사무소 (G52lz8V2B9)만 매물 개수가 800개이며, 허위매물이 없다
    • 각 중개사무소의 허위매물 비율은 비슷하다.
  • 게재일
    • 특정 기간 (2024-08~2024-12)에 매물 개수가 많다
    • 특정 기간 (2024-04~2024-7)에 허위매물 개수가 많다

1-3 숫자형 데이터 분석

숫자형 칼럼은 9개가 있었습니다.

  • 보증금, 월세, 전용면적, 해당층, 총층, 방수, 욕실수, 총주차대수, 관리비

각 칼럼별 숫자 분포와 이상치값 존재 여부를 시각화해서 확인해보겠습니다.

그래프를 통해 아래와 같이 확인해볼 수 있었습니다.

  • 보증금
    • 전체 보증금 분포에서 허위매물 개수가 비슷함
    • 사분범위(IQR) 기준으로 이상치가 존재함
  • 월세
    • 전체 월세 분포에서 허위매물 개수가 비슷함
  • 전용면적
    • 전용면적이 낮은 매물과 허위매물이 많음
  • 해당층
    • 해당층이 낮은 매물과 허위매물이 많음
    • 사분범위(IQR) 기준으로 이상치가 존재함
  • 총층
    • 총층이 낮은 매물과 허위매물이 많음
    • 사분범위(IQR) 기준으로 이상치가 존재함
  • 방수
    • 방수가 1인 매물이 많고, 방수가 2인 허위매물 비율이 높음
  • 욕실수
    • 욕실수는 대부분 1임
  • 총주차대수
    • 이상치로 인해 분포 확인이 힘듦
  • 관리비
    • 이상치로 인해 분포 확인이 힘듦

총주차대수와 관리비는 이상치로 인해 분포 확인이 힘들기 때문에 로그스케일로 변환 후 확인해주었습니다.

  • 총주차대수
    • 특이사항 없음
  • 관리비
    • 특이사항 없음

다음으로, 숫자형 데이터들이 정규성을 띄는지 Q-Q plot을 통해 확인해봤습니다.
Q-Q plot은 대각선 위에 데이터가 위치해있으면 정규분포를 띈다고 이해할 수 있습니다.

그래프를 확인해보니, 각 숫자형 데이터들은 모두 정규분포를 띄지 않음을 확인할 수 있습니다.

참고: Q-Q Plot 직관적으로 이해하기

다음으로, 숫자형 데이터들의 상관관계를 시각화해보았습니다.

앞서 확인한 것 처럼 숫자형 데이터들은 모두 정규성을 만족하지 않으므로, 스피어만 상관계수를 통해 확인해보았습니다.

그래프를 통해 각 숫자형 칼럼간의 어느정도 상관관계를 확인할 수 있었습니다.

  • 0.68: 총층 - 해당층
  • 0.49: 총층 - 총주차대수
  • 0.35: 전용면적 - 방수

총층이 높을수록, 해당층이 높거나 전용면적이 클수로 방수가 넓다는 것으로 이해할 수 있습니다.

마지막으로, 숫자형 데이터들의 다중공선성을 확인해보았습니다.

다중공선성은 하나의 독립변수가 다른 여러 개의 독립변수들로 잘 예측되는 경우로, 독립 변수(특징)들 간의 상관관계가 높아 모델 성능에 영향을 줄 수 있는 현상을 의미합니다.

다중공선성과 상관관계의 차이는 아래와 같습니다

  • 상관관계: 두 변수 간의 선형 관계를 나타내는 척도 (-1 ~ 1)
  • 다중공선성: 여러 독립 변수 간 높은 상관관계로 인해 회귀 분석의 문제를 유발

각 피쳐별 다중공선성을 확인해보면 다음과 같습니다.

VIF(Variance Inflation Factor)는 각 변수의 다중공선성을 수치화한 값입니다.

  • VIF 값이 높을수록 다중공선성이 심함.
  • VIF > 10 → 다중공선성 문제 가능성이 높음 (제거 고려)
  • VIF > 5 → 다중공선성이 의심됨 (주의 필요)
FeatureVIF해석
보증금2.64다중공선성 문제 없음 ✅
월세4.15다중공선성 문제 없음 ✅
전용면적14.55다중공선성이 높음 ❌
해당층5.49다중공선성이 의심됨 ⚠️
총층7.92다중공선성이 의심됨 ⚠️
방수11.30다중공선성이 높음 ❌
욕실수21.15다중공선성이 매우 높음 ❌
총주차대수1.77다중공선성 문제 없음 ✅
관리비2.04다중공선성 문제 없음 ✅
  • 전용면적, 해당층, 총층
    • 상관관계가 높아서 VIF가 높다고 이해
  • 방수, 욕실수
    • 값이 1,2로 제한된 값을 가지기 때문에 높다고 이해

하지만, 다중공선성이 높다고 무조건 제거하는 것은 아닙니다.

  • 분류 및 트리 기반 모델에서는 고려할 필요가 없음
  • 도메인 지식을 이용해 변수간의 관계 확인이 필요

참고: 다중공선성은 생각하지 마라

1-4 결측 데이터 분석

결측 데이터 개수는 다음과 같았습니다.

  • 전용면적(787개), 총주차대수(696개), 해당층(229개), 총층(16개), 방수(16개), 욕실수(16개)

결측 데이터의 매물개수를 시각화해보았습니다.

그래프를 통해 다음과 같이 확인할 수 있었습니다.

  • 각 결측 데이터에 허위매물 개수가 일정 비율 존재한다.

2 데이터 전처리


데이터 분석을 통해 다음과 같이 확인할 수 있었습니다.

  • 결측 데이터 존재
    • 전용면적(787개), 총주차대수(696개), 해당층(229개), 총층(16개), 방수(16개), 욕실수(16개)
  • 결측 데이터는 전부 숫자형 데이터임

따라서, 결측치를 회귀모델을 사용하여 예측 후 대치하도록 했습니다.

2-1 결측치 예측 및 대치

결측치 대치 전략은 다음과 같습니다.

  • 1 결측 데이터가 많은 칼럼부터 모델 학습, 예측 후 대치한다.
  • 2 대치하려는 칼럼 외 결측치는 평균값으로 임의로 채워넣는다.
  • 3 회귀모델(RandomForestRegressor)을 사용하여 결측치를 예측한다.
  • 4 회귀모델 평가 지표를 사용하여 결측치 대치를 평가한다.
  • 5 결측치 대치 전, 후 데이터 분포를 비교한다.

아래는 회귀모델을 사용하여 각 결측 데이터를 순회하며 결측치를 대치하는 코드입니다.

import time
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.ensemble import RandomForestRegressor
from sklearn.impute import SimpleImputer
from sklearn.model_selection import cross_val_predict
from sklearn.metrics import mean_squared_error, mean_absolute_error

# 시작 시간 기록
start_time = time.time()

# 결측값이 있는 칼럼 리스트
missing_columns = ['전용면적', '총주차대수', '해당층', '욕실수', '총층', '방수']

# 평가 지표 저장용
results = {}

# 기본 RandomForestRegressor 모델 정의
rf = RandomForestRegressor(
    n_estimators=100,
    criterion='squared_error',
    max_depth=None,
    random_state=42
)

# 각 칼럼에 대해 결측값 대체
for column in missing_columns:
    print(f"ㅡㅡㅡㅡ{column} 결측치 대치중ㅡㅡㅡㅡ")
    print(df.isna().sum())

    # 결측값을 가진 데이터와 없는 데이터 분리
    X = df[list_numerical_columns].drop(columns=[column])
    y = df[column]

    # 대치할 칼럼 외 칼럼들의 결측값을 평균으로 대체
    fill_columns = missing_columns.copy()
    fill_columns.remove(column)
    for fill_column in fill_columns:
        X[fill_column] = SimpleImputer(strategy='mean').fit_transform(X[[fill_column]])

    # 결측값이 없는 데이터만 학습에 사용
    X_train = X[~y.isna()]
    y_train = y[~y.isna()]

    # 결측값이 있는 데이터만 예측에 사용
    X_test = X[y.isna()]

    # 모델 학습
    rf.fit(X_train, y_train)

    # 교차 검증 예측 값 얻기 (교차 검증은 X_train에 대해서만 예측)
    y_pred = cross_val_predict(rf, X_train, y_train, cv=3)

    # RMSE와 MAE 계산
    rmse = np.sqrt(mean_squared_error(y_train, y_pred))
    mae = mean_absolute_error(y_train, y_pred)

    # 결과 저장
    results[column] = {
        'rmse': rmse,
        'mae': mae,
        'model': rf
    }

    # 결측값 예측 (여기서 예측값을 채워야 함)
    y_pred_test = rf.predict(X_test)

    # 결측값 채우기
    df.loc[df[column].isnull(), column] = y_pred_test

# 결과 출력
print(f"ㅡㅡㅡㅡ결측치 대치 완료ㅡㅡㅡㅡ")
print(df.isna().sum())

# 끝 시간 기록
end_time = time.time()

# 학습 시간 계산
training_time = end_time - start_time
print(f"모델 학습 시간: {training_time:.2f} 초")

# 모델별 결과 요약을 DataFrame으로 변환
result_df_1 = pd.DataFrame.from_dict(results, orient='index')
result_df_1 = result_df_1[['rmse', 'mae']]

2-2 결측치 대치 평가

앞서 이야기한 회귀 모델 평가 지표는 다음의 값을 사용하였습니다.

  • RMSE (Root Mean Squared Error): 평균 제곱 오차 제곱근
  • MAE (Mean Absolute Error): 평균 절대 오차

두 값은 모델의 예측값과 실제값 간의 차이를 측정한 값이며 낮을수록 예측을 잘했다고 이해할 수 있습니다.

각 숫자형 데이터 결측치 대치 후 통계값과 지표값을 확인하면 다음과 같습니다.

항목최소값평균값중앙값표준편차최대값RMSEMAE
전용면적17.527.66101626.5757.59845349.977.0084105.567027
총주차대수1.016.9570557.44026.529787590.0023.11082211.677323
해당층1.04.9092334.0003.46309621.002.5692911.648115
욕실수1.01.0342581.0000.1819282.000.1484970.041623
총층2.08.0508936.0004.90868421.003.1925402.123030
방수1.01.3760321.0000.4840962.000.2739230.157989

데이터가 정규분포를 따르지는 않지만, 각 칼럼의 표준편차보다 오차값인 MRSE, MAE 값이 낮아서 결측치 대측이 어느정도 되었다고 판단하였습니다.

추가로, 결측치 대치 전과 후의 데이터 분포를 시각화하여 결측치 대치에 문제가 없는지 확인해보았습니다.

그래프를 통해 다음과 같이 확인할 수 있었습니다.

  • 결측치 대치 전과 후의 데이터 분포가 유사

3 피쳐 엔지니어링


피처 엔지니어링은 데이터를 분석해서 중요한 패턴을 찾아, 모델이 더 잘 이해할 수 있도록 가공하는 과정입니다.

데이터를 그냥 모델에 넣으면 모델이 중요한 패턴을 잘 찾기 어렵기 때문에, 데이터 분석을 통해 중요한 패턴을 발견하고, 모델이 잘 이해하도록 가공해야 합니다.

3-1 피쳐 중요도 확인

먼저, 어떤 피쳐가 중요한지 간단히 알아보기 위해 아래와 같이 기본 모델을 학습시켜보았습니

model = RandomForestClassifier(
    n_estimators=100,
    criterion='gini',
    max_depth=None,
    random_state=42
)

model.fit(x, y)

학습된 모델의 피쳐 중요도를 확인하기 위해 아래의 방법을 사용했습니다.

  • Permutation Importace
  • SHAP Value

Permutation Importace의 개념은 아래와 같습니다.

  • 모델의 특정 특성(Feature) 을 랜덤하게 섞어서(Shuffle) 성능(F1, Accuracy 등)이 얼마나 감소하는지를 측정하는 방법
  • 특정 특성이 중요하다면, 해당 특성을 랜덤하게 섞으면 모델 성능이 크게 하락
  • 특정 특성이 덜 중요하다면, 랜덤하게 섞어도 성능이 거의 변하지 않음

결과값을 확인해보니, 게재일과 중개사무소 칼럼의 값을 랜덤하게 변할때 모델 성능이 크게 하락했음을 알 수 있었고, 모델에 영향도가 높다고 이해할 수 있습니다.

SHAP Value의 개념은 아래와 같습니다.

  • 게임 이론(Game Theory)의 Shapley Value를 기반으로, 각 특성이 예측값에 기여한 정도를 계산
  • 특정 샘플이 예측 결과를 만들기 위해 개별 특성이 얼마나 기여했는지를 확인 가능
  • 특성별 기여도(양수/음수)를 개별 샘플 단위로 측정 가능

결과값을 확인해보니, 위와 같이 게재일과 중개사무소가 예측 결과에 기여도가 높았음을 알 수 있었고, 인코딩된 값의 크기에 따라 양/음의 기여도를 미쳤음을 이해할 수 있습니다.

3-2 인사이트 활용

피쳐 중요도를 확인해보니 중개사무소와 게재일 피쳐가 모델에 큰 영향을 주었다는 것을 알았습니다.

도메인 관점에서도 생각해보면 허위매물은 각 중개사무소가 등록하는 것이니 어쩌면 당연한 것 같습니다.

중개사무소와 게재일 피쳐에 대해 이전에 데이터 분석을 통해 다음의 주요 인사이트를 확인할 수 있었습니다.

  • 중개사무소
    • 총 276개의 중개사무소 존재
    • 특정 중개사무소 (G52lz8V2B9)만 매물 개수가 800개이며, 허위매물이 없다
    • 각 중개사무소의 허위매물 비율은 비슷하다.
  • 게재일
    • 특정 기간 (2024-08~2024-12)에 매물 개수가 많다
    • 특정 기간 (2024-04~2024-7)에 허위매물 개수가 많다

위의 피쳐들의 인사이트들을 모델에게 다음과 같이 알려주고싶었습니다.

  • 중개사무소
    • 특정 중개사무소 (G52lz8V2B9)를 편향해서 학습하지마라
    • 각 중개사무소마다 전체 매물과 허위매물 개수가 다르다.
  • 게재일
    • 특정 기간에 전체매물 또는 허위매물 개수가 많다.

따라서 아래와 같이 다양한 방법으로 모델에게 어떻게 알려줘야할지 고민해보았습니다.

  • 중개사무소 기준으로 오버샘플링하여 각 중개사무소의 데이터 개수를 맞춰볼까?
  • 중개사무소별 매물 개수와 허위매물비율을 파생피쳐로 만들어볼까?
  • 중개사무소 기준으로 데이터를 클러스터링하여 비슷한 중개사무소끼리 묶어볼까?
  • 허위매물 위험 점수라는 파생 피쳐를 만들어볼까?
  • 허위매물 위험 기간이라는 파생 피쳐를 만들어볼까?
  • 게재일별 매물 개수와 허위매물비율을 파생피쳐로 만들어볼까?

위와같은 다양한 가설을 적용해보면서 가장 점수가 높았던 방법은 아래와 같았습니다.

  • 중개사무소
    • 1 중개사무소별 군집 생성
    • 2 중개사무소 군집 별 허위매물 비율 파생 피쳐 생성
  • 게재일
    • 1 일별 데이터를 월별 데이터로 변환
    • 2 월별 허위매물 비율을 파생 피쳐 생성

3-3 중개사무소 피쳐 가공

중개사무소별 숫자형 데이터의 평균값을 시각화해보면 다음과 같습니다.

각 숫자형 데이터의 평균값이 중개사무소별로 다르게 분포해있음을 확인할 수 있습니다.

따라서, 분포해 있는 각 중개사무소를 KMeans 알고리즘으로 아래와 같이 클러스터링 하고자했습니다.

KMeans 클러스터링은 거리 기반 알고리즘이므로, 아래의 특징이 클러스터링에 영향을 미칠 수있습니다.

  • 피쳐의 스케일: 변수 간 단위 차이가 클 경우 특정 변수가 군집화에 더 큰 영향
  • 다중공선성: 상관관계가 높은 변수가 있으면 해당변수가 군집화에 더 큰 영향

따라서, 먼저 중개사무소별 각 숫자형 데이터의 평균값간의 상관계수와 다중공선성 여부를 확인해보았습니다.

먼저, Q-Q Plot 그래프를 확인해보니, 각 숫자형 데이터들은 모두 정규분포를 띄지 않음을 확인할 수 있습니다.

중개사무소별 각 숫자형 데이터의 평균값은 모두 정규성을 만족하지 않으므로, 스피어만 상관계수를 통해 확인해보았습니다.

그래프를 통해 각 숫자형 칼럼간의 어느정도 상관관계를 확인할 수 있었습니다.

  • 0.85: 평균 총층 - 평균 층수
  • 0.51: 평균 총층 - 평균 총주차대수
  • 0.49: 평균 총층 - 평균 관리비

다음으로, 다중공선선을 확인해본 결과 다음과 같았습니다.

FeatureVIF
허위매물_비율1.587806
총_매물수1.070661
평균_보증금4.732560
평균_월세6.920095
평균_전용면적10.812211
평균_층수28.068860
평균_총층37.807254
평균_총주차대수3.320291
평균_관리비3.874353

상관관계에서 확인해본 것 처럼 아래 값들의 VIF가 높은것을 확인할 수 있었습니다.

  • 평균_총층: 37.807254
  • 평균_층수: 28.068860
  • 평균_전용면적: 10.812211

따라서, 하나씩 제거해 나가면서 휴리스틱하게 클러스터링 할 피쳐들을 선별하여 다중공선성을 낮추었습니다.

FeatureVIF
허위매물_비율1.564794
총_매물수1.047053
평균_보증금4.268984
평균_월세4.461320
평균_층수6.342668
평균_관리비3.612628

다음으로, 선별한 피쳐들의 단위를 맞춰주기 위해 스케일링을 진행해준다음

features = ['허위매물_비율', '총_매물수', '평균_보증금', '평균_월세', '평균_층수', '평균_관리비']

# 데이터 스케일링
scaler = StandardScaler()
scaled_features = scaler.fit_transform(df[features])

최적의 군집 개수를 갖는 군집을 생성하기 위해 엘보우 그래프를 확인해보았습니다.

엘보우 그래프는 위와 같이 각 클러스터 내 각 데이터 포인트가 클러스터의 중심(centroid)에서 얼마나 떨어져 있는지를 나타내는 값의 제곱합으로, 클러스터링이 진행되면서 해당 값은 작아지며, 값이 급격하게 작아질때마다 최적의 클러스터가 형성됨을 이해할 수 있습니다.

엘보우 그래프 확인 결과, 클러스터 개수가 4개 이후 부터 그래프가 완만해 지기 때문에 클러스터를 3개로 지정하여 클러스터링하였습니다.

그 다음, 각 중개사무소가 어떤 클러스터에 속해있는지 확인해기 위해 PCA를 통해 차원을 2차원으로 축소하여 시각화해보았습니다.

그래프 확인 결과, 군집이 어느정도 생성되어 있음을 확인하였습니다.

그 다음, 클러스터 별 중개사무소의 총 개수와 unique 개수를 살펴보았습니다.

그래프 확인 결과, 클러스터 2는 데이터 분석에서 확인했던 특정 중개사무소 (G52lz8V2B9)임을 알 수 있었고, 각 클러스터의 특징이 잘 드러난 것을 확인할 수 있었습니다.

따라서 아래와 같이 데이터에 다음과 같은 피쳐들을 추가해주었습니다.

  • 중개사무소_cluster
  • 중개사무소_cluster_size
  • 중개사무소_cluster_fraud_rate
ID...중개사무소중개사무소_cluster중개사무소_cluster_fraud_rate중개사무소_cluster_size
......t93Nt6I2I000.2043011023
......q39iV5J4E610.141270630
......b03oE4G3F610.141270630
......G52Iz8V2B920.000000799
......N45gM0M7R000.2043011023

3-4 게재일 피쳐 가공

게재일은 일별 데이터보다 월별 데이터를 통해 트렌드 확인이 용이하다고 판단하였습니다.

따라서 아래와 같이 데이터 변환 후 다음과 같은 피쳐들을 추가해주었습니다.

  • 게재일: YYYY-MM-DD -> YYYY-MM 변환
  • 게재일_size
  • 게재일_fraud_rate
ID...게재일게재일_fraud_rate게재일_size
------2024100.008596349
------2024120.000000240
------2024110.003165316

3-5 나머지 범주형 피쳐 가공

아래의 나머지 범주형 피쳐는 특이사항이 없어서, Label Encoding을 진행하였습니다.

  • 매물확인방식, 뱡향, 주차가능여부, 제공플랫폼
le = LabelEncoder()

# Label Encoding 적용 열
label_encode_cols = ['제공플랫폼','방향', '주차가능여부', '매물확인방식']

for col in label_encode_cols:
    df[col] = le.fit_transform(df[col].astype(str))

3-6 피쳐 중요도 재확인

먼저 Permutation Importace의 결과는 아래와 같았습니다.

  • 중개사무소와 게재일 관련하여 추가된 파생피쳐들의 중요도가 어느정도 확인됨
  • 관리비와 월세의 중요도가 갑자기 높아짐

Shap Value의 결과는 아래와 같았습니다.

  • 중개사무소와 게재일 관련하여 추가된 파생피쳐들의 중요도가 어느정도 확인됨

4 모델 엔지니어링


4-1 모델 실험

모델 엔지니어링을 진행한 항목 및 종류는 아래와 같습니다.

  • 1 타겟 데이터 불균형 처리
    • base (처리x)
    • Sampling (SMOTE, SMOTEEN)
    • Cost-Sensitive-Leaning
  • 2 모델 종류
    • RandomForestClassifier
    • LGBMClassifier
    • XGBClassifier
  • 3 하이퍼 파라미터 최적화 방법
    • base (최적화x)
    • RandomSearch
    • BasianSearch
    • Optuna-TPESampler

각 항목의 종류별로 48(=4 x 3 x 4)번의 실험을 진행한 결과 최적의 모델은 다음과 같았습니다.

  • 타겟 데이터 불균형 처리
    • base (처리x)
  • 모델 종류
    • RandomForestClassifier
  • 하이퍼 파라미터 최적화 방법
    • base (최적화x)

한마디로 기본 RandomForestClassifier 모델의 점수가 가장 높았습니다.

아래는 기본 RandomForestClassifier 모델 학습 및 예측 코드입니다.

# 기본 RandomForestClassifier 모델 학습 코드

df_train = pd.read_csv("train.csv")

Y = df[target_column]
X = df.drop([target_column], axis=1)

# 랜덤 포레스트 모델 설정
model = RandomForestClassifier(
    n_estimators=100,
    criterion='gini',
    max_depth=None,
    random_state=42,
)

# 모델 학습
model.fit(X, Y)

# 허위매물 분류 예측
df_test = pd.read_csv("test.csv")
model.predict(df_test)

아래와 같이 허위매물여부를 모르는 부동산 매물 데이터(df_test)를 넣고 predict를 해주면 모델이 학습한 결과를 바탕으로 허위매물여부를 분류하게됩니다.

ID매물확인방식보증금월세전용면적해당층...중개사무소게재일
1현장확인402500000.047000017.56...t93Nt6I2I02024-10-09
2현장확인170500000.020000024.43...q39iV5J4E62024-12-26
3전화확인114000000.038000052.22...b03oE4G3F62024-11-28
4현장확인163500000.03000036.33...G52Iz8V2B92024-11-26
5현장확인346000000.053000012.23...N45gM0M7R02024-06-25
...........................

4-2 모델 해석

아래의 세가지 방법으로 모델을 평가해보겠습니다.

  • 1 Confusion Matrix
  • 2 Classification Report
  • 3 ROC-AUC

첫번째로, Confusion Matrix는 아래와 같으며, 개념과 해석 방법은 다음과 같습니다.

  • 개념: 모델이 예측한 결과와 실제 정답을 비교하여 만든 행렬(표)
    • TP (True Positive): 실제 양성(1) → 모델도 양성(1) 으로 예측
    • TN (True Negative): 실제 음성(0) → 모델도 음성(0) 으로 예측
    • FP (False Positive): 실제 음성(0) → 모델이 양성(1) 으로 잘못 예측 (Type I Error)
    • FN (False Negative): 실제 양성(1) → 모델이 음성(0) 으로 잘못 예측 (Type II Error)
  • 해석 방법:
    • FP가 많으면 Precision이 낮아짐
    • FN이 많으면 Recall이 낮아짐
    • 데이터가 불균형할 경우 Accuracy보다는 Precision, Recall, F1-score를 보는 게 중요

학습한 모델의 Confusion Matrix는 다음과 같습니다.

허위매물이 1클래스이기 때문에 전체 데이터 2452개에 대해 다음과 같이 해석이 가능합니다.

  • TP 244개: 허위매물인 매물을 허위매물로 잘 예측한 데이터가 244개
  • TN 2109개: 허위매물이 아닌 매물을 허위매물이 아니라고 잘 예측한 데이터가 2109개
  • FP 45개: 허위매물이 아닌 매물을 허위매물로 잘못 예측한 데이터가 54개
  • FN 54개: 허위매물인 매물을 허위매물이 아니라고 잘못 예측한 데이터가 45개

두번째로, Classification Report는 분류 모델의 성능을 자세히 평가하는 리포트입니다.

  • 개념
    • 분류 모델의 성능을 자세히 평가하는 리포트
    • precision, recall, f1-score, support(샘플 개수)
  • 해석 방법
    • Precision(정밀도): FP(거짓 양성)를 얼마나 줄였는지
    • Recall(재현율): FN(거짓 음성)을 얼마나 줄였는지
    • F1-score: Precision과 Recall의 조화 평균
    • Support: 각 클래스별 샘플 개수

학습한 모델의 Classification Report는 다음과 같습니다.

ClassPrecisionRecallF1-scoreSupport
00.980.980.982154
10.840.820.83298
Accuracy0.962452
Macro Avg0.910.900.902452
Weighted Avg0.960.960.962452

해커톤의 평가 지표인 f1_macro 지표는 f1_score의 양성,음성 값의 평균으로 0.90임을 확인할 수 있습니다.

마지막으로, ROC-AUC는 정확한 양성(TP)과 잘못된 양성(FP)의 관계를 그래프로 표시한 것입니다.

  • 개념
    • 모델이 임계값을 바꿨을 때, 정확한 양성(TP)과 잘못된 양성(FP)의 관계를 그래프로 표시
    • x축 = False Positive Rate (FPR)
    • y축 = True Positive Rate (TPR, Recall)
    • AUC (Area Under Curve): 곡선 아래 면적
  • 해석 방법
    • AUC = 0.5 → 모델이 랜덤하게 예측
    • AUC = 0.7~0.8 → 준수한 성능
    • AUC = 0.8~0.9 → 좋은 성능
    • AUC = 0.9 이상 → 매우 좋은 성능
  • Confusion Matrix와의 차이점
    • Confusion Matrix는 고정된 임계값(threshold)에서 오차 분석
    • ROC AUC는 임계값을 변경하면서 전체적인 성능을 평가

학습한 모델의 ROC-AUC 그래프는 다음과 같습니다.

0.9725 값을 가진것으로 보아 각 클래스 예측이 양 극단에 위치하여 threshold 변경에 따라 TPR 변화가 크지 않음을 알 수 있습니다.

5 정리


각 단계별 해커톤 제출 점수는 아래와 같았습니다.

  • 데이터 전처리 전: 0.790점
  • 데이터 전처리 후: 0.807점
  • 피쳐 엔지니어링 후: 0.870점
  • 모델 엔지니어링 후: 0.870점

느낀점은 다음과 같습니다.

  • EDA를 통한 명확한 근거를 바탕으로 피쳐 엔지니어링을 진행하여 타겟 분류에 필요한 데이터를 모델에게 알려주는게 정말 중요하다.
  • 모델 엔지니어링은 블랙박스 영역이고 기도메타라고 느껴졌다. 데이터 특징에 맞는 모델 선별 및 하이퍼파라미터 역할에 대한 이해가 중요하다.

0개의 댓글