Intro

지난 포스트에서 서울 지역별 원룸 면적과 전, 월세 분포를 살펴보았다.
이번 포스트에서는 이러한 정보를 토대로 ML기반 모델을 만들어서 좋은 방을 찾는데 활용할 것이다. 먼저 전세가격을 예측하는 모델을 만들고, 실제 매물의 전세가격이 모델이 예측한 가격보다 낮으면 해당 매물은 조건에 비해 저렴한 매물이라고 할 수 있다.
쉽게 설명하면 회기역 근처에 위치하고, 지어진지 10년 된 5평정도의 원룸 전세가는 평균적으로 x만원인데(모델이 예측하는 값) 특정 매물의 가격이 이 가격보다 현저히 낮다면 좋은 조건의 매물이라고 추측할 수 있다.
물론 이러한 추론을 하기위해서는 몇가지 전제가 존재한다(모델의 성능이 괜찮아야하고, 전세가에 큰 영향을 미치는 변수들이 모두 모델 학습 feature에 포함되어야하고, 데이터에 허위매물이 없어야하는 등).
이번 포스트에서는 이러한 전제들을 모두 충족시키는 완벽한 모델을 만드는 것을 목적으로 하기보다는, 좋은 방을 구하기위한 수단으로 데이터 모델링을 활용하는 가이드라인 정도를 제시하는것을 목표로 하고자 한다.

전처리

  • 사용데이터 : 22년12월1일 기준 직방 원룸 매물 데이터. 9월25일기준 데이터는 코어닷투데이에 업로드 되어있음
import pandas as pd
from sklearn.metrics import mean_squared_error, r2_score
from sklearn.model_selection import KFold
from sklearn.model_selection import train_test_split
import lightgbm as lgbm

data_date = 221201  # or 220925
data = pd.read_csv(f'data_preprocessed/room_info_{data_date}.csv')
charter_info = data[data['sales_type'] == '전세'].reset_index(drop=True)
charter_info = charter_info[charter_info['보증금액']<= 50000].reset_index(drop=True)  # 이상치 제거

모델 생성

  • 모델은 LightGBM사용
  • 사용변수는 전용면적, 사용승인년도(건축년도와 유사), 위치와 고도값, 반지하 여부
  • 위치와 고도값은 전세가와 linear한 관계가 있는게 아니기 때문에(강남, 여의도 등 특정 구역이 비싼것이지 서쪽으로 혹은 남쪽으로갈수록 비싼경향이 있는게 아님) 회귀분석과 같은 선형모델이 아니라 neural network, tree based model등 비선형 모델을 사용해야함.
train_cols = ['전용면적_m2', 'approve_year', 'random_lat', 'random_long', 'is_underground']
X = charter_info[train_cols]
y = charter_info['보증금액']
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42, test_size=0.2)
model = lgbm.LGBMRegressor()
model.fit(X_train, y_train);
pred = model.predict(X_test)
r2_score(y_test, pred)  # test set의 r-square값은 0.765정도로 어느정도 괜찮은 모델이라고 할 수 있음
  • 위도와 고도값을 뺀 모델의 r-square값은 0.64정도
  • 사용승인년도를 뺀 모델의 r-square값도 0.64정도
  • 전용면적을 뺀 모델의 r-square값은 0.43정도로 전용면적이 확실히 전세가에 큰 영향을 미침을 알 수 있음.

    예측

  • 구하고자 하는 동을 기준으로 매물 검색
# 전체 데이터셋을 이용해 모델 다시 생성
model = lgbm.LGBMRegressor()
model.fit(X, y);
charter_info_pred = charter_info.copy()
charter_info_pred['pred'] = model.predict(X)
charter_info_pred['score'] = charter_info_pred['pred'] - charter_info_pred['보증금액']  # 높을수록 좋음
def select_dong(df, wide=[], narrow=[]):
    result = pd.DataFrame()
    for i in wide:
        result = pd.concat([result, df[df['local3'].str.contains(i)]])
    for i in narrow:
        result = pd.concat([result, df[df['local3'] == i]])
    result = result.reset_index(drop=True)
    return result
		
df = select_dong(charter_info_pred, ['문래', '당산', '망원'])

  • 위처럼 좋은 조건의 방인지를 score(예측가-실제전세가)를 통해서 어느정도 파악이 가능하다.

결론

  • 실제로 필자가 방을 구할 때 위 모델을 사용해봤는데 설정한 조건(보증금액 상한, 위치)에서 좋은 score값을 가지는 매물들은 그저그런 오피스텔 원룸 매물들이었고, 그다지 유용하지는 않았다.
  • 블로그를 쓰다 보니 residence_type이라는 feature도 모델성능에 긍정적인 영향을 미칠것 이라고 생각된다.
  • 이러한 모델은 좋은매물을 찾는것 뿐 아니라 허위매물탐색 등에도 활용될 수 있을것이라고 생각된다.