반응형

핸즈 온 머신러닝 (Hands-On Machine Learning with Scikit-Learn & TensorFlow) / 오렐리앙 제론 지음 , 박해선 옮김

을 읽고, 추후 기억을 되살릴 수 있게끔 나만의 방법으로 내용을 리뷰한다. 따라서 리뷰의 내용 별 비중이 주관적일 수 있다.


챕터 2. 머신러닝 프로젝트 처음부터 끝까지

 

2장에서는 머신러닝 프로젝트에서 공통적으로 중요한 요소들에 대해 설명한다.

 

2.1 실제 데이터로 작업하기

인공적으로 만들어진 데이터셋 보다는 실제 데이터로 실험하는 것이 좋으며, 대표적인 데이터 저장소는 Kaggle이 있다.

https://www.kaggle.com/

 

Kaggle: Your Home for Data Science

 

www.kaggle.com

다양한 competition들도 열린다.

 

2.2 큰 그림 보기

캘리포니아 인구조사 데이터를 사용해 주택 가격 모델을 만드는 프로젝트를 예시로 설명하고 있다.

 

 

2.2.1 문제 정의

모델을 만드는 것이 최종 목적이 아니라, 모델을 이용하여 이익을 얻으려고 하는 것이 최종 목표이다. 따라서 프로젝트의 최종 목적 혹은 비즈니스 관계자와 소통하여 현 상황 및 최종 목표를 구체화하는것이 중요하다. 

이 문제는 레이블된 훈련 샘플이 있으니 지도 학습이며 회귀 문제이다. 또한 예측에 사용할 특성이 다수이므로 다변량 회귀문제이다.

 

2.2.2 성능 측정 지표 선택

프로젝트를 잘 해결하였는가의 척도가 필요하다. 회귀에서 자주 사용하는 지표는 RMSE이다. 그 외에도 다양한 지표가 있으며 (MAE, Euclidean norm, Manhattan norm 등)

https://scikit-learn.org/stable/modules/model_evaluation.html#regression-metrics

 

3.3. Metrics and scoring: quantifying the quality of predictions — scikit-learn 0.22.1 documentation

3.3. Metrics and scoring: quantifying the quality of predictions There are 3 different APIs for evaluating the quality of a model’s predictions: Finally, Dummy estimators are useful to get a baseline value of those metrics for random predictions. 3.3.1. Th

scikit-learn.org

위 링크에서 확인할 수 있다.

 

2.2.3 가정 검사

마지막으로 지금까지의 가정을 나열하고 검사하는 것이 좋다. 모델의 결과가 추후에 어떻게 활용되는지 정확하게 알 수 있다면 더 유용한 모델을 만들 수 있을 것이다.

2.3 데이터 가져오기

python과 scikit-learn을 사용하기 위한 준비 단계로, 간단하게만 정리하겠다.

 

2.3.1 작업 환경 만들기

http://www.python.org 

 

Welcome to Python.org

The official home of the Python Programming Language

www.python.org

파이썬을 설치 후, 가상 환경을 만들고 패키지들을 설치해야한다. 윈도우에서는 linux (ubuntu)를 사용하는 것을 추천한다. 파이썬 가상 환경에 관해서는 추후 포스팅 하겠다.

 

pip3 install --upgrade pip
pip3 install --upgrade jupyter matplotlib numpy pandas scipy scikit-learn

혹은 anaconda를 설치하여 유용한 패키지들을 한 번에 설치할 수 있다.

 

2.3.2 데이터 다운로드

comma로 데이터들이 분리되어있는 csv 파일을 많이 사용하며 urllib 라이브러리를 이용하여 웹에서 파일을 다운로드 받을 수 있다. pandas 의 read_csv 를 이용하면 된다.

 

import os
import pandas as pd

csv_path = os.path.join (housing_path, "housing.csv")
df = pd.read_csv (csv_path)

 

2.3.3 데이터 구조 훑어보기

데이터 구조를 알아볼 수 있는 몇 가지 방법을 소개한다.

 

df.head() # 처음 다섯 행 확인

df.info() # 간략한 설명, 전체 행 수, 각 특성의 데이터 타입과 값의 개수 확인

df["rooms"].value_counts() # 특성의 카테고리 count

df.describe() # 숫자형 특성들의 통계적 정보

import matplotlib.pyplot as plt

df.hist(bins=50, figsize=(20,15))
plt.show #숫자형 특성들에 대한 히스토그램

 

2.3.4 테스트 세트 만들기

데이터 구조를 훑어볼 때에 테스트 세트를 분리한 후 구조를 훑어보아야 한다. 테스트 세트가 가지고 있는 특성이 모델에 반영되면 안되기 때문이다. 그런 현상을 data snooping 편향이라고 한다.

 

테스트 세트를 직접 분리하는 방법으로는 numpy의 random.permutation을 사용하는 방법이 있다. numpy의 random.seed를 설정하면 같은 데이터 셋에서 항상 같은 테스트 세트가 추출되지만, 만약 데이터 셋이 조금 추가된다면 테스트 세트가 완전히 바뀌게 된다. 이런 경우 각각의 데이터에 대해 id를 부여하여 hash 값으로 분리하는 방법이 있다.

 

sklearn의 train_test_split을 쓰는 방법이 매우 간편하다.

 

from sklean.model_selection import train_test_split

train_set, test_set = train_test_split (df, test_size = 0.2, random_state = 25)

https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.train_test_split.html

 

sklearn.model_selection.train_test_split — scikit-learn 0.22.1 documentation

 

scikit-learn.org

 

완전히 무작위로 테스트 셋을 추출하는 과정은 데이터가 많을 때에는 좋지만, 적을 때에는 우연히 편향된 테스트 셋이 추출될 가능성도 있다. 카테고리 별로 최대한 균일하게 테스트 셋을 추출하고 싶을 때에는 sklearn의 StratifiedShuffleSplit을 사용하면 된다.

 

https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.StratifiedShuffleSplit.html

 

sklearn.model_selection.StratifiedShuffleSplit — scikit-learn 0.22.1 documentation

 

scikit-learn.org

 

2.4 데이터 이해를 위한 탐색과 시각화

2.4.1 지리적 데이터 시각화

본 프로젝트에서 사용하는 캘리포니아 인구조사 데이터를 위도와 경도에 따라 시각화 하는 방법들을 소개한다.

 

df.plot(kind="scatter", x="longitude", y="latitude") # 단순히 그래프에 위치 표시

df.plot(kind="scatter", x="longitude", y="latitude", alpha=0.1) # 투명도를 조절하여 밀집된 지역 파악 가능

df.plot(kind="scatter", x="longitude", y="latitude", alpha=0.4, s=df["population"]/100, label="population", figsize=(10,7), c="median_house_value", cmap=plt.get_cmap("jet"), colorbar=True, sharex=False) # cmap을 활용하여 특성에 따라 색을 변화

 

2.4.2 상관관계 조사

모든 특성 간의 표준 상관계수를 corr() method를 이용하여 계산할 수 있다.

 

corr_matrix = df.corr()

corr_matrix["median_house_value"].sort_values(ascending=False)

 

특성 사이의 상관관계를 산점도로 확인하려면 pandas의 scatter_matrix 함수를 사용하면 된다.

 

from pandas.plotting import scatter_matrix

attributes = ["median_house_value", "median_income", "total_rooms", "housing_median_age"]
scatter_matrix(df[attributes], figsize=(12,8))

 

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.plotting.scatter_matrix.html

 

pandas.plotting.scatter_matrix — pandas 0.25.3 documentation

Parameters: frame : DataFrame alpha : float, optional amount of transparency applied figsize : (float,float), optional a tuple (width, height) in inches ax : Matplotlib axis object, optional grid : bool, optional setting this to True will show the grid dia

pandas.pydata.org

 

2.4.3 특성 조합으로 실험

데이터의 특성을 그대로 사용하지 않고, 특성 사이의 상관관계를 활용하거나 새로운 특성을 판단하에 만들어서 사용하는 것이 더 좋은 모델을 만드는 경우가 될 수 있다. 이러한 판단을 하기 위해서는 데이터를 분석하고 시각화하는 과정을 반복하여 통찰을 얻어야한다.

2.5 머신러닝 알고리즘을 위한 데이터 준비

데이터 전처리를 수동으로 하는 것 보다는 함수로 만들어 자동화하는 것이 좋다. 데이터셋에 변화가 있어도 쉽게 재적용할 수 있으며 실제 모델 예측에 활용하거나 여러 조합을 시도해 보는데에 훨씬 유리하다.

 

2.5.1 데이터 정제

데이터에 누락된 값이 있는 경우 drop, dropna, fillna 등의 method를 이용하여 처리할 수 있다. 만약 fillna를 사용하여 중간값 등으로 채워넣는 경우 모델 학습시의 중간값을 기억하여야 추후 테스트 데이터에도 해당 값을 사용할 수 있다. 이러한 과정을 자동으로 해주는 것이 sklearn의 SimpleImputer 이다.

 

https://scikit-learn.org/stable/modules/generated/sklearn.impute.SimpleImputer.html

 

sklearn.impute.SimpleImputer — scikit-learn 0.22.1 documentation

 

scikit-learn.org

from sklearn.impute import SimpleImputer

imputer = SimpleImputer(strategy="median")

imputer.fit(df) # df에 수치형 자료만 있다고 가정

print (imputer.statistics_)

X = imputer.transform(df)

 

이 과정에서 사이킷런의 설계 철학을 알아볼 필요가 있다.

 

https://arxiv.org/pdf/1309.0238v1.pdf

불러오는 중입니다...

일관성 : 모든 객체가 일관되고 단순한 인터페이스를 공유한다.

검사 가능 : 모든 추정기의 하이퍼파라미터는 직접 접근할 수 있다.

클래스 남용 방지 : 데이터 셋을 항상 numpy array나 sparse matrix로 표현한다.

조합성 : 기존의 구성요소를 최대한 재사용 한다. (pipeline)

합리적인 기본값 : 대부분의 파라미터들이 합리적인 default를 가지고 있다.

 

특히 일관성 부분에서, 객체들은

- estimator (데이터 셋을 기반으로 parameter 들을 추정, fit method)

- transformer (estimator 중 데이터를 변환, transform method, fit_transform method)

- predictor (estimator 중 predict가 가능 한 것. predict method, score method 등)

중 하나의 종류로 이루어져 있다.

 

2.5.2 텍스트와 범주형 특성 다루기

텍스트와 범주형 특성은 수치화하여 모델링 할 필요가 있다. 예를들어 pandas factorize() method를 사용하면 각각의 카테고리를 정수로 매핑해준다. 하지만 이런 매핑은 수의 크기관계가 생겨나므로 사용할 수 없는 경우가 있다. 그런 경우에는 카테고리별 이진 특성을 만드는 one-hot encoding을 추가로 사용한다.

 

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.factorize.html

 

pandas.factorize — pandas 0.25.3 documentation

Returns: labels : ndarray An integer ndarray that’s an indexer into uniques. uniques.take(labels) will have the same values as values. uniques : ndarray, Index, or Categorical The unique valid values. When values is Categorical, uniques is a Categorical. W

pandas.pydata.org

https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.OneHotEncoder.html

 

sklearn.preprocessing.OneHotEncoder — scikit-learn 0.22.1 documentation

 

scikit-learn.org

 

책에는 언급되어있지 않지만 pandas의 get_dummies 함수를 활용하여도 된다.

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.get_dummies.html

 

pandas.get_dummies — pandas 0.25.3 documentation

Parameters: data : array-like, Series, or DataFrame Data of which to get dummy indicators. prefix : str, list of str, or dict of str, default None String to append DataFrame column names. Pass a list with length equal to the number of columns when calling

pandas.pydata.org

 

2.5.3 나만의 변환기

sklearn에 많은 변환기들이 제공되어있지만, customized 변환기가 필요하다면 직접 fit(), transform(), fit_transform() method가 구현된 클래스를 만들면 된다. 이 때 duck typing을 지원하므로 상속할 필요는 없다. 혹은 BaseEstimator를 상속하여 활용하여도 된다. TransformerMixin을 상속하면 fit_transform() 함수도 자동으로 선언된다.

 

2.5.4 특성 스케일링

여러 학습 방법에서 특성의 스케일링이 중요하다. 주로 min-max scaling이나 standardization 방법을 사용한다. min-max scaling은 최대 최소값을 기준으로 모든 값을 0에서 1로 변환하는 것이고, standardization은 평균이 0이고 표준편차가 1인 분포로 변환시키는 것이다. 두 변환 모두 train data에서 parameter를 결정한 후 test data에 해당 값을 적용 하여야 한다.

 

2.5.5 변환 파이프라인

여러 단계의 변환을 정확한 순서대로 처리할 수 있도록 도와주는 sklearn의 Pipeline 클래스가 존재한다.

https://scikit-learn.org/stable/modules/generated/sklearn.pipeline.Pipeline.html

 

sklearn.pipeline.Pipeline — scikit-learn 0.22.1 documentation

 

scikit-learn.org

from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler

num_pipeline = Pipeline([
  ('imputer', SimpleImputer(strategy="median")),
  ('attribs_adder', CombinedAttributesAdder()),
  ('std_scaler', StandardScaler()),
])

df_tr = num_pipeline.fit_transform(df)

 

여러 개의 pipeline (수치형 pipeline과 범주형 pipeline 등) 을 합치려면 sklearn FeatureUnion 을 사용하면 된다.

https://scikit-learn.org/stable/modules/generated/sklearn.pipeline.FeatureUnion.html

 

sklearn.pipeline.FeatureUnion — scikit-learn 0.22.1 documentation

 

scikit-learn.org

 

from sklearn.pipeline import FeatureUnion

full_pipeline = FeatureUnion(transformer_list=[
  ("num_pipeline", num_pipeline),
  ("cat_pipeline", cat_pipeline),
])


df_prepared = full_pipeline.fit_transform(df)

 

2.6 모델 선택과 훈련

2.6.1 훈련 세트에서 훈련하고 평가하기

위에서 전처리한 데이터를 가지고 여러 모델을 활용하여 데이터를 학습시키고 평가 할 수 있다. LinearRegression 등의 모델을 fit method로 훈련시키고 predict method로 얻은 예측 값과 실제 값의 RMSE를 구함으로 평가할 수 있다. 그런데 train data를 평가해보면 오차가 0.0이 나올 수 있다. 이런 경우 데이터에 과대적합한 것으로, 모델 검증에 활용할 validation data를 만들어야 한다. (test data는 정말 마지막에 사용)

 

2.6.2 교차 검증을 사용한 평가

train data를 다시 train_test_split 하여 validation data를 만들어, validation data로 모델을 평가해야한다. 주어진 데이터를 최대한으로 활용하기 위해서는 cross-validation 기법을 활용하여 데이터를 분할 후 번갈아 가며 validation data로 사용한다. 

https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.cross_val_score.html

 

sklearn.model_selection.cross_val_score — scikit-learn 0.22.1 documentation

 

scikit-learn.org

 

2.7 모델 세부 튜닝

모델의 후보를 몇 가지 정한 후에, 어떤 모델을 어떤 파라미터로 사용하는 것이 가장 좋은지 판단하여야 한다.

 

2.7.1 그리드 탐색

모든 파라미터 조합을 시도해보는 과정을 도와주는 sklearn의 GridSearchCV를 사용하자.

 

https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.GridSearchCV.html

 

sklearn.model_selection.GridSearchCV — scikit-learn 0.22.1 documentation

 

scikit-learn.org

 

 best_params_, best_estimator_ 를 사용하여 최적의 조합 및 추정기를 확인할 수 있다. 또한 cv_results_ 를 통해 결과를 볼 수 있다.

 

2.7.2 랜덤 탐색

탐색 공간이 커지면 모든 경우를 확인할 수 없으므로 RandomizedSearchCV를 사용하여 효율적인 탐색을 할 수 있다.

https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.RandomizedSearchCV.html

 

sklearn.model_selection.RandomizedSearchCV — scikit-learn 0.22.1 documentation

 

scikit-learn.org

 

2.7.3 앙상블 방법

더 좋은 모델을 활용하거나 모델의 그룹을 활용하면 더 나은 모델을 만들 수 있다. (RandomForest 등)

 

2.7.4 최상의 모델과 오차 분석

최상의 모델을 분석하면 좋은 insight를 얻을 가능성이 높다. 예를 들어 RandomForest의 중요한 features를 확인하는 방법이 있다.

 

2.7.5 테스트 세트로 시스템 평가하기

validation data를 이용하여 최적의 모델을 찾았으면 test data를 pipeline에 통과시킨 후 시스템의 최종 점수를 구할 수 있다. validation data에 최적화 된 모델이므로 이보다는 점수가 낮을 가능성이 높다.

 

2.8 론칭, 모니터링, 그리고 시스템 유지 보수

프로젝트를 완료하였다면 실제 데이터 소스를 모델에 연결하고 시스템 성능을 자동으로 체크하며 입력 데이터 및 출력 값의 품질을 자주 모니터링 해야한다. 또한 꾸준히 모델을 훈련시켜야 한다. 위의 과정을 최대한 자동화하여야 유지 보수가 편하다.

 

2.9 직접 해보세요!

위의 내용을 Kaggle 등을 통해 직접 프로젝트를 구현해 보는 것이 실력 향상에 가장 도움이 된다.

반응형