카테고리 보관물: scikit-learn

“핸즈온 머신러닝” 사이킷런 0.20 업데이트

사이킷런 0.20 버전에 맞추어 <핸즈온 머신러닝> 도서에 반영될 내용을 정리하였습니다. 깃허브 주피터 노트북에는 더 많은 내용이 반영되어 있습니다! 🙂

  • sklearn.preprocessing.Imputer 클래스는 사이킷런 0.22 버전에서 삭제될 예정입니다. 대신 0.20 버전에서 추가된 sklearn.impute.SimpleImputer 클래스로 변경합니다.
    • (p100) 두 번째 문단 시작 부분에 “사이킷런의 Imputer는 누락된 … 지정하여 Imputer의 객체를 생성합니다.”를 “사이킷런의 SimpleImputer는 누락된 … 지정하여 SimpleImputer의 객체를 생성합니다.”로 변경합니다. 첫 번째 코드 블럭에서
      from sklearn.preprocessing import Imputer
      imputer = Imputer(strategy=”median”)

      from sklearn.impute import SimpleImputer
      imputer = SimpleImputer(strategy=”median”)
      로 변경합니다.
    • (p101) 주석 34의 첫 문장에서 ‘(예를 들면 Imputer(strategy=”median”) )’를 ‘(예를 들면 SimpleImputer(strategy=”median”) )’로 변경합니다.
    • (p108, 109) 파이프라인 정의 코드에서 ‘Imputer(strategy=”median”)’을 ‘SimpleImputer(strategy=”median”)’로 변경합니다.
  • OneHotEncoder 클래스가 종전에는 훈련 데이터에 나타난 0~최댓값 사이 범위를 카테고리로 인식하여 원-핫 인코딩하지만 앞으로는 고유한 정수 값 또는 문자열을 원-핫 인코딩할 수 있습니다. 정수 특성과 문자열 특성이 함께 있는 경우에는 에러가 발생합니다. 경고 메세지를 피하고 고유한 값을 사용하는 방식을 선택하기 위해 categories 매개변수를 'auto'로 지정합니다.
    • (p103) 마지막 코드 블럭에서 encoder = OneHotEncoder()를 encoder = OneHotEncoder(categories='auto')로 변경합니다.
  • 0.22 버전에서 RandomForestClassifierRandomForestRegressor 모델의 n_estimators 기본값이 10에서 100으로 늘어납니다. 경고 메세지를 피하기 위해 명시적으로 트리 개수를 10으로 지정합니다.
    • (p114, p116) 코드 블럭에서 RandomForestRegressor()를 RandomForestRegressor(n_estimators=10)으로 변경합니다.
    • (p139, p244) 코드 블럭에서 RandomForestClassifier()를 RandomForestClassifier(n_estimators=10)으로 변경합니다.
  • 공개된 훈련 데이터를 다운로드 받는 fetch_mldata 함수가 mldata.org 사이트의 잦은 에러로 openml.org 를 사용하는 fetch_openml 함수로 변경되었습니다.
    • (p124) mnist = fetch_mldata('MNIST original')을 mnist = fetch_openml('mnist_784', version=1)로 변경합니다. openml.org의 MNIST 타깃 데이터는 문자열로 저장되어 있으므로 mnist.target = mnist.target.astype(np.int)와 같이 정수로 바꾸는 것이 좋습니다.
  • 사이킷런 0.22 버전에서 LogisticRegression 클래스의 solver 매개변수 기본값이 'liblinear'에서 'lbfgs'로 변경될 예정입니다. 경고 메세지를 피하고 출력 결과를 일관되게 유지하기 위하여 solver 매개변수를 'liblinear'로 설정합니다.
    • (p192, p244) LogisticRegression()을 LogisticRegression(solver='liblinear')로 변경합니다.
  • SVCSVR ​클래스의 gamma 매개변수 옵션에 'auto'외에 'scale'이 추가되었습니다. 'auto'는 1/n_features, 즉 특성 개수의 역수입니다. 'scale'은 1/(n_features * X.std())로 스케일 조정이 되지 않은 특성에서 더 좋은 결과를 만듭니다. 사이킷런 0.22 버전부터는 gamma 매개변수의 기본값이 'auto'에서 'scale'로 변경됩니다. 서포트 벡터 머신을 사용하기 전에 특성을 표준화 전처리하면 'scale'과 'auto'는 차이가 없습니다. 경고를 피하기 위해 명시적으로 'auto' 옵션을 지정합니다.
    • (p213) 맨 아래 코드 블럭에서 SVR(kernel="poly", degree=2, C=100, epsilon=0.1)SVR(kernel="poly", gamma='auto', degree=2, C=100, epsilon=0.1)로 변경합니다.
    • (p244) SVC()를 SVC(gamma='auto')로 변경합니다.
  • LinearSVC의 verbose 매개변수가 0이 아닐 때 max_iter 반복 횟수가 부족하면 경고 메세지가 출력됩니다. 사이킷런 0.20 버전부터는 verbose 매개변수에 상관없이 max_iter 반복 안에 수렴하지 않을 경우 반복 횟수 증가 경고가 나옵니다. 경고 메세지를 피하기 위해 max_iter 매개변수의 기본값을 1,000에서 2,000으로 증가시킵니다.
    • (p206) LinearSVC(C=10, loss="hinge")를 LinearSVC(C=10, loss="hinge", max_iter=2000)으로 변경합니다.

“파이썬 라이브러리를 활용한 머신러닝” 사이킷런 0.20 업데이트

사이킷런 0.20 버전이 릴리스되었습니다. <파이썬 라이브러리를 활용한 머신러닝> 도서에 영향을 미치는 부분을 정리하여 에러타로 등록하였습니다. 깃허브의 코드도 최신 라이브러리 버전에서 모두 재실행하여 커밋하였습니다. 자세한 변경 내용은 <파이썬 라이브러리를 활용한 머신러닝>의 에러타 페이지를 참고해 주세요. 다음은 주요 변경 내용입니다.

  • 사이킷런 0.19 버전 이하에서는 LinearSVC와 liblinear를 사용하는 LogisticRegression의 verbose 매개변수가 0이 아니고 max_iter 반복 안에 수렴하지 않을 경우 반복 횟수를 증가하라는 경고 메세지가 나옵니다. 사이킷런 0.20 버전부터는 verbose 매개변수에 상관없이 max_iter 반복 안에 수렴하지 않을 경우 반복 횟수 증가 경고가 나옵니다. 경고 메세지를 피하기 위해 max_iter 매개변수의 기본값을 증가시킵니다.
  • 향후 사이킷런 0.22 버전에서 LogisticRegression 클래스의 solver 매개변수 기본값이 liblinear에서 lbfgs로 변경될 예정입니다. 사이킷런 0.20 버전에서 solver 매개변수를 지정하지 않는 경우 이에 대한 경고 메세지를 출력합니다. 경고 메세지를 피하고 출력 결과를 일관되게 유지하기 위하여 solver 매개변수를 liblinear로 설정합니다.
  • 사이킷런 0.20 버전에서 LogisticRegression의 multi_class 매개변수 옵션에 auto가 추가되었습니다. auto로 설정하면 이진 분류이거나 solver가 liblinear일 경우에는 ovr을 선택하고 그 외에는 multinomial을 선택합니다. 사이킷런 0.22 버전부터는 multi_class 매개변수의 기본값이 ovr에서 auto로 변경됩니다. 경고 메세지를 피하기 위해 명시적으로 ovr 옵션을 지정합니다.
  • 사이킷런 0.20 버전에서 SVC ​클래스의 gamma 매개변수 옵션에 auto외에 scale이 추가되었습니다. auto는 1/n_features, 즉 특성 개수의 역수입니다. scale은 1/(n_features * X.std())로 스케일 조정이 되지 않은 특성에서 더 좋은 결과를 만듭니다. 사이킷런 0.22 버전부터는 gamma 매개변수의 기본값이 auto에서 scale로 변경됩니다. 서포트 벡터 머신을 사용하기 전에 특성을 표준화 전처리하면 scale과 auto는 차이가 없습니다. 경고를 피하기 위해 명시적으로 auto 옵션을 지정합니다.
  • 사이킷런 0.22 버전에서 OneHotEncoder 클래스가 데이터에서 정수 카테고리를 인식하는 방식이 변경될 예정입니다. 종전에는 훈련 데이터에 나타난 0~최댓값 사이 범위를 카테고리로 인식하여 원-핫 인코딩하지만 0.22 버전부터는 고유한 정수 값을 카테고리로 사용합니다. 후자의 경우 0~최댓값 사이의 정수라도 훈련 데이터에 없는 값을 변환하려면 에러가 발생합니다. 경고 메세지를 피하고 고유한 정수 값을 사용하는 방식을 선택하려면 categories 매개변수를 auto로 지정합니다.
  • 사이킷런 0.22 버전에서 cross_val_score 함수와 GridSearchCV 클래스의 cv 매개변수 기본값이 3에서 5로 바뀔 예정입니다. 0.20 버전에서 cv 매개변수를 지정하지 않는 경우 이에 관한 경고 메세지가 출력됩니다. 경고 메세지를 피하기 위해 cv 매개변수 값을 명시적으로 3으로 지정합니다.
  • 사이킷런 0.22 버전부터는 GridSearchCV와 RandomizedSearchCV의 iid 매개변수 기본값이 True에서 False로 바뀝니다. 0.24 버전에서는 이 매개변수가 아예 삭제될 예정입니다. iid 매개변수가 True이면 독립 동일 분포라고 가정하고 테스트 세트의 샘플 수로 폴드의 점수를 가중 평균합니다. False로 지정하면 단순한 폴드 점수의 평균입니다. False일 때 기본 교차 검증과 동작 방식이 같습니다. 사이킷런 0.20 버전에서 iid 매개변수가 기본값일 때 가중 평균과 단순 평균의 차이가 10^-4 이상이면 경고 메세지가 발생합니다. 경고 메세지를 피하기 위해 GridSearchCV의 iid 매개변수를 True로 설정합니다.

Tensorflow 1.11.0 & Scikit-Learn 0.20.0 Release

텐서플로 1.11.0사이킷런 0.20.0 버전이 릴리즈되었습니다.

텐서플로 1.11.0부터는 cudnn 7.2 버전으로 패키징이 되어 있습니다. cudnn은 NVIDIA 개발자 사이트에서 다운로드 받을 수 있습니다. CUDA 9.0과 cudnn 7.3 버전에서 정상 작동됩니다. 텐서플로는 pip 명령으로 설치할 수 있습니다. 파이썬 2.7(윈도우즈제외), 3.5, 3.6 버전을 지원합니다.

$ pip install --upgrade tensorflow
$ pip install --upgrade tensorflow-gpu

사이킷런 0.20.0은 pipconda를 사용하여 설치할 수 있습니다.

$ conda update scikit-learn
$ pip install --upgrade scikit-learn

Scikit-Learn 0.20 RC1 Release

사이킷런 0.20 버전이 예상대로 가을에 출시될 것 같네요. 0.20 RC1 버전이 릴리즈되었습니다.

conda install scikit-learn=0.20rc1 -c conda-forge/label/rc -c conda-forge
# 또는
pip install --pre scikit-learn

0.20 버전에 추가, 변경된 내용이 많습니다. 전체 변경 내용은 릴리즈 노트를 참고하세요. 그중에서도 가장 필요했던 것이 판다스 데이터를 그대로 주입해 전처리할 수 있는 ColumnTransformer가 아닐까 싶습니다. 핸즈온 머신러닝 2장 노트북에는 이미 적용되어 있습니다. 🙂

0.20 버전의 중요 기능을 정리하고 “파이썬 라이브러리를 활용한 머신러닝“의 내용도 보강해야 겠네요. 덤으로 scipy-lectures.org 도 새로 릴리즈 되었습니다!

TensorFlow 1.10.0 RC0 Release

텐서플로 1.10 RC 버전이 릴리즈되었습니다. 1.9버전이 나온지 정말 며칠되지 않았는데 말이죠. 1.10버전부터 NVIDIA NCCL 2.2 버전을 사용합니다. 2개 이상의 GPU를 사용하는 경우 NCCL 라이브러리를 업데이트해야 합니다. 텐서플로 1.10 RC 버전은 pip 명령을 사용해 설치할 수 있습니다.

$ pip install --upgrade --pre tensorflow
$ pip install --upgrade --pre tensorflow-gpu

(업데이트) RC1 버전이 릴리즈되었습니다.

사이킷런도 0.20 버전을 준비중입니다. 아마 가을에는 릴리즈되지 않을까 생각됩니다.

최근 사이킷런에서 리팩토링된 코드 중에서 습관적으로 사용하던 np.ones(), np.zeros()np.full()로 바꾼 것이 눈에 띄입니다. 무심코 다음처럼 비효율적인 코드를 쓰게 됩니다.

np.ones((3,2)) * -1

다음과 같이 쓰는게 훨씬 직관적이고 효율적입니다. 🙂

np.full((3,2), -1.)

“핸즈온 머신러닝” 주피터 노트북 업데이트 안내

핸즈온 머신러닝“의 3장, 11장 주피터 노트북이 조금 업데이트되었습니다.

  • 3장: 연습문제 3번의 답에 서포트 벡터 머신과 랜덤 포레스트의 결과를 박스 플롯(boxplot)으로 비교하는 셀이 추가되었습니다. 다음 스샷을 참고해 주세요.

  • 11장: SELU 활성화 함수에 대한 설명이 보강되었습니다. 다음 스샷을 참고해 주세요.


감사합니다! 🙂

[핸즈온 머신러닝] 업데이트 안내해 드립니다.

핸즈온 머신러닝” 도서의 수정 사항에 대해 안내해 드립니다. 최근 원서 깃허브에 여러가지 내용이 추가 되어서 이를 번역서 깃허브에 반영하였습니다. 본문 내용에 영향이 있는 것은 에러타로 등록하였습니다. 도서를 구매하셨다면 꼭 확인 부탁드립니다. 주요한 변경 사항은 다음과 같습니다.

  • 7장의 연습문제 8, 9번의 답이 추가되었습니다.
  • 16장의 연습문제 8번의 답이 추가되었습니다.
  • 2장 3장에 범주형 변수의 인코딩을 위해 OrdinalEncoder와 OneHotEncoder를 사용하는 예가 추가되었습니다(사이킷런 0.20에 추가될 예정인 CategoricalEncoder가 두 개의 클래스로 리팩토링되었습니다). 그리고 두 클래스를 future_encoders.py 로 분리했습니다.
  • 2장에 신뢰 구간을 구하는 예가 추가되었습니다.
  • 7장에 XGBoost 예가 추가되었습니다.
  • 10장에 tf.contrib.learn 외에 tf.estimator를 사용한 예가 추가되었습니다.
  • 12장에 tf.data 를 사용한 예가 추가되었습니다.
  • 16장에 넘파이 배열을 사용한 재현 메모리 구현 예가 추가되었습니다.
  • tf.examples.tutorials.mnist 가 deprecated 될 예정이므로 Keras에 포함된 MNIST 함수를 사용하도록 바꾸었습니다.
  • 텐서보드를 주피터 노트북에 표현하기 위해 추가했던 코드를 tensorflow_graph_in_jupyter.py 파일로 분리했습니다.
  • 9장에 있던 자동 미분 예를 extra_autodiff.ipynb로 분리했습니다. 이 노트북의 번역을 완료하여 업데이트했습니다.

아직 번역하지 못한 extra 노트북이 여러개 남아 있습니다. 꾸준히 작업하고 있으니 조금만 기다려 주세요. 감사합니다!

‘핸즈온 머신러닝’이 출간되었습니다.

b9267655530_lHands-On Machine Learning with Scikit-Learn & TensorFlow의 번역서 ‘핸즈온 머신러닝‘이 출간되었습니다!

그 동안 이 작업을 하면서 많은 것을 배웠습니다. 모쪼록 다른 누군가에게도 도움이 된다면 다행입니다.

원래 번역서 제목이 ‘사이킷런과 텐서플로를 활용한 머신러닝, 딥러닝 실무’ 정도로 예상되었는데 출간 직전에 ‘핸즈온 머신러닝’으로 변경되었습니다. 개인적으로는 단순하고 평소에도 부르는 이름이라 만족입니다. 🙂 혹시 이 책에 관해 궁금한 점 있으면 언제든지 댓글이나 메일 주세요.

마지막으로 책을 만드는 데 도움을 주신 많은 분들께 다시 한번 감사드립니다.

(저자 오렐리앙도 아주 기뻐하네요. ㅎ)

결정 트리와 불순도에 대한 궁금증

이 글은 세바스찬 라쉬카의 머신러닝 FAQ 글(Why are implementations of decision tree algorithms usually binary and what are the advantages of the different impurity metrics?)을 번역한 것입니다.

결정 트리 알고리즘은 왜 이진 트리로 구현되어 있을까요? 각 불순도 지표들의 장점은 무엇인가요?

현실적인 이유로(조합의 폭발적인 증가combinatorial explosion) 대부분의 라이브러리들은 결정 트리를 이진 트리로 구현합니다. 좋은 점은 이진 트리가 NP-완전 문제NP-complete라는 것입니다(Hyafil, Laurent, and Ronald L. Rivest. “Constructing optimal binary decision trees is NP-complete.” Information Processing Letters 5.1 (1976): 15-17.).

(CARTClassification And Regression Tree 알고리즘의) 목적 함수는 각 분할에서 정보 이득information gain(IG)을 최대화하는 것입니다:

IG(D_p, f) = I(D_p) - \sum_{j=1}^{m}\dfrac{N_j}{N}I(D_j)

는 분할에 사용되는 특성이고 D와 D는 각각 부모 노드와 번째 자식 노드의 데이터셋입니다. 는 불순도 지표입니다. N 은 샘플의 전체 개수이고 Njj 번째 자식 노드의 샘플 개수입니다. 이제 분류에서 가장 널리 사용되는 (CART 알고리즘의) 분할 기준을 살펴 보겠습니다. 간단하게 이진 분할로 식을 표현하지만 당연히 다중 분할로 일반화될 수 있습니다. 이진 분할에 대한 IG 는 다음과 같이 계산합니다:

IG(D_p, a) = I(D_p) - \dfrac{N_{left}}{N}I(D_{left}) - \dfrac{N_{right}}{N}I(D_{right})

이진 결정 트리에서 가장 널리 사용되는 불순도 지표 또는 분할 기준은 지니 불순도Gini impurity(IG)와 엔트로피Entropy(IH)와 분류 오차Classification Error(IE)입니다. 엔트로피의 정의부터 살펴보죠. 다음과 같습니다.

I_H(t) = - \sum_{i=1}^c p(i|t)\,log_2\,p(i|t)

클래스에 샘플이 하나라도 있다면

p(i|t) \ne 0

이고 p(i|t) 는 특정 노드 t 에서 클래스 c 에 속한 샘플의 비율입니다. 그러므로 한 노드의 샘플이 모두 동일한 클래스에 속한다면 엔트로피는 0입니다. 클래스 별로 균등하게 분포되어 있다면 당연하게 엔트로피는 최대가 됩니다. 지니 불순도는 잘 못 분류될 확률을 최소화시키려는 기준으로 생각할 수 있습니다.

I_G(t) = \sum_{i=1}^c p(i|t)(1-p(i|t)) = 1 - \sum_{i=1}^c p(i|t)^2

엔트로피와 비슷하게 지니 불순도는 클래스가 균일하게 섞여 있을 때 최대가 됩니다. 그러나 실제로 지니 불순도와 엔트로피는 매우 비슷한 결과를 만들며 불순도 기준을 사용하여 트리를 평가하는데 시간을 들이는 것보다 가지치기pruning 방식을 바꿔보는 것이 더 낫습니다. 또 다른 불순도 지표는 분류 오차입니다.

I_E = 1 - \text{max}\{ p(i|t) \}

가지치기에는 좋은 지표지만 노드의 클래스 확률 변화에 덜 민감하기 때문에 결정 트리를 구성하는데는 적합하지 않습니다.

overview-plot

분류 오차가 클래스 확률 변화에 왜 덜 민감한지 보기 위해 다음 그림에서 두 개의 분할 사례를 살펴 보겠습니다.

split

클래스 1에 40개의 샘플, 클래스 2에 40개의 샘플을 가진 부모 노드의 데이터셋 Dp 를 각각 두 개의 데이터셋 Dleft 와 Dright 로 나누었습니다. 분류 오차를 분할 기준으로 사용했을 때 정보 이득은 AB 의 경우 모두 같습니다(IGE = 0.25):

I_E(D_p) = 1 - \text{max}(0.5 + 0.5) = 0.5

A:

I_E(D_{left}) = 1 - \text{max}(0.75, 0.25) = 0.25

I_E(D_{right}) = 1 - \text{max}(0.25, 0.75) = 0.25

IG_E = 0.5 - \dfrac{40}{80}\times0.25-\dfrac{40}{80}\times0.25 = 0.25

B:

I_E(D_{left}) = 1 - \text{max}(\dfrac{20}{60},\dfrac{40}{60}) = \dfrac{1}{3}

I_E(D_{right}) = 1 - \text{max}(1, 0) = 0

IG_E = 0.5 - \dfrac{60}{80}\times\dfrac{1}{3}-\dfrac{20}{80}\times0 = 0.25

하지만 지니 불순도 기준의 IG는 A(0.125) 보다 B(0.1666) 가 더 순수하기 때문에 높습니다.

I_G(D_p) = 1 - (0.5^2 + 0.5^2) = 0.5

A:

I_G(D_{left}) = 1 - \left( \left(\dfrac{3}{4}\right)^2 + \left(\dfrac{1}{4}\right)^2 \right) = \dfrac{3}{8} = 0.375

I_G(D_{right}) = 1 - \left( \left(\dfrac{1}{4}\right)^2 + \left(\dfrac{3}{4}\right)^2 \right) = \dfrac{3}{8} = 0.375

IG_G = 0.5 - \dfrac{40}{80}\times0.375 - \dfrac{40}{80}\times0.375 = 0.125

B:

I_G(D_{left}) = 1 - \left( \left(\dfrac{2}{6}\right)^2 + \left(\dfrac{4}{6}\right)^2 \right) = \dfrac{4}{9}

I_G(D_{right}) = 1 - \left( \left(\dfrac{2}{2}\right)^2 + \left(\dfrac{0}{2}\right)^2 \right) = 1 - 1 = 0

IG_G = 0.5 - \dfrac{60}{80}\times\dfrac{4}{9} - \dfrac{40}{80}\times0 = 0.1666

비슷하게 엔트로피 기준은 A(0.19) 보다 B(0.31)를 선호합니다.

I_H(D_p) = - (0.5\,log_2\,(0.5) + 0.5\,log_2(0.5)) = 1

A:

I_H(D_{left}) = - \left( \dfrac{3}{4}\,log_2\left(\dfrac{3}{4}\right) + \dfrac{1}{4}\,log_2\left(\dfrac{1}{4}\right) \right) = 0.81

I_H(D_{right}) = - \left( \dfrac{1}{4}\,log_2\left(\dfrac{1}{4}\right) + \dfrac{3}{4}\,log_2\left(\dfrac{3}{4}\right) \right) = 0.81

IG_H = 1 - \dfrac{40}{80}\times0.81 - \dfrac{40}{80}\times0.81 = 0.19

B:

I_H(D_{left}) = - \left( \dfrac{2}{6}\,log_2\left(\dfrac{2}{6}\right) + \dfrac{4}{6}\,log_2\left(\dfrac{4}{6}\right) \right) = 0.92

I_H(D_{right}) = - \left( \dfrac{2}{2}\,log_2\left(\dfrac{2}{2}\right) + \dfrac{0}{2}\,log_2\left(\dfrac{0}{2}\right) \right) = 0

IG_G = 1 - \dfrac{60}{80}\times0.92 - \dfrac{40}{80}\times0 = 0.31

지니 불순도와 엔트로피에 대해 덧붙이자면 위에 언급한 것처럼 만들어진 트리는 실제 매우 비슷합니다. 지니 불순도의 장점은 로그를 계산할 필요가 없어서 구현 성능이 조금 더 낫다는 것입니다.

옮긴이: 위 그림을 보면 엔트로피보다 지니 불순도 방식이 불순도 값을 줄이기 위해 더 클래스 확률을 낮추어야 함을 알 수 있습니다. 즉 엔트로피 방식이 조금 더 균형잡힌 트리를 만들 가능성이 높습니다. scikit-learn의 DecisionTreeClassifier와 DecisionTreeRegressor 및 이들을 사용하는 랜덤 포레스트와 그래디언트 부스팅에서 특성 중요도 속성은(feature_importances_) 트리가 분할에 사용한 특성별로 발생되는 모든 정보 이득을 더하고 전체 특성 중요도의 합이 1이 되도록 정규화한 것입니다.