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

2.4 데이터 이해를 위한 탐색과 시각화 | 목차 | 2.6 모델 선택과 훈련

 

이제 머신러닝 알고리즘을 위해 데이터를 준비할 차례입니다. 이 작업을 그냥 수동으로 하는 대신 함수를 만들어 자동화해야 하는 이유가 있습니다.

  • 어떤 데이터셋에 대해서도 데이터 변환을 손쉽게 반복할 수 있습니다(예를 들어 다음번에 새로운 데이터셋을 사용할 때).
  • 향후 프로젝트에 사용할 수 있는 변환 라이브러리를 점진적으로 구축하게 됩니다.
  • 실제 시스템에서 알고리즘에 새 데이터를 주입하기 전에 변환시키는 데 이 함수를 사용할 수 있습니다.
  • 여러 가지 데이터 변환을 쉽게 시도해볼 수 있고 어떤 조합이 가장 좋은지 확인하는 데 편리합니다.

하지만 먼저 원래 훈련 세트로 복원하고(strat_train_set을 다시 한번 복사합니다), 예측 변수와 타깃 값에 같은 변형을 적용하지 않기 위해 예측 변수와 레이블을 분리하겠습니다(drop()은 데이터 복사본을 만들며 strat_train_set에는 영향을 주지 않습니다).

housing = strat_train_set.drop("median_house_value", axis=1)
housing_labels = strat_train_set["median_house_value"].copy()

 

2.5.1 데이터 정제

대부분의 머신러닝 알고리즘은 누락된 특성을 다루지 못하므로 이를 처리할 수 있는 함수를 몇 개 만들겠습니다. 앞서 total_bedrooms 특성에 값이 없는 경우를 보았는데 이를 고쳐보겠습니다. 방법은 세 가지입니다.

  • 해당 구역을 제거합니다.
  • 전체 특성을 삭제합니다.
  • 어떤 값으로 채웁니다(0, 평균, 중간값 등).

데이터프레임의 dropna(), drop(), fillna() 메서드를 이용해 이런 작업을 간단하게 처리할 수 있습니다.

housing.dropna(subset=["total_bedrooms"]) # 옵션 1
housing.drop("total_bedrooms", axis=1) # 옵션 2
median = housing["total_bedrooms"].median() # 옵션 3
housing["total_bedrooms"].fillna(median, inplace=True)

옵션 3을 선택하면 훈련 세트에서 중간값을 계산하고 누락된 값을 이 값으로 채워 넣어야 합니다. 하지만 계산된 중간값을 저장하는 것 또한 잊지 말아야 합니다. 나중에 시스템을 평가할 때 테스트 세트에 있는 누락된 값을 바꾸기 위해 필요하고 시스템이 실제 운영될 때 새로운 데이터에서 누락된 값을 바꿔야 하기 때문입니다.31

사이킷런의 Imputer는 누락된 값을 손쉽게 다루도록 해줍니다. 어떻게 사용하는지 살펴보죠. 먼저 누락된 값을 특성의 중간값으로 대체한다고 지정하여 Imputer의 객체를 생성합니다.

from sklearn.preprocessing import Imputer
imputer = Imputer(strategy="median")

중간값이 수치형 특성에서만 계산될 수 있기 때문에 텍스트 특성인 ocean_proximity를 제외한 데이터 복사본을 생성합니다.

housing_num = housing.drop("ocean_proximity", axis=1)

이제 imputer 객체의 fit( ) 메서드를 사용해 훈련 데이터에 적용할 수 있습니다.

imputer.fit(housing_num)

imputer는 각 특성의 중간값을 계산해서 그 결과를 객체의 statistics_ 속성에 저장합니다. total_bedrooms 특성에만 누락된 값이 있지만 나중에 시스템이 서비스될 때 새로운 데이터에서 어떤 값이 누락될지 확신할 수 없으므로 모든 수치형 특성에 imputer를 적용하는 것이 바람직합니다.

>>> imputer.statistics_
array([ -118.51 , 34.26 , 29. , 2119.5 , 433. , 1164. , 408. , 3.5409])
>>> housing_num.median().values
array([ -118.51 , 34.26 , 29. , 2119.5 , 433. , 1164. , 408. , 3.5409])

이제 학습된 imputer 객체를 사용해 훈련 세트에서 누락된 값을 학습한 중간값으로 바꿀 수 있습니다.

X = imputer.transform(housing_num)

이 결과는 변형된 특성들이 들어 있는 평범한 넘파이 배열입니다. 이를 다시 판다스 데이터프레임으로 간단히 되돌릴 수 있습니다.

housing_tr = pd.DataFrame(X, columns=housing_num.columns,
                          index = list(housing.index.values))
사이킷런의 설계 철학

사이킷런의 API는 아주 잘 설계되어 있습니다. 주요 설계 원칙은 다음과 같습니다.32

  • 일관성. 모든 객체가 일관되고 단순한 인터페이스를 공유합니다.
    • 추정기estimator. 데이터셋을 기반으로 일련의 모델 파라미터들을 추정하는 객체를 추정기라고 합니다(예를 들어 imputer 객체는 추정기입니다). 추정 자체는 fit() 메서드에 의해 수행되고 하나의 매개변수로 하나의 데이터셋만 전달합니다(지도 학습 알고리즘에서는 매개변수가 두 개로, 두 번째 데이터셋은 레이블을 담고 있습니다). 추정 과정에서 필요한 다른 매개변수들은 모두 하이퍼파라미터로 간주되고(예를 들면 imputer 객체의 strategy 매개변수), 인스턴스 변수33로 저장됩니다(보통 생성자의 매개변수로 전달합니다34).
    • 변환기transformer. (imputer 같이) 데이터셋을 변환하는 추정기를 변환기라고 합니다. 여기서도 API는 매우 단순합니다. 변환은 데이터셋을 매개변수로 전달받은 transform() 메서드가 수행합니다. 그리고 변환된 데이터셋을 반환합니다. 이런 변환은 일반적으로 imputer의 경우와 같이 학습된 모델 파라미터에 의해 결정됩니다.35 모든 변환기는 fit()과 transform()을 연달아 호출하는 것과 동일한 fit_transform() 메서드도 가지고 있습니다(이따금 fit_transform()이 최적화되어 있어서 더 빠릅니다).
    • 예측기predictor. 일부 추정기는 주어진 데이터셋에 대해 예측을 만들 수 있습니다. 예를 들어 앞 장에 나온 LinearRegression 모델이 예측기입니다. 어떤 나라의 1인당 GDP가 주어질 때 삶의 만족도를 예측했습니다. 예측기의 predict() 메서드는 새로운 데이터셋을 받아 이에 상응하는 예측값을 반환합니다. 또한 테스트 세트(지도 학습 알고리즘이라면 레이블도 함께)를 사용해 예측의 품질을 측정하는 score() 메서드를 가집니다.36
  • 검사 가능. 모든 추정기의 하이퍼파라미터는 공개public 인스턴스 변수로 직접 접근할 수 있고(예를 들면 imputer.strategy), 모든 추정기의 학습된 모델 파라미터도 접미사로 밑줄을 붙여서 공개 인스턴스 변수로 제공됩니다(예를 들면 imputer.statistics_).37
  • 클래스 남용 방지. 데이터셋을 별도의 클래스가 아니라 넘파이 배열이나 사이파이 희소sparse 행렬로 표현합니다. 하이퍼파라미터는 보통의 파이썬 문자열이나 숫자입니다.
  • 조합성. 기존의 구성요소를 최대한 재사용합니다. 앞으로 보겠지만 예를 들어 여러 변환기를 연결한 다음 마지막에 추정기 하나를 배치한 Pipeline 추정기를 쉽게 만들 수 있습니다.
  • 합리적인 기본값. 사이킷런은 일단 돌아가는 기본 시스템을 빠르게 만들 수 있도록 대부분의 매개변수에 합리적인 기본값을 지정해두었습니다.

 

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

앞서 범주형 특성 ocean_proximity가 텍스트라 중간값을 계산할 수 없어서 그냥 남겨뒀습니다.

>>> housing_cat = housing["ocean_proximity"]
>>> housing_cat.head(10)
17606 <1H OCEAN
18632 <1H OCEAN
14650 NEAR OCEAN
3230 INLAND
3555 <1H OCEAN
19480 INLAND
8879 <1H OCEAN
13685 INLAND
4937 <1H OCEAN
4861 <1H OCEAN
Name: ocean_proximity, dtype: object

대부분의 머신러닝 알고리즘은 숫자형을 다루므로 이 카테고리를 텍스트에서 숫자로 바꾸도록 하겠습니다. 이를 위해 각 카테고리를 다른 정숫값으로 매핑해주는 판다스의 factorize() 메서드를 사용합니다.

>>> housing_cat_encoded, housing_categories = housing_cat.factorize()
>>> housing_cat_encoded[:10]
array([0, 0, 1, 2, 0, 2, 0, 2, 0, 0])

훨씬 나아졌네요. 이제 housing_cat_encoded는 완전히 숫자입니다. factorize() 메서드는 카테고리 리스트도 반환해줍니다(‘<1H OCEAN’은 0으로 매핑되고, ‘NEAR OCEAN’은 1로 매핑되고, 등등).

>>> housing_categories
Index(['<1H OCEAN', 'NEAR OCEAN', 'INLAND', 'NEAR BAY', 'ISLAND'], dtype='object')

이 표현 방식의 문제는 머신러닝 알고리즘이 가까이 있는 두 값이 떨어져 있는 두 값보다 더 비슷하다고 생각한다는 점입니다. 실제로는 그렇지 않습니다(예를 들어 카테고리 0과 1보다 카테고리 0과 4가 더 비슷합니다). 이 문제는 일반적으로 카테고리별 이진 특성을 만들어 해결합니다. 카테고리가 ‘<1H OCEAN’일 때 한 특성이 1이고(그 외 특성은 0), 카테고리가 ‘INLAND’일 때 다른 한 특성이 1이 되는(역시 그 외에는 0) 식입니다. 한 특성만 1이고(핫) 나머지는 0이므로 이를 원-핫 인코딩one-hot encoding이라고 부릅니다.

사이킷런은 숫자로 된 범주형 값을 원-핫 벡터로 바꿔주는 OneHotEncoder를 제공합니다. 카테고리들을 원-핫 벡터로 인코딩해보겠습니다.

>>> from sklearn.preprocessing import OneHotEncoder
>>> encoder = OneHotEncoder()
>>> housing_cat_1hot = encoder.fit_transform(housing_cat_encoded.reshape(-1,1))
>>> housing_cat_1hot
<16512x5 sparse matrix of type '<class 'numpy.float64'>'
with 16512 stored elements in Compressed Sparse Row format>

fit_transform() 메서드는 2차원 배열을 넣어줘야 하는데 housing_cat_encoded는 1차원 배열이므로 구조를 바꿔야 합니다.38 또한 출력을 보면 넘파이 배열이 아니고 사이파이SciPy 희소 행렬sparse matrix입니다. 이는 수천 개의 카테고리가 있는 범주형 특성일 경우 매우 효율적입니다. 이런 특성을 원-핫 인코딩하면 열이 수천 개인 행렬로 변하고 각 행은 1이 하나뿐이고 그 외에는 모두 0으로 채워져 있을 것입니다. 0을 모두 메모리에 저장하는 것은 낭비이므로 희소 행렬은 0이 아닌 원소의 위치만 저장합니다. 이 행렬을 거의 일반적인 2차원 배열처럼 사용할 수 있지만39 (밀집된) 넘파이 배열로 바꾸려면 toarray() 메서드를 호출하면 됩니다.

>>> housing_cat_1hot.toarray()
array([[ 1., 0., 0., 0., 0.],
[ 1., 0., 0., 0., 0.],
[ 0., 1., 0., 0., 0.],
...,
[ 0., 0., 1., 0., 0.],
[ 1., 0., 0., 0., 0.],
[ 0., 0., 0., 1., 0.]])

텍스트 카테고리를 숫자 카테고리로, 숫자 카테고리를 원-핫 벡터로 바꿔주는 이 두 가지 변환을 CategoricalEncoder를 사용하여 한번에 처리할 수 있습니다.40 이 파이썬 클래스는 사이킷런 0.19.0과 그 이전 버전에는 포함되어 있지 않습니다. 하지만 곧 추가될 예정이라 아마 이 책을 읽을 때쯤이면 이미 포함되어 있을 가능성이 많습니다. 그렇지 않다면 이 장의 주피터 노트북에서 가져와 사용할 수 있습니다(이 코드는 #9151 풀 리퀘스트Pull Request41에서 복사한 것입니다). 이 클래스를 사용하는 방법은 다음과 같습니다.

>>> from sklearn.preprocessing import CategoricalEncoder # 또는 노트북에서 가져옵니다.
>>> cat_encoder = CategoricalEncoder()
>>> housing_cat_reshaped = housing_cat.values.reshape(-1, 1)
>>> housing_cat_1hot = cat_encoder.fit_transform(housing_cat_reshaped)
>>> housing_cat_1hot
<16512x5 sparse matrix of type '<class 'numpy.float64'>'
        with 16512 stored elements in Compressed Sparse Row format>

기본적으로 CategoricalEncoder는 희소 행렬을 출력하지만 밀집 행렬dense matrix을 원할 경우에는 encoding 매개변수를 “onehot-dense”로 지정할 수 있습니다.

>>> cat_encoder = CategoricalEncoder(encoding="onehot-dense")
>>> housing_cat_1hot = cat_encoder.fit_transform(housing_cat_reshaped)
>>> housing_cat_1hot
array([[ 1., 0., 0., 0., 0.],
       [ 1., 0., 0., 0., 0.],
       [ 0., 0., 0., 0., 1.],
       ...,
       [ 0., 1., 0., 0., 0.],
       [ 1., 0., 0., 0., 0.],
       [ 0., 0., 0., 1., 0.]])

categories_ 인스턴스 변수를 사용해 카테고리 리스트를 얻을 수 있습니다. 이 리스트는 카테고리 특성마다 1D 카테고리 배열을 담고 있습니다(여기에서는 하나의 카테고리 특성만 있기 때문에 배열 하나만을 담고 있는 리스트입니다).

>>> cat_encoder.categories_
[array(['<1H OCEAN', 'INLAND', 'ISLAND', 'NEAR BAY', 'NEAR OCEAN'], dtype=object)]
TIP 카테고리 특성이 담을 수 있는 카테고리 수가 많다면(예를 들면 국가 코드, 직업, 생물 종류 등) 원-핫 인코딩은 많은 수의 입력 특성을 만듭니다. 이는 훈련을 느리게 하고 성능을 감소시킬 수 있습니다. 이런 경우에는 임베딩embedding이라고 하는 조금 더 조밀한 표현을 사용할 수 있지만 신경망에 대한 이해가 필요합니다(자세한 내용은 14장에서 설명합니다).

 

2.5.3 나만의 변환기

사이킷런이 유용한 변환기를 많이 제공하지만 특별한 정제 작업이나 어떤 특성들을 조합하는 등의 작업을 위해 자신만의 변환기를 만들어야 할 때가 있습니다. 내가 만든 변환기를 (파이프라인과 같은) 사이킷런의 기능과 매끄럽게 연동하고 싶을 것입니다. 사이킷런은 (상속이 아닌) 덕 타이핑duck typing 42을 지원하므로 fit()(self를 반환), transform(), fit_transform() 메서드를 구현한 파이썬 클래스를 만들면 됩니다. 마지막 메서드는 TransformerMixin을 상속하면 자동으로 생성됩니다.43 또한 BaseEstimator를 상속하면(그리고 생성자에 *args나 **kargs를 사용하지 않으면) 하이퍼파라미터 튜닝에 필요한 두 메서드(get_params()와 set_params())를 추가로 얻게 됩니다.44 예를 들어 다음은 앞서 이야기한 조합 특성을 추가하는 간단한 변환기입니다.

from sklearn.base import BaseEstimator, TransformerMixin

rooms_ix, bedrooms_ix, population_ix, household_ix = 3, 4, 5, 6

class CombinedAttributesAdder(BaseEstimator, TransformerMixin):
    def __init__(self, add_bedrooms_per_room = True): # *args나 **kargs가 아닙니다.
        self.add_bedrooms_per_room = add_bedrooms_per_room

    def fit(self, X, y=None):
        return self # 더 할 일이 없습니다.
    def transform(self, X, y=None):
        rooms_per_household = X[:, rooms_ix] / X[:, household_ix]
        population_per_household = X[:, population_ix] / X[:, household_ix]
        if self.add_bedrooms_per_room:
            bedrooms_per_room = X[:, bedrooms_ix] / X[:, rooms_ix]
            return np.c_[X, rooms_per_household, population_per_household, bedrooms_per_room]
        else:
            return np.c_[X, rooms_per_household, population_per_household]

    attr_adder = CombinedAttributesAdder(add_bedrooms_per_room=False)
    housing_extra_attribs = attr_adder.transform(housing.values)

이 경우에는 변환기가 add_bedrooms_per_room 하이퍼파라미터 하나를 가지고 있고 기본값을 True로 지정합니다(합리적인 기본값을 주는 것이 좋습니다). 이 특성을 추가하는 것이 머신러닝 알고리즘에 도움이 될지 안 될지 이 하이퍼파라미터로 쉽게 확인해볼 수 있습니다. 일반적으로 100% 확신이 없는 모든 데이터 준비 단계에 대해 하이퍼파라미터를 추가할 수 있습니다. 이런 데이터 준비 단계를 자동화할수록 더 많은 조합을 자동으로 시도해볼 수 있고 최상의 조합을 찾을 가능성을 매우 높여줍니다(그리고 시간도 많이 절약됩니다).

 

2.5.4 특성 스케일링

데이터에 적용할 가장 중요한 변환 중 하나가 특성 스케일링feature scaling입니다. 몇 가지를 빼고는,45 머신러닝 알고리즘은 입력 숫자 특성들의 스케일이 많이 다르면 잘 작동하지 않습니다. 주택 가격 데이터도 이에 해당합니다. 즉, 전체 방 개수의 범위는 6에서 39,320인 반면 중간 소득의 범위는 0에서 15까지입니다. 타깃 값에 대한 스케일링은 일반적으로 불필요합니다.

모든 특성의 범위를 같도록 만들어주는 방법으로 min-max 스케일링과 표준화standardization가 널리 사용됩니다.

min-max 스케일링은 매우 간단합니다(많은 사람이 이를 정규화normalization 46라고 부릅니다). 0~1 범위에 들도록 값을 이동하고 스케일을 조정하면 됩니다. 데이터에서 최솟값을 뺀 후 최댓값과 최솟값의 차이로 나누면 이렇게 할 수 있습니다. 사이킷런에는 이에 해당하는 MinMaxScaler 변환기를 제공합니다. 0~1 사이를 원하지 않는다면 feature_range 매개변수로 범위를 변경할 수 있습니다.

표준화는 많이 다릅니다. 먼저 평균을 뺀 후(그래서 표준화를 하면 항상 평균이 0이 됩니다) 표준편차로 나누어 결과 분포의 분산이 1이 되도록 합니다. min-max 스케일링과는 달리 표준화는 범위의 상한과 하한이 없어 어떤 알고리즘에서는 문제가 될 수 있습니다(예를 들어 신경망은 종종 입력값의 범위로 0에서 1 사이를 기대합니다). 그러나 표준화는 이상치에 영향을 덜 받습니다. 예를 들어 중간 소득을 (잘못해서) 100이라 입력한 구역을 가정해봅시다. min-max 스케일링은 0~15 사이의 모든 다른 값을 0~0.15로 만들어버리겠지만, 표준화는 크게 영향받지 않습니다. 사이킷런에는 표준화를 위한 StandardScaler 변환기가 있습니다.

CAUTION_ 모든 변환기에서 스케일링은 (테스트 세트가 포함된) 전체 데이터가 아니고 훈련 데이터에 대해서만 fit() 메서드를 적용해야 합니다. 그런 다음 훈련 세트와 테스트 세트(그리고 새로운 데이터)에 대해 transform() 메서드를 사용합니다.

 

2.5.5 변환 파이프라인

앞서 보았듯이 변환 단계가 많으며 정확한 순서대로 실행되어야 합니다. 다행히 사이킷런에는 연속된 변환을 순서대로 처리할 수 있도록 도와주는 Pipeline 클래스가 있습니다. 다음은 숫자 특성을 처리하는 간단한 파이프라인입니다.

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

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

housing_num_tr = num_pipeline.fit_transform(housing_num)

Pipeline은 연속된 단계를 나타내는 이름/추정기 쌍의 목록을 입력으로 받습니다. 마지막 단계에는 변환기와 추정기를 모두 사용할 수 있고 그 외에는 모두 변환기여야 합니다(즉, fit_transform() 메서드를 가지고 있어야 합니다47). 이름은 무엇이든 상관없지만, 이중 밑줄 문자(__)는 포함하지 않아야 합니다.

파이프라인의 fit() 메서드를 호출하면 모든 변환기의 fit_transform() 메서드를 순서대로 호출하면서48 한 단계의 출력을 다음 단계의 입력으로 전달합니다. 마지막 단계에서는 fit() 메서드만 호출합니다.

파이프라인 객체는 마지막 추정기와 동일한 메서드를 제공합니다. 이 예에서는 마지막 추정기가 변환기 StandardScaler이므로 파이프라인이 데이터에 대해 모든 변환을 순서대로 적용하는 transform( ) 메서드를 가지고 있습니다(또한 fit( )과 transform( )을 차례대로 호출하는 대신에 사용할 수 있는 fit_transform( ) 메서드도 가지고 있습니다).

수치형 컬럼을 넘파이 배열로 추출하는 대신 판다스의 데이터프레임을 파이프라인에 직접 주입할 수 있다면 좋을 것입니다. 사이킷런이 판다스의 데이터프레임을 다룰 수는 없지만49 이를 처리하는 변환기를 직접 만들 수는 있습니다.

from sklearn.base import BaseEstimator, TransformerMixin

class DataFrameSelector(BaseEstimator, TransformerMixin):
    def __init__(self, attribute_names):
        self.attribute_names = attribute_names
    def fit(self, X, y=None):
        return self
    def transform(self, X):
        return X[self.attribute_names].values

DataFrameSelector는 나머지는 버리고 필요한 특성을 선택하여 데이터프레임을 넘파이 배열로 바꾸는 식으로 데이터를 변환합니다. 이를 이용해 데이터프레임을 받아 수치형만 다루는 파이프라인을 손쉽게 만들 수 있습니다. 수치형 특성을 선택한 DataFrameSelector로 파이프라인을 시작해서 앞서 이야기한 다른 전처리 단계들을 나열합니다. 범주형 특성을 다루는 또 다른 파이프라인도 DataFrameSelector로 범주형 특성을 선택하고 CategoricalEncoder를 적용하면 간단히 만들 수 있습니다.

num_attribs = list(housing_num)
cat_attribs = ["ocean_proximity"]

num_pipeline = Pipeline([
        ('selector', DataFrameSelector(num_attribs)),
        ('imputer', Imputer(strategy="median")),
        ('attribs_adder', CombinedAttributesAdder()),
        ('std_scaler', StandardScaler()),
    ])

cat_pipeline = Pipeline([
        ('selector', DataFrameSelector(cat_attribs)),
        ('cat_encoder', CategoricalEncoder(encoding="onehot-dense")),
    ])

하지만 어떻게 이 두 파이프라인을 하나의 파이프라인으로 합칠 수 있을까요? 정답은 사이킷런의 FeatureUnion입니다. 변환기 목록(또는 모두 변환기로 이뤄진 파이프라인)을 전달하고 transform() 메서드를 호출하면 각 변환기의 transform( ) 메서드를 병렬로 실행합니다. 그런 다음 각 변환기의 결과를 합쳐 반환합니다(물론 fit() 메서드를 호출하면 각 변환기의 fit()) 메서드를 실행합니다). 숫자형과 범주형 특성을 모두 다루는 전체 파이프라인은 다음과 같습니다.

from sklearn.pipeline import FeatureUnion

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

전체 파이프라인을 간단하게 실행할 수 있습니다.

>>> housing_prepared = full_pipeline.fit_transform(housing)
>>> housing_prepared
array([[-1.15604281, 0.77194962, 0.74333089, ..., 0. ,
         0.        , 0.        ],
       [-1.17602483, 0.6596948 , -1.1653172 , ..., 0. ,
         0.        , 0.        ],
       [...]
>>> housing_prepared.shape
(16512, 16)

 


 

31 옮긴이_ 훈련 세트에서 학습한 것이 소용없어지므로 테스트 세트의 중간값을 사용하면 안 됩니다.
32 설계 원칙에 대한 더 자세한 내용은 다음을 참고하세요. 「API design for machine learning software: experiences from the scikit-learn project」, L. Buitinck, G. Louppe, M. Blondel, F. Pedregosa, A. Müller, et al. (2013). http://goo.gl/wL10sI
33 옮긴이_ 인스턴스 변수는 객체지향 프로그래밍에서 객체가 각각 독립적으로 가지고 있는 변수입니다.
34 옮긴이_ 파이썬 객체를 만들 때 전달하는 매개변수를 말합니다(예를 들면 Imputer(strategy=”median”) ). 이 매개변수는 파이썬에서 새로운 객체가 생성될 때 자동으로 호출되는 특수 메서드인 init에 전달됩니다. 객체 생성 시 호출되는 또 다른 특수 메서드인 new도 있지만 종종 init를 생성자라고 부릅니다.
35 옮긴이_ imputer가 실제로 계산한 것은 데이터셋에 있는 각 특성의 중간값입니다. 사이킷런에서는 변환기도 추정기와 인터페이스가 같기 때문에 학습한다고 표현합니다.
36 어떤 예측기는 예측의 확신을 측정하는 메서드도 제공합니다. 옮긴이_ 분류 모델이 제공하는 predict_proba()나 decision_function() 메서드를 말합니다. 이 메서드들은 3장에서 자세히 소개합니다.
37 옮긴이_ 사실 파이썬에는 비공개(private) 인스턴스 변수가 없습니다. 따라서 모든 인스턴스 변수는 직접 참조가 가능합니다.
38 넘파이의 reshape( ) 함수에서 -1은 차원을 지정하지 않는다는 뜻입니다. 해당 차원의 크기는 전체 배열에서 다른 차원이 정해지고 남은 크기가 됩니다.
39 자세한 내용은 사이파이 문서를 참고하세요. 옮긴이_ housing_cat_1hot은 사이파이가 지원하는 희소 행렬 중 행을 압축하는 csr_matrix입니다. csr_matrix에서 지원하는 메서드는 다음 주소를 참고하세요. https://goo.gl/rakTep
40 옮긴이_ housing이 판다스 데이터프레임이므로 pd.get_dummies(housing)처럼 텍스트 특성을 원-핫 벡터로 간단하게 변환할 수 있습니다. get_dummies( ) 함수는 데이터프레임에서 텍스트 특성을 가진 열을 찾아 자동으로 원-핫 인코딩을 적용하고 변환된 데이터프레임을 반환합니다.
41. 옮긴이_ 사이킷런 0.20 릴리스에 추가될 CategoricalEncoder는 OrdinalEncoder와 새로운 OneHotEncoder로 리팩토링되었습니다. 새로운 클래스를 사용한 예는 깃허브 노트북을 참고해주세요
42 옮긴이_ 덕 타이핑은 상속이나 인터페이스 구현이 아니라 객체의 속성이나 메서드가 객체의 유형을 결정하는 식을 말합니다.
43 옮긴이_ 파이썬에서 이름에 Mixin이 있으면 객체의 기능을 확장하려는 목적으로 만들어진 클래스를 나타냅니다. TransformerMixin은 fit_transform() 메서드 하나를 가지고 있으며 이를 상속하는 모든 파이썬 클래스에 이 메서드를 제공합니다. TransformerMixin의 fit_transform() 메서드는 단순히 fit()과 transform()을 메서드 연결(method chaining)한 것입니다.
44 옮긴이_ get_params()와 set_params() 함수는 사이킷런의 파이프라인과 그리드 탐색에 꼭 필요한 메서드이므로 모든 추정기와 변환기는 BaseEstimator를 상속해야 합니다. 이 두 메서드는 생성자에 명시된 매개변수만을 참조하므로 *args나 **kargs는 사용할 수 없습니다. 더 자세한 내용은 사이킷런 문서를 참고하세요. https://goo.gl/fkQWsN
45 옮긴이_ 6장과 7장에서 다루는 트리 기반 알고리즘이 이에 해당합니다.
46 옮긴이_ 사이킷런에는 입력 데이터에서 각 행의 \ell_2 노름이 1이 되도록 조정하는 Normalizer라는 전처리 기능이 있으며 min-max 스케일링과는 전혀 다른 결과를 만듭니다. 정규화는 여러 의미로 다양하게 사용되므로 혼동하지 마세요.
47 옮긴이_ 또는 fit()과 transform() 메서드만 가지고 있어도 됩니다.
48 옮긴이_ fit_transform() 메서드가 없다면 fit()과 transform()을 차례로 호출합니다.
49 하지만 사이킷런 깃허브의 #3886 풀 리퀘스트(Pull Request #3886)를 보면 특성별 변환을 수행할 수 있는 ColumnTransformer가 준비되고 있습니다. pip3 install sklearn-pandas 명령으로 비슷한 목적을 가진 DataFrameMapper를 얻을 수도 있습니다. 옮긴이_ #3886 풀 리퀘스트는 #9012로 이어져 마스터 브랜치에 병합되었고 0.20 릴리스에 포함될 예정입니다.

 

2.4 데이터 이해를 위한 탐색과 시각화 | 목차 | 2.6 모델 선택과 훈련

 

이 글은 한빛미디어에서 출간한  “핸즈온 머신러닝“의 1장과 2장입니다. 이 책의 저작권은 한빛미디어(주)에 있으므로 무단 복제 및 무단 전제를 금합니다.

2.5 머신러닝 알고리즘을 위한 데이터 준비”에 대한 7개의 생각

  1. 윤영선

    안녕하세요, 저자님. 번번이 감사합니다. 여쭤볼게있는데요. 중간부분에

    CAUTION_ 모든 변환기에서 스케일링은 (테스트 세트가 포함된) 전체 데이터가 아니고 훈련 데이터에 대해서만 fit() 메서드를 적용해야 합니다. 그런 다음 훈련 세트와 테스트 세트(그리고 새로운 데이터)에 대해 transform() 메서드를 사용합니다.

    이 내용에서 X_train과 X_test 을 합한 데이터로 fit을 하는게 아니라, X_train으로만 fit 하는 이유가 궁금합니다. 그냥 전체로 하는게 맞지 않나 하는 생각이 들어서 여쭤봅니다.

    좋아요

    응답
    1. 박해선 글의 글쓴이

      안녕하세요. 전체 데이터로 전처리를 하게 되면 테스트 세트에 대해 낙관적인 추정을 하게 됩니다. 전처리 방식에 대한 자세한 내용은 3장과 5장을 참고하시면 도움이 되실 것 같네요. 🙂

      좋아요

      응답
  2. 김동선

    cannot import name ‘CategoricalEncoder’ from ‘sklearn.preprocessing’

    이와 같은 에러가 낫을 경우에는 어떻게 해결할 수 있을가요?

    좋아요

    응답
      1. 박해선 글의 글쓴이

        그런데 이 문서를 수정할 수가 없네요. 워드프레스가 업데이트되면서 예전에 작성했던 문서를 제대로 편집하지 못합니다. ㅠ.ㅠ

        좋아요

댓글 남기기

이 사이트는 스팸을 줄이는 아키스밋을 사용합니다. 댓글이 어떻게 처리되는지 알아보십시오.