카테고리 보관물: Python

QuantileTransformer

Scikit-Learn 0.19 버전에 추가된 기능 중 오늘은 QuantileTransformer() 변환기를 살펴 보겠습니다. 먼저 ‘파이썬 라이브러리를 활용한 머신러닝‘ 3장에 있는 스케일 조정의 예제와 비슷한 데이터 셋을 make_blobs 함수로 만들겠습니다. 여기서는 샘플 개수가 어느 정도 되어야 눈으로 확인하기 좋으므로 500개를 만들겠습니다.

X, y = make_blobs(n_samples=500, centers=2, random_state=4)
plt.scatter(X[:, 0], X[:, 1], c=y, edgecolors='black')

quantile-1

QuantileTransformer 는 지정된 분위수에 맞게 데이터를 변환합니다. 기본 분위수는 1,000개이며 n_quantiles 매개변수에서 변경할 수 있습니다. 여기서는 100개 정도로 지정해 보겠습니다.

quan = QuantileTransformer(n_quantiles=100)

fit() 메서드에서 입력 데이터의 범위를 분위수에 맞게 나누어 quantiles_ 속성에 저장합니다. 이를 위해 넘파이 percentile() 함수를 사용하여 분위에 해당하는 값을 손쉽게 구할 수 있습니다. QuantileTransformer 에는 기본값이 100,000인 subsample 매개변수가 있습니다.  만약 입력 데이터 개수가 subsample 보다 크면 계산량을 줄이기 위해 subsample 개수만큼 데이터를 샘플링하여 percentile() 함수를 적용합니다. percentile() 함수는 특성마다 각각 적용되므로 quantiles_ 속성의 크기는 [n_quantiles, X.shape[1]] 이 됩니다.

quan.fit(X)
print(quan.quantiles_.shape)
(100, 2)

transform() 메서드에서는 데이터를 quantiles_를 기준으로 하여 0~1 사이로 매핑합니다. 이를 위해 넘파이 interp() 함수를 사용합니다. 두 개의 특성이 모두 0~1 사이로 균등하게 나뉘어진 것을 그래프로 확인할 수 있습니다.

X_quan = quan.transform(X)
plt.scatter(X_quan[:, 0], X_quan[:, 1], c=y, edgecolors='black')

quantile-2

이런 변환은 RobustScaler와 비슷하게 이상치에 민감하지 않게 됩니다. 하지만 균등 분포라서 무조건 [0, 1] 사이로 클리핑합니다.

사실 transform() 메서드에서는 scipy.stats.uniform.ppf() 함수를 사용하여 균등 분포로 변환합니다. 하지만 interp() 함수에서 동일한 변환을 이미 하고 있기 때문에 효과가 없습니다. QuantileTransformer 에서 output_distribution=’normal’ 로 지정하면 scipy.stats.norm.ppf() 함수를 사용하여 정규 분포로 변환합니다.

quan = QuantileTransformer(output_distribution='normal', n_quantiles=100)
X_quan = quan.fit_transform(X)
plt.scatter(X_quan[:, 0], X_quan[:, 1], c=y, edgecolors='black')

quantile-3

변환된 데이터는 평균이 0, 표준편차가 1인 정규 분포임을 확인할 수 있습니다.

X_quan.mean(axis=0), X_quan.std(axis=0)
(array([-0.00172502, -0.00134149]), array([ 1.0412595 ,  1.03818794]))

StandardScaler 와 비교해 보면 평균 과 표준편차는 같지만 정규 분포를 따르지 않는 분포에서 차이를 확인할 수 있습니다. 🙂

from sklearn.preprocessing import StandardScaler
X_std = StandardScaler().fit_transform(X)
plt.scatter(X_std[:, 0], X_std[:, 1], c=y, edgecolors='black')

quantile-4

이 글의 샘플 코드는 ‘파이썬 라이브러리를 활용한 머신러닝‘ 깃허브(https://github.com/rickiepark/introduction_to_ml_with_python/blob/master/QuantileTransformer.ipynb)에서 확인할 수 있습니다.

더욱 랜덤한 포레스트-익스트림 랜덤 트리(ExtraTreesClassifier)

파이썬 라이브러리를을 활용한 머신러닝‘ 2장의 지도학습에서 대표적인 앙상블 모델로 랜덤 포레스트를 소개하고 있습니다. 랜덤 포레스트는 부스트랩 샘플과 랜덤한 후보 특성들을 사용해 여러개의 결정 트리decision tree를 앙상블 합니다. 그래서 훈련 데이터에 과대적합을 막아주고 모델의 일반화 성능이 항상 단일 트리보다 높습니다. 랜덤 포레스트 모델의 변종으로 익스트림 랜덤 트리extremely randomized trees 혹은 엑스트라 트리ExtraTrees라 부르는 모델이 있습니다. 엑스트라 트리는 포레스트 트리의 각 후보 특성을 무작위로 분할하는 식으로 무작위성을 증가 시킵니다. Scikit-Learn은 앙상블 패키지 안에 엑스트라 트리 모델을 제공합니다.

from sklearn.ensemble import ExtraTreesClassifier

​RandomForestClassifier 클래스가 사용하는 결정 트리는 DecisionTreeClassifier입니다. 이에 반해 ExtraTreesClassifier가 사용하는 결정 트리는 ExtraTreeClassifier입니다. 이름이 매우 비슷하니 유의하세요. ExtraTreesClassifier의 매개변수는 RandomForestClassifier와 동일합니다. 책에서와 같이 make_moons 데이터셋에 엑스트라 트리를 학습시켜 보겠습니다.

X, y = make_moons(n_samples=100, noise=0.25, random_state=3)
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y, 
                                                    random_state=42)

xtree = ExtraTreesClassifier(n_estimators=5, random_state=2)
xtree.fit(X_train, y_train)

엑스트라 트리가 사용하는 ExtraTreeClassifier()의 기본값으로 베이스 트리가 만들어 집니다. 랜덤 포레스트와 같이 베이스 모델을 직접 만들어 주입할 수는 없습니다. 엑스트라 트리가 만든 베이스 트리와 전체의 결정 경계를 그려 보겠습니다.

extratrees

그래프에서 볼 수 있듯이 랜덤 포레스트가 만든 것보다 두 클래스의 경계를 잘 구분하고 있습니다. 사실 엑스트라 트리의 베이스 트리인 ExtraTreeClassifier는 DecisionTreeClassifier를 상속한 것이며 splitter=’best’가 아니고 splitter=’random’인 것과 max_features=’auto’인 것을 제외하고는 동일합니다.

이번에는 cancer 데이터셋에 적용해 보겠습니다.

X_train, X_test, y_train, y_test = train_test_split(cancer.data, cancer.target, 
                                                    random_state=0)
xtree = ExtraTreesClassifier(n_estimators=100, random_state=0)
xtree.fit(X_train, y_train)

print("훈련 세트 정확도: {:.3f}".format(xtree.score(X_train, y_train)))
print("테스트 세트 정확도: {:.3f}".format(xtree.score(X_test, y_test)))

훈련 세트 정확도: 1.000
테스트 세트 정확도: 0.972

훈련 세트와 테스트 세트에서의 정확도는 랜덤 포레스트와 동일합니다. 하지만 특성 중요도를 그려보면 차이점을 발견할 수 있습니다.

extratree_feature_importance_

이 그래프에서 볼 수 있듯이 엑스트라 트리가 랜덤 포레스트 보다 전반적으로 특성의 중요도를 더 높게 평가하고 있습니다. 이는 엑스트라 트리가 더 폭넓은 시각으로 특성들을 평가한다고 생각할 수 있습니다. 단일 결정 트리에서는 ‘worst radius’가 거의 독점적으로 주요한 특성으로 평가되었지만 랜덤 포레스트는 ‘worst perimeter’가 더 높았고 ‘worst area’는 훨씬 더 낮게  나왔습니다. 이에 비해 엑스트라 트리는 ‘worst area’, ‘worst perimeter’, ‘worst radius’, ‘mean concavity’ 등의 특성 중요도가 비교적 고르게 나온 것을 볼 수 있습니다.

당연히 회귀에 대응하는 엑스트라 트리인 ExtraTreesRegressor도 있습니다. ExtraTreesClassifier와 ExtraTreesRegressor의 매개변수 기본값은 부스트랩 샘플을 사용하지 않도록 bootstrap=False인 것을 제외하고는 랜덤 포레스트와 동일합니다. 이 포스트의 코드는 깃허브(https://github.com/rickiepark/introduction_to_ml_with_python/blob/master/ExtraTreesClassifier.ipynb)에서 확인하실 수 있습니다.

New Jupyter Environment: Colaboratory

구글이 회사 내부에서 사용하고 있던 주피터 노트북의 커스텀 버전인 Colaboratory를 공개하였습니다. Colaboratory는 연구와 교육의 목적으로 개발되었다고 합니다. https://colab.research.google.com에 접속하면 샘플 노트북이 로드되는데요. 주피터 커널이 연결되어 있지 않은 상태입니다. 커널을 연결하기 위해서 권한을 요청하면 하루 정도 지나서 메일로 승인이 되었다는 안내를 받을 수 있습니다.

Colab에서 노트북을 생성한 후에 구글 드라이브에 저장을 할 수가 있습니다. 또한 구글 드라이브에서 새 문서 버튼을 통해 Colab 노트북을 직접 만들 수도 있습니다. 또 로컬 컴퓨터에 있는 주피터 노트북을 업로드해서 다른 사람과 공유할 수도 있습니다. 막다운markdown과 라텍LaTex도 물론 지원됩니다. 또 좀 더 편리한 텍스트 셀을 제공하고 있습니다.

스크린샷 2017-10-26 오전 11.40.12

Colab 노트북의 최대 크기는 20M까지입니다. Python 2.7만 지원하고 R이나 Scala는 아직 지원하고 있지 않습니다. 재미있는 것은 대부분의 파이썬의 과학 패키지는 최신 버전을 유지하고 있는데 텐서플로와 Scikit-Learn의 버전이 좀 뒤쳐져 있네요. 하지만 스터디나 튜토리얼 세션 등에는 유용하게 사용될 수 있을 것 같습니다. 🙂

스크린샷 2017-10-26 오전 10.58.27

Andrew Ng launch New DL Courses!

바이두에서 나온 앤드류 응이 세가지 프로젝트를 진행한다고 합니다. 그 중에 먼저 첫 번째로 선을 보이는 것deeplearning.ai로 예고했던 코세라의 Deep Learning Specialization 코스입니다! 파이썬과 텐서플로를 사용하는 이 커리큘럼은 총 다섯개의 코스로 이루어져 있습니다.

  1. Neural Networks and Deep Learning
  2. Improving Deep Neural Networks: Hyperparameter tuning, Regularization and Optimization
  3. Structuring Machine Learning Projects
  4. Convolutional Neural Networks
  5. Sequence Models

작년부터 시작한 코세라의 구독 모델이 적용되는 specialization으로 월 $49를 내고 빠른 속도(!)로 주파를 하면 Certificate를 받을 수 있습니다. 돈을 내지 않고 청강을 할 수도 있는데요. 각 코스의 링크로 직접 들어가서 Enroll을 하면 팝업 화면 아래 조그맣게 쓰인 Audit 링크를 누르시면 됩니다. 자세히는 아직 모르지만 전체 커리큘럼의 수준은 intermediate 정도로 보입니다.

deeplearningai

눈에 익은 책상과 모니터네요! 🙂

SciPy 2017

파이썬 과학 컴퓨팅 컨퍼런스인 SciPy 2017이 텍사스주 오스틴에서 지난 10~16일에 열렸습니다. 올해에도 풍성한 토크튜토리얼 동영상이 유투브에 공개되었습니다. 이 중에 눈에 띄는 몇 개를 골라 보았습니다.

이 외에도 다양한 주제에 대한 여러 동영상이 많이 올라와 있습니다. 전체 리스트를 확인해 보세요.

‘파이썬 라이브러리를 활용한 머신러닝’ 1, 2장

번역서 “파이썬 라이브러리를 활용한 머신러닝“의 1장과 2장의 내용을 담은 파이썬 머신러닝 페이지를 올렸습니다! 공개를 허락해 주신 한빛미디어에 다시 한번 감사의 말씀을 드립니다.

이 책의 1장과 2장은 지도 학습에 관련된 scikit-learn의 주요 클래스들을 다루고 있습니다. 여러 사람에게 유용한 자료가 되었으면 좋겠습니다. 최대한 출판된 책과 동일하게 포스트를 만들었는데 혹시 에러타가 있다면 언제든지 알려 주세요. 그럼 재미있게 읽어 주세요! 🙂

‘파이썬 라이브러리를 활용한 머신러닝’ 출간

b6119391002_lscikit-learn의 코어 개발자이자 배포 관리자인 안드레아스 뮐러Andreas Mueller와 매쉬어블의 데이터 과학자인 세라 가이도Sarah Guido가 쓴 ‘Introduction to Machine Learning with Python‘를 번역한 ‘파이썬 라이브러리를 활용한 머신러닝‘을 출간하였습니다.

출간 직전에 원서가 새로 릴리즈되어서 한바탕 소동을 벌이기는 등 이런 저런 일들이 오랜 작업 기간동안 생겼던 것 같습니다. 추운 겨울에 시작한 일을 한 여름이 되어서야 내놓게 되었네요. 책은 출간이 새로운 시작인 것 같습니다. 에러타나 궁금한 점 등 어떤 이야기도 괜찮습니다. 도서 페이지에 있는 양식을 통해 자유롭게 보내 주세요.

그리고 혹, 서점에 가시면 잘 보이는 곳으로 옮겨놔 주세요! 🙂

(업데이트) 번역서의 1장, 2장 전체를 블로그에 공개할 예정입니다. 공개를 허락해 주신 한빛미디어에 깊이 감사드립니다. 원고를 정리해서 올릴려면 1주일 정도 걸릴 것 같습니다. 😀

PyCon 2017

스크린샷 2017-05-22 오후 12.01.28

지난 주 캘리포니아 구글 마운틴뷰에서 구글 IO 2017이 열렸습니다. 많은 사람들의 관심이 구글 IO에 집중될 때 바로 그 위 오레건 주에서는 파이콘 2017이 같이 시작됐습니다. ^^ 파이콘이 구글 IO처럼 라이브 스트림되지는 못하지만 벌써 유투브에 튜토리얼과 토크 동영상이 올라왔습니다! 파이콘 유투브 채널에서 데이터 사이언스와 관련있는 것을 추려 보았습니다. (파이콘 코리아 2017도 8월에 열립니다)

Python 3.6 Out!

지난 주에 파이썬 3.6 버전이 릴리즈되었습니다. 아나콘다 패키지들도 대부분 파이썬 3.6에 맞춰져 준비되었으니 파이썬 3.6 버전을 써볼 수 있을 것 같습니다. 다만 텐서플로우나 아나콘다에서 제공하지 않는 라이브러리들은 아직 3.6 버전과 호환되지 않을 수 있습니다. 그러므로 파이썬 3.6 을 테스트하려면 콘다 환경을 따로 만들어서 사용해 보는 것이 좋습니다.

$conda create -n python36 python=3.6
$source activate python36

파이썬 3.6에서 눈에 띠는 변경사항을 정리하였습니다.

1. 포맷 문자열

f 로 시작하는 문자열은 중괄호 안에 대치할 변수 이름을 넣을 수 있습니다. 문자열 평가는 한번만 일어 납니다. 변수 이름뒤에 이전과 동일하게 포맷팅 옵션을 쓸 수 있습니다.

>>> name = "철수"
>>> s = f"내 이름은 {name}입니다."
>>> s
'내 이름은 철수입니다.'
>>> name = "영희"
>>> s
'내 이름은 철수입니다.'
>>> val = 1.23456789
>>> f"{val:.3f}"
'1.235'

2. 숫자 밑줄 표현

가독성을 위해 숫자를 사용할 때 밑줄 문자를 써서 천 단위를 표시할 수 있습니다.

>>> 1_000_000_000
1000000000
>>> 0x_FF_FF_FF
4294967295

3. Path 오브젝트 활용

pathlib.Path 오브젝트를 open 함수에 직접 넣을 수 있고 os 와 os.path 하위의 함수들에서도 사용할 수 있습니다.

>>> import pathlib
>>> with open(pathlib.Path("README")) as f:
... 
>>> import os.path
>>> os.path.splitext(pathlib.Path("some_file.txt"))
('some_file', '.txt')
>>> os.path.join("/a/b", pathlib.Path("c"))
'/a/b/c'
>>> import os
>>> os.fspath(pathlib.Path("some_file.txt"))
'some_file.txt'

4. **kwargs 파라미터 순서 유지

**kwargs 로 넘어온 딕셔너리가 입력 파라메타의 순서대로 소팅됩니다.

>>> def myfunc(a, b, **kwargs):
        print(kwargs)
>>> myfunc(1,2, t=1, y=2, u=3, i=4)
{'t': 1, 'y': 2, 'u': 3, 'i': 4}
>>> myfunc(1,2, i=1, u=2, y=3, t=4)
{'i': 1, 'u': 2, 'y': 3, 't': 4}

5. secrete 모듈 추가

암호 생성에 필요한 난수를 위해 random 이나 os.urandom 대신 권장되는 secrete 모듈이 추가되었습니다.

>>> import secrets
>>> secrets.randbelow(100)
>>> 41
>>> secrets.token_hex(16)
>>> '3d7975470f64cbca981c07209c0cbcc4'
>>> secrets.token_urlsafe(16)
>>> 'ZLIS3TVPH301LwuPzwFEjg'

6. http.client 가 HTTP chunked 인코딩을 지원합니다.

7. json.loads, json.load 함수가 문자열 외에 bytes, bytearray 도 지원합니다.

8. random.choices 함수가 추가 되어 한개 이상의 아이템을 무작위로 선택해 리턴할 수 있습니다.

이외에도 많은 사항이 변경되었습니다. 주목할 만한 내용이 발견되면 업데이트 하겠습니다.

TensorFlow API Changes

텐서플로우 v0.12 버전이 릴리즈되면서 파이썬 API 가 일부 변경되었습니다. 혼돈을 줄 수 있는 것들을 바로 잡고 또 가능하면 NumPy 와 일관성을 가지게 하려는 것 같습니다. 이런 API 변경은 앞으로도 조금 더 발생할 수 있을 것으로 예상됩니다. 아직 1.0 버전이 언제 나올지 알 수는 없지만 1.0 이후에는 하위 버전 호환성에 대해 더 엄격하게 관리할 것이라 합니다. 관련된 내용은 구글 그룹스에 올린 구글 브레인팀의 애드류 셀(Andrew Selle)의 포스팅과 텐서플로우 깃허브의 릴리즈 노트의 ‘Breaking Changes to the API’ 섹션을 참고하세요.

  • tf.pack / tf.unpack –> tf.stack / tf.unstack
    • v0.12: stack/unstack 추가, pack/unpack 은 stack/unstack 을 단순 wrapping
    • master: pack/unpack 에 deprecated 메세지 추가
  • tf.concat(concat_dim, values) –> tf.concat_v2(values, axis)
    • v0.12: concat_v2 추가
    • master: concat 에 deprecated 메세지 추가
  • tf.split(split_dim, num_splits, value) –> tf.split(value, num_or_size_splits, axis)
    • v0.12: split_v(value, size_splits, split_dim) 추가
    • master: split(value, num_or_size_splits, axis) 로 변경
  • tf.sparse_split(split_dim, num_split, sp_input) –> tf.sparse_split(sp_input, num_split, axis)
    • master: sparse_split(sp_input, num_split, axis) 로 변경
  • tf.reverse(tensor, dims) –> tf.reverse(tensor, axis)
    • v0.12: reverse_v2(tensor, axis) 추가
    • master: reverse 가 바뀌고, v1.0 이후 reverse_v2 가 deprecated 될 예정
  • tf.round –> banker’s rounding
    • v0.12: 파이썬의 banker’s rounding 으로 변경, 짝수로 반올림/내림
  • dimension, dim, ~indices, ~dim, ~axes 키워드 파라미터 –> axis 로 통일
    • v0.12: 기존 파라미터와 axis 모두 유지, 향후 기존 파라미터 삭제 예정
    • tf.argmax: dimension –> axis
      tf.argmin: dimension –> axis
      tf.count_nonzero: reduction_indices –> axis
      tf.expand_dims: dim –> axis
      tf.reduce_all: reduction_indices –> axis
      tf.reduce_any: reduction_indices –> axis
      tf.reduce_join: reduction_indices –> axis
      tf.reduce_logsumexp: reduction_indices –> axis
      tf.reduce_max: reduction_indices –> axis
      tf.reduce_mean: reduction_indices –> axis
      tf.reduce_min: reduction_indices –> axis
      tf.reduce_prod: reduction_indices –> axis
      tf.reduce_sum: reduction_indices –> axis
      tf.reverse_sequence: batch_dim –> batch_axis, seq_dim –> seq_axis
      tf.sparse_concat: concat_dim –> axis
      tf.sparse_reduce_sum: reduction_axes –> axis
      tf.sparse_reduce_sum_sparse: reduction_axes –> axis
      tf.sparse_split: split_dim –> axis
  • tf.listdiff –> tf.setdiff1d
    • v0.12: setdiff1d 추가
    • master: listdiff 에 deprecated 메세지 추가
  • tf.select –> tf.where
    • v0.12: where 추가
    • master: select 삭제
  • tf.inv –> tf.reciprocal
    • v0.12: inv –> reciprocal 이름 변경
  • tf.SparseTensor.shape –> tf.SparseTensor.dense_shape
    • master: shape –> dense_shape 이름변경
  • tf.SparseTensorValue.shape –> tf.SparseTensorValue.dense_shape
    • master: shape –> dense_shape 이름 변경
  • all_variables –> global_variables , initialize_all_variables -> global_variables_initializer , initialize_local_variables -> local_variables_initializer
    • v0.12: 이름 변경 및 deprecated 메세지 추가
  • zeros_initializer –> 함수 리턴으로 변경
    • master: ones_initializer 와 동일한 리턴 형식으로 변경

이 외에도 tf.nn.sparse_softmax_cross_entropy_with_logits, tf.nn.softmax_cross_entropy_with_logits, tf.nn.sigmoid_cross_entropy_with_logits 의 파라미터 순서가 바뀔 예정이라고 합니다.(아마도 널리 통용되는 크로스 엔트로피 공식의 기호와 순서가 반대여서 그런 것 같습니다)

(업데이트)

  • v0.12: TensorFlowEstimator() 가 삭제되었습니다. 대신 Estimator() 가 권장됩니다.