반응형

 

 

 

 

 

데이터 시각화 --> 인사이트 고안 --> 전처리 --> 모델 선정 및 학습

 

 

Visualization & Pre-processing : 공유된 코드 이해에 주안점을 둠

Analysis : 나름의 인사이트를 적용해보고자 함

Model : 인사이트의 직관적 적용을 파악하고자 Linear Regression(선형 회귀) 모델 사용

 

 

참고한 코드 : https://dacon.io/competitions/official/235745/codeshare/3017?page=1&dtype=recent

대회 3위를 수상하신 'MIND' 님께서 데이콘에 공유해주신 코드로 공부했다.

대부분 코드를 참고했지만, 특히 전처리 부분은 모든 부분을 활용했다.

 

 

 

 

 

 

 

 

 

대회 개요

아파트 신축 단지의 주차 수요를 예측하는 모델을 작성한다.

현행되는 인력조사로 과대 또는 과소 산정의 가능성이 생겨, 학습을 통한 모델로 정확한 예측을 가능케 하고자 함.

 

 

 

 

 

준비

# 폰트 변경
from matplotlib import pyplot as plt
plt.rc('font', family='NanumBarunGothic') 
 
# Colab 환경에서 네이버 나눔 폰트 설치
## 설치 후 상단에서 '런타임 > 런타임 다시 시작 > 이전 import 재실행'
!sudo apt-get install -y fonts-nanum
!sudo fc-cache -fv
!rm ~/.cache/matplotlib -rf
 

Matplotlib 그래프를 그리면 한글 폰트가 깨진다.

폰트 변경 코드를 사용하면 되는데,

구글 Colab은 sudo 명령으로 폰트를 설치해준 후, 런타임을 다시 시작해야 한다.

구글링 오지게 많이 했다.

 

 

 

 

 

데이터 시각화

 

 

 

 

import seaborn as sns
plt.figure(figsize=(12, 8))
sns.heatmap(train.corr(), annot=True, cmap="viridis")
plt.show()

 

 
스터디원이 그려주신 상관계수 히트맵

 

처음보는 라이브러리, 모듈이었다

근데 사실 숫자가 더 보기 편했다 (ㅎㅎ;)

 

corr_train = train.corr()
corr_train["등록차량수"].sort_values(ascending=False)
 

 

 

 

 

 

 

데이터 전처리

결측치 : 검색을 통해 채움 (공공임대상가의 공시 가격)

 

2차원 데이터 : 1차원으로 변환

하나의 단지에 여러 개의 전용면적 존재 --> 총전용면적, 평균전용면적 column으로 변환

하나의 단지에 여려 개의 임대료, 보증금 존재 --> 평균임대료, 평균임대보증금 column으로 변환

 

 

 

 

 

 

분석

'단지내주차면수', '임대료', '임대보증금', '총전용면적', '평균전용면적'과 목표값(등록차량수)의 상관계수가 높음.

 

임대료, 임대보증금, 전용면적과 등록차량수가 선형적으로 비례하지 않을 것이라고 판단했다.

예컨데, 24평에 살고 있는 가구와 48평에 살고 있는 가구가 약 2배의 평균등록차량수를 보이지는 않을 것이라고 생각했다.

 

오히려 많은 가구에 필수적인 1대의 차량을 기점으로 로그적인 증가에 가까울 것이라고 예상했다.

따라서 '임대료', '임대보증금', '총전용면적', '평균전용면적' 4개 컬럼을 로그변환하였다.

 

임대료, 임대보증금은 예상대로 로그 변환 후 더 높은 상관계수를 보였지만

평균전용면적, 총전용면적은 오히려 로그 변환 후 더 낮은 상관계수를 보였다.

 

따라서 임대료, 임대보증금만 로그 변환 후의 컬럼을 활용하여 선형 회귀 모델에 대입하기로 했다.

 

 

 

 

 

모델 학습

# 훈련 데이터 만들기
tmp_train = df_train[['등록차량수', '단지코드', 'n지역', 'n공급유형', '공가수', '지하철', '버스', '단지내주차면수', '총임대세대수', '평균전용면적', '총전용면적', 'log_평균임대보증금', 'log_평균임대료']]

# train_test_split으로 훈련, 테스트 세트 셔플
y_target = tmp_train['등록차량수']
X_data = tmp_train.drop(['단지코드', '등록차량수'], axis=1, inplace=False)

X_train, X_test, y_train, y_test = train_test_split(X_data, y_target, shuffle=False, random_state=42, test_size=0.1)

# 선형회귀 모델 훈련 및 지표 산출(R2 Score, MAE)
model = LinearRegression()
model.fit(X_train, y_train)

print(f'R2 Score : {r2_score(model.predict(X_test), y_test)}, MAE : {mean_absolute_error(model.predict(X_test), y_test)}')

# 3Fold 
from sklearn.model_selection import cross_val_score

mae_scores = cross_val_score(model, X_data, y_target, scoring='neg_mean_absolute_error', cv=3)
avg_mae = np.mean(mae_scores)
std_mae = np.std(mae_scores)

print('3Fold 개별 MAE score : ', mae_scores)
print('3Fold 평균 MAE : ', avg_mae)
print('3Fold 표준편차 MAE : ', std_mae)
 

예상한대로, 로그 변환한 컬럼을 사용한 모델의 점수(MAE)가 가장 좋게 나왔다.

(사실 데이터 크기가 작은 탓에 변환한 컬럼을 중복으로 추가한 점수가 가장 좋게 나왔으나, 결과 제출 시 점수는 그렇지 않았다.)

 

 

 

 

 

 

제출

# 다운로드를 원하는 모델 재실행 후 컬럼 가져오기 (등록차량수, 단지코드 제외)
submission['num'] = model.predict(df_test[['n지역', 'n공급유형', '공가수', '지하철', '버스', '단지내주차면수', '총임대세대수', '평균전용면적', '총전용면적', '평균임대보증금', '평균임대료', 'log_평균임대보증금', 'log_평균임대료']])
submission

# csv 파일로 저장
submission.to_csv("주차수요.csv", index = False)
 

 

 

 

Public 기준 약 112점

제출된 500여개 답안 중 300여등이다.

 

간단한 선형 회귀 모델로 나쁘지 않은 점수(?)가 나온 것은

절대적으로 좋은 전처리 코드를 빌려왔기 때문이지만, 로그 변환을 적용한 것도 대략 몇 점의 좋은 영향은 주었다.. ㅠ

 

 

 

 

 

 

 

스터디 피드백

선형회귀에는 많은 가정이 활용되는데, 해당 내용을 추가하면 좋을 것 같다.

--> 회귀 공부 마치고 다시 적용해보기

 

컬럼에 로그 변환한 인사이트가 좋았다.

--> 다른 모델에도 변환한 컬럼 적용해보기

 

stepwise model selection을 사용하면 사용할 컬럼을 지정하지 않아도, 가장 좋은 모델을 위한 컬럼 선택과 선형회귀 모델 파라미터를 결정해준다고 한다.

--> 해당 라이브러리 공부하고 적용해보기

 

 

 

 

 

 

총평

무지하게 어렵다.

 

 

 

 

 

 

 

 

 

 

 

반응형

+ Recent posts