Post

주택 가격 예측 모델 구축(데이터 조회 및 결측치 처리)

주택 가격 예측 모델 구축을 위한 데이터 조회 및 결측치 처리 과제입니다.

주택 가격 예측 모델 구축(데이터 조회 및 결측치 처리)

과제 1번: 지도학습

주제: 주택 가격 예측 모델 구축

  • 주어진 주택 데이터셋을 사용하여 주택 가격을 예측하는 회귀 모델을 구축한다.
컬럼별 설명
  1. CRIM: 타운별 1인당 범죄율.
  2. ZN: 25,000 평방피트 이상의 주거 구역 비율.
  3. INDUS: 비소매 상업 지역 비율.
  4. CHAS: 찰스강 인접 여부 (1: 강과 접함, 0: 접하지 않음).
  5. NOX: 대기 중 일산화질소 농도 (0.1 단위).
  6. RM: 주택 1가구당 평균 방 개수.
  7. AGE: 1940년 이전에 건설된 주택 비율.
  8. DIS: 5개의 보스턴 고용 중심지까지의 가중 거리.
  9. RAD: 고속도로 접근성 지수.
  10. TAX: 10,000달러당 재산세율.
  11. PTRATIO: 타운별 학생-교사 비율.
  12. B: 흑인 비율 (1000(Bk - 0.63)^2, 여기서 Bk는 흑인 인구 비율).
  13. LSTAT: 하위 계층 인구 비율.
  14. 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

출력 결과

 CRIMZNINDUSCHASNOXRMAGEDISRADTAXPTRATIOBLSTATMEDV
00.0063218.02.310.00.5386.57565.24.0900129615.3396.904.9824.0
10.027310.07.070.00.4696.42178.94.9671224217.8396.909.1421.6
20.027290.07.070.00.4697.18561.14.9671224217.8392.834.0334.7
30.032370.02.180.00.4586.99845.86.0622322218.7394.632.9433.4
40.069050.02.180.00.4587.14754.26.0622322218.7396.90NaN36.2
5010.062630.011.930.00.5736.59369.12.4786127321.0391.99NaN22.4
5020.045270.011.930.00.5736.12076.72.2875127321.0396.909.0820.6
5030.060760.011.930.00.5736.97691.02.1675127321.0396.905.6423.9
5040.109590.011.930.00.5736.79489.32.3889127321.0393.456.4822.0
5050.047410.011.930.00.5736.030NaN2.5050127321.0396.907.8811.9

506 rows × 14 columns

코드 설명

  1. 라이브러리 임포트:
    • pandas(pd): 데이터 조작 및 분석을 위한 파이썬 라이브러리입니다. 데이터프레임(DataFrame) 형식으로 데이터를 처리합니다.
    • numpy(np): 수치 연산을 위한 파이썬 라이브러리입니다. 여기서는 아직 사용되지 않았지만, 데이터 처리를 위한 다양한 연산을 지원합니다.
  2. 데이터 읽기:
    • pd.read_csv('housingdata.csv'): 로컬 디렉토리에서 CSV 파일(housingdata.csv)을 읽어와서 데이터프레임(df)으로 저장합니다.

사용 목적

  • CSV 파일 데이터 읽기: 머신러닝 작업에서 데이터를 준비하는 첫 번째 단계는 데이터 파일을 읽어오는 것입니다. 여기서 데이터는 CSV(Comma-Separated Values) 형식으로 저장되어 있다고 가정합니다.

활용 사례

  1. 데이터 로딩:
    • 파일로 저장된 데이터(예: .csv, .xlsx)를 읽어서 데이터 분석과 머신러닝에 사용할 수 있도록 준비합니다.
  2. 데이터 소스:
    • CSV 파일 외에도 다른 데이터 소스(예: 데이터베이스, 웹 API)로부터 데이터를 가져올 때 pandas가 유용합니다.
    • pd.read_csv() 외에도 pd.read_excel(), pd.read_sql(), pd.read_json() 등을 활용할 수 있습니다.

사용 시 주의사항

  1. 파일 경로:
    • housingdata.csv 파일이 현재 작업 디렉토리에 존재해야 합니다. 파일 경로가 다를 경우, 절대경로 또는 상대경로를 명시해야 합니다.
    • 예: pd.read_csv('data/housingdata.csv')
  2. 데이터 확인:
    • 데이터를 읽은 후 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)

코드 설명

  1. 라이브러리 임포트:
    • train_test_split: Scikit-learn 라이브러리의 데이터 분할 함수로, 데이터셋을 훈련용(Train)과 테스트용(Test)으로 나눕니다.
  2. 특성과 레이블 분리:
    • df.drop(columns=['MEDV']):
      • 데이터프레임 df에서 MEDV 열을 제외한 나머지 열을 X(특성 데이터)로 지정합니다.
      • drop() 함수는 제거할 열을 지정하며, columns=['MEDV']는 열 이름이 MEDV인 열을 삭제합니다.
    • df['MEDV']:
      • 데이터프레임 df에서 MEDV 열만 선택하여 y(레이블 데이터)로 저장합니다.
  3. 데이터셋 분할:
    • train_test_split(X, y, test_size=0.2, random_state=42):
      • Xy를 훈련 데이터(X_train, y_train)와 테스트 데이터(X_test, y_test)로 분할합니다.
      • test_size=0.2: 데이터의 20%를 테스트 데이터로 사용하고, 나머지 80%를 훈련 데이터로 사용합니다.
      • random_state=42: 랜덤 시드를 설정하여 항상 동일한 결과를 재현 가능하게 합니다.

사용 목적

  • 모델 성능 평가:
    • 데이터를 훈련 데이터와 테스트 데이터로 나누는 이유는 모델이 새로운 데이터(테스트 데이터)에 대해 얼마나 잘 일반화되는지 평가하기 위함입니다.
    • 훈련 데이터는 모델 학습에 사용되고, 테스트 데이터는 학습된 모델의 성능을 검증하는 데 사용됩니다.

활용 사례

  1. 머신러닝 모델 학습:
    • 데이터를 훈련 데이터와 테스트 데이터로 분할해 모델 학습 후 성능을 검증하는 일반적인 과정입니다.
  2. 파이프라인 구축:
    • 데이터 전처리, 특성 엔지니어링, 모델 학습 및 평가의 파이프라인에서 첫 단계로 데이터셋을 분리합니다.

사용 시 주의사항

  1. 데이터 누락 방지:
    • 데이터셋에 결측치가 있는 경우 분할 전에 결측치를 처리하거나, 분할 후에도 적절히 처리해야 합니다.
  2. 레이블 데이터 분포:
    • train_test_split은 기본적으로 데이터를 무작위로 분할합니다. 하지만 레이블 데이터가 불균형한 경우 stratify 매개변수를 사용해 분포를 유지해야 합니다.
    • 예: train_test_split(X, y, test_size=0.2, stratify=y, random_state=42)
  3. 테스트 데이터 크기:
    • 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)

코드 설명

  1. 라이브러리 임포트:
    • enable_iterative_imputer:
      • IterativeImputer는 실험적 기능으로, 사용하기 전에 활성화가 필요합니다. 이를 위해 enable_iterative_imputer를 임포트합니다.
    • IterativeImputer:
      • 결측치를 대체하는 데 사용되는 Scikit-learn 클래스입니다. 결측치를 반복적으로 예측하고 대체하는 방식으로 처리합니다.
    • LinearRegression:
      • IterativeImputer에서 결측치를 예측하는 데 사용할 모델로 지정됩니다. 여기서는 선형 회귀를 사용합니다.
  2. 결측치 처리 로직:
    • IterativeImputer(estimator=LinearRegression(), random_state=42):
      • 결측치를 처리하기 위해 IterativeImputer 객체를 생성합니다.
      • estimator=LinearRegression():
        • 결측치를 예측하기 위해 선형 회귀 모델을 사용합니다.
      • random_state=42:
        • 결과 재현성을 위해 랜덤 시드를 고정합니다.
  3. 훈련 데이터 처리:
    • imputer.fit_transform(X_train):
      • 훈련 데이터를 사용해 결측치를 예측하고 대체합니다.
      • fit은 데이터를 기반으로 결측치 처리 규칙을 학습합니다.
      • transform은 학습한 규칙을 사용해 데이터를 변환합니다.
    • pd.DataFrame(...):
      • 결측치가 대체된 결과를 데이터프레임으로 변환하며, 원래 열 이름(X_train.columns)을 유지합니다.
  4. 테스트 데이터 처리:
    • imputer.transform(X_test):
      • 훈련 데이터에서 학습한 규칙을 사용해 테스트 데이터의 결측치를 대체합니다.
      • 테스트 데이터는 fit을 하지 않으며, 훈련 데이터 기반의 규칙만 적용됩니다.

사용 목적

  1. 결측치 처리:
    • 데이터셋에 결측치가 포함되어 있을 때, 머신러닝 모델은 결측치를 직접 처리할 수 없습니다. 이를 해결하기 위해 결측치를 대체하는 작업이 필요합니다.
    • 단순 대체 방식(평균, 중앙값 등)보다 더 정교하게 결측치를 예측할 수 있습니다.
  2. 반복적 예측:
    • IterativeImputer는 각 특성을 다른 특성의 선형 조합으로 예측하며, 반복적으로 결측치를 업데이트해 최적화된 값을 제공합니다.

활용 사례

  1. 다양한 결측치 상황 처리:
    • 데이터를 삭제하거나 평균/중앙값으로 대체하기 어려운 경우, 다른 특성을 기반으로 결측치를 예측해 대체합니다.
    • 특히, 데이터셋이 크고 결측치가 많은 경우에 유용합니다.
  2. 다양한 추정 모델 사용:
    • IterativeImputerestimator를 사용자 정의로 설정할 수 있어, 선형 회귀 외에도 랜덤 포레스트, KNN 등 다양한 방법으로 결측치를 예측할 수 있습니다.

매개변수 설명

  1. estimator=LinearRegression():
    • 결측치를 예측할 추정 모델로, 여기서는 선형 회귀 모델을 사용합니다.
    • 다른 예로 랜덤 포레스트를 사용하려면 estimator=RandomForestRegressor()로 설정 가능합니다.
  2. random_state=42:
    • 반복 과정에서 난수를 사용하는 경우 결과 재현성을 보장합니다.
  3. max_iter:
    • 결측치를 반복적으로 대체할 최대 반복 횟수입니다(기본값: 10). 더 복잡한 데이터에 대해 값을 늘릴 수 있습니다.
  4. tol:
    • 반복적인 대체가 수렴하는 허용 오차입니다(기본값: 1e-3).

사용 시 주의사항

  1. 결측치가 적은 경우:
    • 데이터가 충분하고 결측치가 적다면, 단순 대체(예: 평균, 중앙값)로도 충분할 수 있습니다.
  2. 훈련-테스트 데이터 처리 분리:
    • 훈련 데이터에서 학습한 규칙을 테스트 데이터에 동일하게 적용해야 합니다.
    • 테스트 데이터에 대해 fit_transform()을 사용하면 정보 누출 문제가 발생합니다.
  3. 추정 모델 선택:
    • 선형 회귀 외에도 비선형 추정 모델을 사용할 수 있지만, 데이터와 문제 특성에 적합한 모델을 선택해야 합니다.

활용 상황

  • 데이터셋의 특성 중 일부에 결측치가 포함되어 있는 경우.
    • 예: 주택 데이터에서 일부 특성(예: 방의 개수, 면적)이 누락된 상황.
  • 결측치를 단순 대체(평균, 중앙값)로 해결하기 어렵거나, 데이터 관계를 보존해야 하는 경우.
    • 예: 특성 간 상관관계가 높은 경우, 다른 특성을 기반으로 결측치를 예측하는 방식이 더 효과적.
This post is licensed under CC BY 4.0 by the author.