주택 가격 예측 모델 구축(데이터 조회 및 결측치 처리)
주택 가격 예측 모델 구축을 위한 데이터 조회 및 결측치 처리 과제입니다.
주택 가격 예측 모델 구축(데이터 조회 및 결측치 처리)
과제 1번: 지도학습
주제: 주택 가격 예측 모델 구축
- 주어진 주택 데이터셋을 사용하여 주택 가격을 예측하는 회귀 모델을 구축한다.
컬럼별 설명
- CRIM: 타운별 1인당 범죄율.
- ZN: 25,000 평방피트 이상의 주거 구역 비율.
- INDUS: 비소매 상업 지역 비율.
- CHAS: 찰스강 인접 여부 (1: 강과 접함, 0: 접하지 않음).
- NOX: 대기 중 일산화질소 농도 (0.1 단위).
- RM: 주택 1가구당 평균 방 개수.
- AGE: 1940년 이전에 건설된 주택 비율.
- DIS: 5개의 보스턴 고용 중심지까지의 가중 거리.
- RAD: 고속도로 접근성 지수.
- TAX: 10,000달러당 재산세율.
- PTRATIO: 타운별 학생-교사 비율.
- B: 흑인 비율 (1000(Bk - 0.63)^2, 여기서 Bk는 흑인 인구 비율).
- LSTAT: 하위 계층 인구 비율.
- MEDV: 주택의 중앙값 (단위: $1000).
과제 가이드
- 데이터셋 탐색 및 전처리:
- 결측치 처리
- 이상치 탐지 및 제거
- 특징 선택
- 여러 회귀 모델 비교:
- 선형 회귀
- 의사결정나무
- 랜덤 포레스트 등
- 모델 성능 평가:
- 지표를 사용하여 모델 성능을 비교합니다.
- Mean Absolute Error (MAE): 예측값과 실제값의 절대 오차의 평균.
- Mean Squared Error (MSE): 예측값과 실제값의 제곱 오차의 평균.
- R² Score: 모델이 데이터의 변동성을 얼마나 설명하는지 나타내는 지표.
- 지표를 사용하여 모델 성능을 비교합니다.
- 결과 분석:
- 각 모델의 성능을 비교하고 최적의 모델을 선택하여 결과를 시각화합니다.
- 시각화: 성능 지표를 막대 그래프로 시각화하여 쉽게 비교할 수 있도록 합니다. matplotlib 또는 seaborn을 사용하여 막대 그래프를 그립니다.
- 각 모델의 성능을 비교하고 최적의 모델을 선택하여 결과를 시각화합니다.
도전 과제 가이드
- 모델 앙상블 ⭐⭐⭐⭐⭐
- 여러 모델의 예측 결과를 결합하여 성능을 향상시키는 앙상블 기법(예: 배깅, 부스팅)을 적용합니다.
- 각 모델의 예측을 평균내거나 가중치를 부여하여 최종 예측을 생성합니다.
- 하이퍼파라미터 튜닝 ⭐⭐⭐⭐
- Grid Search 또는 Random Search 기법을 이용해 모델의 하이퍼파라미터를 최적화합니다.
- 시간적 요소 추가 ⭐⭐⭐
- 주택 데이터셋에 시간적 요소(예: 계절적 변화, 경제 지표 등)를 추가하여 모델의 예측력을 높입니다.
1. 데이터 가져오기
1
2
3
4
5
6
import pandas as pd
import numpy as np
# 데이터 가져오기
df = pd.read_csv('housingdata.csv')
df
출력 결과
CRIM | ZN | INDUS | CHAS | NOX | RM | AGE | DIS | RAD | TAX | PTRATIO | B | LSTAT | MEDV | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0.00632 | 18.0 | 2.31 | 0.0 | 0.538 | 6.575 | 65.2 | 4.0900 | 1 | 296 | 15.3 | 396.90 | 4.98 | 24.0 |
1 | 0.02731 | 0.0 | 7.07 | 0.0 | 0.469 | 6.421 | 78.9 | 4.9671 | 2 | 242 | 17.8 | 396.90 | 9.14 | 21.6 |
2 | 0.02729 | 0.0 | 7.07 | 0.0 | 0.469 | 7.185 | 61.1 | 4.9671 | 2 | 242 | 17.8 | 392.83 | 4.03 | 34.7 |
3 | 0.03237 | 0.0 | 2.18 | 0.0 | 0.458 | 6.998 | 45.8 | 6.0622 | 3 | 222 | 18.7 | 394.63 | 2.94 | 33.4 |
4 | 0.06905 | 0.0 | 2.18 | 0.0 | 0.458 | 7.147 | 54.2 | 6.0622 | 3 | 222 | 18.7 | 396.90 | NaN | 36.2 |
… | … | … | … | … | … | … | … | … | … | … | … | … | … | … |
501 | 0.06263 | 0.0 | 11.93 | 0.0 | 0.573 | 6.593 | 69.1 | 2.4786 | 1 | 273 | 21.0 | 391.99 | NaN | 22.4 |
502 | 0.04527 | 0.0 | 11.93 | 0.0 | 0.573 | 6.120 | 76.7 | 2.2875 | 1 | 273 | 21.0 | 396.90 | 9.08 | 20.6 |
503 | 0.06076 | 0.0 | 11.93 | 0.0 | 0.573 | 6.976 | 91.0 | 2.1675 | 1 | 273 | 21.0 | 396.90 | 5.64 | 23.9 |
504 | 0.10959 | 0.0 | 11.93 | 0.0 | 0.573 | 6.794 | 89.3 | 2.3889 | 1 | 273 | 21.0 | 393.45 | 6.48 | 22.0 |
505 | 0.04741 | 0.0 | 11.93 | 0.0 | 0.573 | 6.030 | NaN | 2.5050 | 1 | 273 | 21.0 | 396.90 | 7.88 | 11.9 |
506 rows × 14 columns
코드 설명
- 라이브러리 임포트:
pandas
(pd): 데이터 조작 및 분석을 위한 파이썬 라이브러리입니다. 데이터프레임(DataFrame) 형식으로 데이터를 처리합니다.numpy
(np): 수치 연산을 위한 파이썬 라이브러리입니다. 여기서는 아직 사용되지 않았지만, 데이터 처리를 위한 다양한 연산을 지원합니다.
- 데이터 읽기:
pd.read_csv('housingdata.csv')
: 로컬 디렉토리에서 CSV 파일(housingdata.csv
)을 읽어와서 데이터프레임(df
)으로 저장합니다.
사용 목적
- CSV 파일 데이터 읽기: 머신러닝 작업에서 데이터를 준비하는 첫 번째 단계는 데이터 파일을 읽어오는 것입니다. 여기서 데이터는
CSV
(Comma-Separated Values) 형식으로 저장되어 있다고 가정합니다.
활용 사례
- 데이터 로딩:
- 파일로 저장된 데이터(예:
.csv
,.xlsx
)를 읽어서 데이터 분석과 머신러닝에 사용할 수 있도록 준비합니다.
- 파일로 저장된 데이터(예:
- 데이터 소스:
- CSV 파일 외에도 다른 데이터 소스(예: 데이터베이스, 웹 API)로부터 데이터를 가져올 때
pandas
가 유용합니다. pd.read_csv()
외에도pd.read_excel()
,pd.read_sql()
,pd.read_json()
등을 활용할 수 있습니다.
- CSV 파일 외에도 다른 데이터 소스(예: 데이터베이스, 웹 API)로부터 데이터를 가져올 때
사용 시 주의사항
- 파일 경로:
housingdata.csv
파일이 현재 작업 디렉토리에 존재해야 합니다. 파일 경로가 다를 경우, 절대경로 또는 상대경로를 명시해야 합니다.- 예:
pd.read_csv('data/housingdata.csv')
- 데이터 확인:
- 데이터를 읽은 후
df.head()
또는df.info()
로 데이터의 첫 몇 행과 요약 정보를 확인해 데이터가 제대로 로드되었는지 점검합니다.
- 데이터를 읽은 후
활용 상황
이 코드는 다음과 같은 경우에 사용됩니다:
- 데이터 분석을 위한 초기 데이터 로딩.
- 머신러닝 파이프라인 구축에서 데이터 준비 단계.
- EDA(Exploratory Data Analysis) 시작 시 데이터 확인.
2. 데이터 정보 확인
1
2
3
4
5
6
7
8
# 데이터 정보 확인
print(df.info())
print('=============================='*3)
print(df.describe())
# 총 506개 행
print('=============================='*3)
print(df.columns) # ['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT', 'MEDV']
# 결측치가 있는 컬럼: 'CRIM', 'ZN', 'INDUS', 'CHAS', 'AGE', 'LSTAT' 총 6개의 컬럼이 있고, 20개씩 결측치가 있음
출력 결과
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 506 entries, 0 to 505
Data columns (total 14 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 CRIM 486 non-null float64
1 ZN 486 non-null float64
2 INDUS 486 non-null float64
3 CHAS 486 non-null float64
4 NOX 506 non-null float64
5 RM 506 non-null float64
6 AGE 486 non-null float64
7 DIS 506 non-null float64
8 RAD 506 non-null int64
9 TAX 506 non-null int64
10 PTRATIO 506 non-null float64
11 B 506 non-null float64
12 LSTAT 486 non-null float64
13 MEDV 506 non-null float64
dtypes: float64(12), int64(2)
memory usage: 55.5 KB
None
==========================================================================================
CRIM ZN INDUS CHAS NOX RM \
count 486.000000 486.000000 486.000000 486.000000 506.000000 506.000000
mean 3.611874 11.211934 11.083992 0.069959 0.554695 6.284634
std 8.720192 23.388876 6.835896 0.255340 0.115878 0.702617
min 0.006320 0.000000 0.460000 0.000000 0.385000 3.561000
25% 0.081900 0.000000 5.190000 0.000000 0.449000 5.885500
50% 0.253715 0.000000 9.690000 0.000000 0.538000 6.208500
75% 3.560263 12.500000 18.100000 0.000000 0.624000 6.623500
max 88.976200 100.000000 27.740000 1.000000 0.871000 8.780000
AGE DIS RAD TAX PTRATIO B \
count 486.000000 506.000000 506.000000 506.000000 506.000000 506.000000
mean 68.518519 3.795043 9.549407 408.237154 18.455534 356.674032
std 27.999513 2.105710 8.707259 168.537116 2.164946 91.294864
min 2.900000 1.129600 1.000000 187.000000 12.600000 0.320000
25% 45.175000 2.100175 4.000000 279.000000 17.400000 375.377500
50% 76.800000 3.207450 5.000000 330.000000 19.050000 391.440000
75% 93.975000 5.188425 24.000000 666.000000 20.200000 396.225000
max 100.000000 12.126500 24.000000 711.000000 22.000000 396.900000
LSTAT MEDV
count 486.000000 506.000000
mean 12.715432 22.532806
std 7.155871 9.197104
min 1.730000 5.000000
25% 7.125000 17.025000
50% 11.430000 21.200000
75% 16.955000 25.000000
max 37.970000 50.000000
==========================================================================================
Index(['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD', 'TAX',
'PTRATIO', 'B', 'LSTAT', 'MEDV'],
dtype='object')
3. 데이터 분리
1
2
3
4
5
6
from sklearn.model_selection import train_test_split
X = df.drop(columns=['MEDV'])
y = df['MEDV']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
코드 설명
- 라이브러리 임포트:
train_test_split
: Scikit-learn 라이브러리의 데이터 분할 함수로, 데이터셋을 훈련용(Train)과 테스트용(Test)으로 나눕니다.
- 특성과 레이블 분리:
df.drop(columns=['MEDV'])
:- 데이터프레임
df
에서MEDV
열을 제외한 나머지 열을X
(특성 데이터)로 지정합니다. drop()
함수는 제거할 열을 지정하며,columns=['MEDV']
는 열 이름이MEDV
인 열을 삭제합니다.
- 데이터프레임
df['MEDV']
:- 데이터프레임
df
에서MEDV
열만 선택하여y
(레이블 데이터)로 저장합니다.
- 데이터프레임
- 데이터셋 분할:
train_test_split(X, y, test_size=0.2, random_state=42)
:X
와y
를 훈련 데이터(X_train
,y_train
)와 테스트 데이터(X_test
,y_test
)로 분할합니다.test_size=0.2
: 데이터의 20%를 테스트 데이터로 사용하고, 나머지 80%를 훈련 데이터로 사용합니다.random_state=42
: 랜덤 시드를 설정하여 항상 동일한 결과를 재현 가능하게 합니다.
사용 목적
- 모델 성능 평가:
- 데이터를 훈련 데이터와 테스트 데이터로 나누는 이유는 모델이 새로운 데이터(테스트 데이터)에 대해 얼마나 잘 일반화되는지 평가하기 위함입니다.
- 훈련 데이터는 모델 학습에 사용되고, 테스트 데이터는 학습된 모델의 성능을 검증하는 데 사용됩니다.
활용 사례
- 머신러닝 모델 학습:
- 데이터를 훈련 데이터와 테스트 데이터로 분할해 모델 학습 후 성능을 검증하는 일반적인 과정입니다.
- 파이프라인 구축:
- 데이터 전처리, 특성 엔지니어링, 모델 학습 및 평가의 파이프라인에서 첫 단계로 데이터셋을 분리합니다.
사용 시 주의사항
- 데이터 누락 방지:
- 데이터셋에 결측치가 있는 경우 분할 전에 결측치를 처리하거나, 분할 후에도 적절히 처리해야 합니다.
- 레이블 데이터 분포:
train_test_split
은 기본적으로 데이터를 무작위로 분할합니다. 하지만 레이블 데이터가 불균형한 경우stratify
매개변수를 사용해 분포를 유지해야 합니다.- 예:
train_test_split(X, y, test_size=0.2, stratify=y, random_state=42)
- 테스트 데이터 크기:
test_size
를 0.2로 설정한 것은 일반적인 선택이며, 데이터 크기와 목표에 따라 조정 가능합니다.- 예: 데이터가 적은 경우
test_size=0.3
로 설정해 더 많은 테스트 데이터를 확보할 수 있습니다.
4. 결측치 처리
1
2
3
4
5
6
7
8
9
10
11
12
from sklearn.experimental import enable_iterative_imputer
from sklearn.impute import IterativeImputer
from sklearn.linear_model import LinearRegression
# 결측치 처리 (훈련 데이터에서 fit, 테스트 데이터는 transform만 적용)
imputer = IterativeImputer(estimator=LinearRegression(), random_state=42)
# 훈련 데이터 결측치 처리
X_train_imputed = pd.DataFrame(imputer.fit_transform(X_train), columns=X_train.columns)
# 테스트 데이터 결측치 처리 (훈련 데이터 기반으로 처리)
X_test_imputed = pd.DataFrame(imputer.transform(X_test), columns=X_test.columns)
코드 설명
- 라이브러리 임포트:
enable_iterative_imputer
:IterativeImputer
는 실험적 기능으로, 사용하기 전에 활성화가 필요합니다. 이를 위해enable_iterative_imputer
를 임포트합니다.
IterativeImputer
:- 결측치를 대체하는 데 사용되는 Scikit-learn 클래스입니다. 결측치를 반복적으로 예측하고 대체하는 방식으로 처리합니다.
LinearRegression
:IterativeImputer
에서 결측치를 예측하는 데 사용할 모델로 지정됩니다. 여기서는 선형 회귀를 사용합니다.
- 결측치 처리 로직:
IterativeImputer(estimator=LinearRegression(), random_state=42)
:- 결측치를 처리하기 위해
IterativeImputer
객체를 생성합니다. estimator=LinearRegression()
:- 결측치를 예측하기 위해 선형 회귀 모델을 사용합니다.
random_state=42
:- 결과 재현성을 위해 랜덤 시드를 고정합니다.
- 결측치를 처리하기 위해
- 훈련 데이터 처리:
imputer.fit_transform(X_train)
:- 훈련 데이터를 사용해 결측치를 예측하고 대체합니다.
fit
은 데이터를 기반으로 결측치 처리 규칙을 학습합니다.transform
은 학습한 규칙을 사용해 데이터를 변환합니다.
pd.DataFrame(...)
:- 결측치가 대체된 결과를 데이터프레임으로 변환하며, 원래 열 이름(
X_train.columns
)을 유지합니다.
- 결측치가 대체된 결과를 데이터프레임으로 변환하며, 원래 열 이름(
- 테스트 데이터 처리:
imputer.transform(X_test)
:- 훈련 데이터에서 학습한 규칙을 사용해 테스트 데이터의 결측치를 대체합니다.
- 테스트 데이터는
fit
을 하지 않으며, 훈련 데이터 기반의 규칙만 적용됩니다.
사용 목적
- 결측치 처리:
- 데이터셋에 결측치가 포함되어 있을 때, 머신러닝 모델은 결측치를 직접 처리할 수 없습니다. 이를 해결하기 위해 결측치를 대체하는 작업이 필요합니다.
- 단순 대체 방식(평균, 중앙값 등)보다 더 정교하게 결측치를 예측할 수 있습니다.
- 반복적 예측:
IterativeImputer
는 각 특성을 다른 특성의 선형 조합으로 예측하며, 반복적으로 결측치를 업데이트해 최적화된 값을 제공합니다.
활용 사례
- 다양한 결측치 상황 처리:
- 데이터를 삭제하거나 평균/중앙값으로 대체하기 어려운 경우, 다른 특성을 기반으로 결측치를 예측해 대체합니다.
- 특히, 데이터셋이 크고 결측치가 많은 경우에 유용합니다.
- 다양한 추정 모델 사용:
IterativeImputer
는estimator
를 사용자 정의로 설정할 수 있어, 선형 회귀 외에도 랜덤 포레스트, KNN 등 다양한 방법으로 결측치를 예측할 수 있습니다.
매개변수 설명
estimator=LinearRegression()
:- 결측치를 예측할 추정 모델로, 여기서는 선형 회귀 모델을 사용합니다.
- 다른 예로 랜덤 포레스트를 사용하려면
estimator=RandomForestRegressor()
로 설정 가능합니다.
random_state=42
:- 반복 과정에서 난수를 사용하는 경우 결과 재현성을 보장합니다.
max_iter
:- 결측치를 반복적으로 대체할 최대 반복 횟수입니다(기본값: 10). 더 복잡한 데이터에 대해 값을 늘릴 수 있습니다.
tol
:- 반복적인 대체가 수렴하는 허용 오차입니다(기본값: 1e-3).
사용 시 주의사항
- 결측치가 적은 경우:
- 데이터가 충분하고 결측치가 적다면, 단순 대체(예: 평균, 중앙값)로도 충분할 수 있습니다.
- 훈련-테스트 데이터 처리 분리:
- 훈련 데이터에서 학습한 규칙을 테스트 데이터에 동일하게 적용해야 합니다.
- 테스트 데이터에 대해
fit_transform()
을 사용하면 정보 누출 문제가 발생합니다.
- 추정 모델 선택:
- 선형 회귀 외에도 비선형 추정 모델을 사용할 수 있지만, 데이터와 문제 특성에 적합한 모델을 선택해야 합니다.
활용 상황
- 데이터셋의 특성 중 일부에 결측치가 포함되어 있는 경우.
- 예: 주택 데이터에서 일부 특성(예: 방의 개수, 면적)이 누락된 상황.
- 결측치를 단순 대체(평균, 중앙값)로 해결하기 어렵거나, 데이터 관계를 보존해야 하는 경우.
- 예: 특성 간 상관관계가 높은 경우, 다른 특성을 기반으로 결측치를 예측하는 방식이 더 효과적.
This post is licensed under CC BY 4.0 by the author.