글쓴이 보관물: 박해선

“머신러닝 파워드 애플리케이션” 독서 후기

아래는 구글 Machine Learning GDE인 박찬성 님이 <머신러닝 파워드 애플리케이션>을 읽은 후 작성하신 리뷰입니다. 찬성 님의 허락을 받아 블로그에 싣게 되었습니다. 좋은 리뷰 정말 감사합니다! 🙂


🖌 머신러닝 파워드 애플리케이션 독서 후기

이 책은 머신러닝이 탑재된 애플리케이션을 만들기위해, End to End 로(처음부터 끝까지) 들어가야 하는 노력을 잘 정리해 보여준다. 이 책만의 몇 가지 특징이 있는 데, 그 중 두개를 꼽자면

1️⃣ 머신러닝 에디터라는 애플리케이션을 만드는 예를 보여주는것 같지만, 이 구체적인 예제를 다룸과 동시에 다양한 문제에 사용될 수 있는 접근법들을 함께 설명한다. 구체적인 예제를 풀어내지만, 일반적인 컨셉도 함께 배울 수 있다.

2️⃣ 애플리케이션 구축에 필요한 모든 요소에 동일한 가중치를 두고 설명한다. 데이터 수집, 모델링, 배포, 모니터링 등에서 한 부분에만 집중하지 않기 때문에, 성공적인 애플리케이션 구축을 위해서는 “모든 부분이 중요하다”는 사실을 묵시적으로 뇌리에 잘 심어주는것 같다.

이 책이 강조하는 부분은 반복성이다. 애플리케이션을 만드는 전체 과정의 입장에서의 반복. 또는 데이터 수집/검증, 모델링, 배포 후 사용자와의 상호작용 등 전체 파이프라인의 부분별로의 반복. 빠르게 아이디어를 실험하고, 검증을 통해 문제를 파악하고, 개선하는 반복의 사이클을 항상 고려해야만 성공적인 머신러닝이 탑재된 애플리케이션을 만들 수 있다는것이다.

✔️ 이는 다른 책에서도 흔히 볼 수 있는 강조인데, 이 책에서는 특히 더 많이 강조하는 부분인것 같다. 전체 파이프라인, 모델링 측면에서는 그렇다고 많이 느끼고 있었는데, 이를 현재 보유한 인력에 맞춰 더욱 잘게 쪼개진 사이클을 만들 수 있구나 라는걸 알게되었다.

이 책은 애플리케이션을 구축하는 전반을 다룬다. 따라서 “서비스”, “고객”의 관점에서 내용을 설명한다. 대개 인공지능이 모든것을 대체할 것이다 라고들 생각하는 경향이 있지만, 100%의 예측이란 불가능하기 때문에 머신러닝이 실패할 때를 항상 대비해야한다. 이 실패를 대처하는 방법으로 머신러닝이 도입되기 전 활용되어온 규칙기반 알고리즘, 또는 매우 단순하게라도 작동하는 간단한 머신러닝 모델을 추가적으로 활용하는것이다.

✔️ 즉 머신러닝이 실패하는 상황을 “우아하게” 대처하기 위해서는 머신러닝이 들어가기 이전의 노력 + 머신러닝을 운용하는 노력이 결합되어야 한다는 것이다. 그리고 이를 위해서는 도메인 지식을 집요하게 습득하려는 노력이 선행되어야한다. AI가 만능이다 라는 생각도 가져야 하지만(그래야 더 완성도 높은 모델을 만들기 때문에), AI 붐이 일어나기 전 수십년간 사람들이 축적해온 문제 해결 능력/방법은 결코 무시해서는 안된다.

✔️ 머신러닝이 탑재되는 애플리케이션/시스템을 만들겠다는 계획은 좋지만, 그 전에 MVP로 만들어야 할 것은 머신러닝이 탑재되지 않은 버전의 최선의 결과물이어야 할 것이다.

그 외에도 보다 구체적인 경험적 방법 (모범 사례)를 파이프라인의 각 요소마다 상세히 설명하고 있다. 물론 추가적인 리서치는 필요하지만, 큰 그림을 이해하고 체크리스트를 만들기에 충분한 지식을 전달한다.

약간 아쉬운점은 비교적 배포, 모니터링, 인프라에 대한 내용이 부족하다는 것이다. 하지만 보다 구체적인 내용을 뒷받침할 수 있는 책들이 많으므로 함께 읽어보면 좋을것 같다고 생각한다.

이 책은 두 번 이상 읽을 때 더 도움이되는 책이며, 각 장마다 제시하는 여러가지 옵션을 시각적으로 표현하거나 체크-리스트로 만들어 관리하면 꽤 도움이 될 것이라고 느꼈다. 다음 주 부터 재독을 진행할 예정인데, 만들게되면 공유해 보겠습니다 🙂


“혼자 공부하는 머신러닝+딥러닝”과 “파이토치로 배우는 자연어 처리”가 교보문고 2021년 올해의 책에 선정되었습니다!

교보문고 2021 올해의 책에 <혼자 공부하는 머신러닝+딥러닝>과 <파이토치로 배우는 자연어 처리> 책이 선정되었습니다. <혼자 공부하는 머신러닝+딥러닝>은 AI/ML 분야에서 1등을 했고 <파이토치로 배우는 자연어 처리>는 자연어 처리 분야에서 1등을 했습니다! (머신 러닝 교과서도 후보에 들었네요! 🙂 )

한 해 동안 제 책을 애독해 주신 모든 분들께 정말 감사드립니다!

“머신러닝 파워드 애플리케이션” 사이킷런 1.0 업데이트 완료!

<머신러닝 파워드 애플리케이션>의 주피터 노트북을 사이킷런 1.0에 맞추어 업데이트했습니다. 업데이트된 노트북은 깃허브 저장소에서 확인하실 수 있습니다. 감사합니다! 🙂

‘혼자 공부하는 머신러닝+딥러닝’이 Yes24 올해의 책 후보에 선정되었습니다!

<혼자 공부하는 머신러닝+딥러닝>이 Yes24 2021년 올해의 책 후보에 선정되었습니다! 추천해 주신 모든 분들께 진심으로 감사드립니다. 올해 후보에는 IT 책이 한 권 뿐이지만 내년에 여러 권이 되었으면 좋겠습니다. 저도 더 열심히 노력하겠습니다.

올해의 책 후보 중 3권이상 골라 투표에 참가하면 1천원 Yes24 상품권을 준다고 하네요. 마음에 드는 책을 골라 투표에 참여해 보세요!

감사합니다! 🙂

TensorFlow 2.7.0이 릴리스되었습니다.

얼마전 케라스 2.7.0 버전이 릴리스된 후 이어서 텐서플로 2.7.0 버전이 릴리스되었습니다. 당연하지만 텐서플로 2.7.0은 케라스 2.7.0 버전을 사용합니다. 주요 변경 사항으로는 서브클래싱으로 만든 케라스 모델에서 스칼라 입력을 자동으로 2D 텐서로 확장하지 않습니다. to_yaml()model_from_yaml()을 사용하지 못하며 대신 json이나 h5 포맷을 사용해야 합니다. 합성곱 층에 convolution_op() 메서드가 추가되어 커스텀 합성곱 층을 만들기 쉬워 집니다. 디버깅에 용이하도록 에러 메시지가 읽기 쉽게 제공됩니다.

더 자세한 내용은 텐서플로 2.7.0의 릴리스 노트를 참고하세요! 감사합니다. 🙂

Yes24 2021년 올해의 책 후보 도전에 응원 부탁드립니다.

온라인 서점 Yes24(www.yes24.com)에서는 매년 올해의 책을 선정합니다. 먼저 20여권의 후보를 추천을 통해 선정한 후에 투표를 통해 최종 올해의 책을 선정합니다. 올해의 책 후보에 드는 것만으로도 엄청난 영광이죠. 제 기억에는 IT 책이 후보에 오른적이 없었던 것 같습니다. 대부분 인기있는 책은 문학, 경제, 자기개발 분야입니다.

오늘 우연히 Yes24에서 <혼자 공부하는 머신러닝+딥러닝> 페이지를 보다가 몇 분이 올해의 책 후보에 추천해 주신 것을 보고 너무 기뻤습니다. 사실 IT 책이 후보가 될 가능성은 매우 희박합니다. 그래도 몇 분의 추천에 힘을 얻고 용기내어 도전해 보려고 합니다. 혹시 이 책을 재미있게 보셨다면 11월 3일까지 Yes24 올해의 책 후보로 추천 부탁드립니다! 저는 물론 이 분야의 책을 내는 출판사, 번역자, 작가 모두에게 큰 힘이 되리라 생각합니다. 감사합니다! 🙂

Yes24 2021년 올해의 책 후보 추천 페이지: http://www.yes24.com/campaign/00_corp/2021/boy.aspx

[핸즈온 머신러닝 2판], [머신 러닝 교과서 3판] 사이킷런 1.0 업데이트 완료

[핸즈온 머신러닝 2판], [머신 러닝 교과서 3판]의 주피터 노트북을 사이킷런 1.0 버전에 맞추어 모두 테스트하여 깃허브에 반영하였습니다. 변경이 필요한 부분은 수정하거나 주석을 추가했습니다. 아래 에러타를 참고해 주세요.

감사합니다! 🙂

핸즈온 머신러닝 2판

  • (p197) 넘파이 1.20버전부터 np.int가 deprecated 되었기 때문에 첫 번째 코드 블럭의 마지막 줄에서 astype(np.int)를 astype(int)로 수정합니다.
  • (p179) 사이킷런 1.0에서 get_feature_names() 메서드를 가진 변환기에 get_feature_names_out() 메서드가 추가되었고 get_feature_names()는 deprecated 되어 1.2 버전에서 삭제될 예정입니다. 따라서 23번 주석에서 get_feature_names()를 get_feature_names_out()으로 수정합니다.

머신 러닝 교과서 3판

  • (p157) 넘파이 1.20버전부터 np.int가 deprecated 되었기 때문에 아래에서 7번째 줄에 OrdinalEncoder(dtype=np.int)를 OrdinalEncoder(dtype=int)로 수정합니다. (p158) 위에서 12번째 줄에 “np.int로 지정했습니다”를 “int로 지정했습니다”로 수정합니다. (p159) 위에서 14번째 줄에 OrdinalEncoder()를 OrdinalEncoder(dtype=int)로 수정합니다.
  • (p236) 아래에서 5번째 줄 끝에 다음 주석을 추가합니다. “구현되어 있습니다.<주석>역주 사이킷런 1.2 버전에서 TSNE 클래스의 init 매개변수의 기본값이 'random'에서 'pca'로 바뀔 예정입니다.”
  • (p271) 사이킷런 1.0 버전에서 plot_confusion_matrix()가 deprecated 되었고 1.2 버전에서는 삭제될 예정입니다. 위에서 4번째 줄에서 from sklearn.metrics import plot_confusion_matrix를 from sklearn.metrics import ConfusionMatrixDisplay로 수정합니다. 위에서 5번째 줄과 아래에서 4번째 줄에서 plot_confusion_matrix(pipe_svc, ...)를 ConfusionMatrixDisplay.from_estimator(pipe_svc, ...)로 수정합니다.
  • (p278) 사이킷런 1.0 버전에서 plot_roc_curve()가 deprecated 되었고 1.2 버전에서는 삭제될 예정입니다. 위에서 6번째 줄에서 from sklearn.metrics import plot_roc_curve를 from sklearn.metrics import RocCurveDisplay로 수정합니다. 위에서 12번째 줄에서 plot_roc_curve(pipe_lr, ...)를 RocCurveDisplay.from_estimator(pipe_lr, ...)로 수정합니다.
  • (p279) 사이킷런 1.0 버전에서 plot_precision_recall_curve()가 deprecated 되었고 1.2 버전에서는 삭제될 예정입니다. 위에서 5번째 줄에서 from sklearn.metrics import plot_precision_recall_curve를 from sklearn.metrics import PrecisionRecallDisplay로 수정합니다. 위에서 11번째 줄에서 plot_precision_recall_curve(pipe_lr, ...)를 PrecisionRecallDisplay.from_estimator(pipe_lr, ...)로 수정합니다.
  • (p328) 사이킷런 1.0에서 히스토그램 기반 부스팅이 experimental 모듈 아래에서 벗어났습니다. 따라서 위에서 7번째 줄에서 시작하는 문장부터 9번째 줄까지 다음 내용을 삭제합니다. “이 클래스는 아직 실험적이기 때문에 사용하기 전에 먼저 활성화해야 합니다.
    from sklearn.experimental import enable_hist_gradient_boosting
  • (p329) XGBoost 1.3.0에서 이진 분류 기본 평가 지표가 'error'에서 'logloss'로 변경되었습니다. 또한 향후 레이블 인코딩을 수행하지 않는다는 경고가 발생합니다. 경고를 없애기 위해 위에서 6번째 줄에 XGBClassifier(tree_method='hist', random_state=1)을 XGBClassifier(tree_method='hist', eval_metric='logloss', use_label_encoding=False, random_state=1)로 수정합니다.
  • (p415) 아래에서 6번째 줄에 price_std 배열을 2차원으로 바꾸기 위해 inverse_transform(price_std)를 inverse_transform(price_std.reshape(-1,1))로 수정합니다.
  • (p419) 사이킷런 1.0에서 'absolute_loss'가 deprecated 되었고 1.2 버전에서 삭제될 예정이기 때문에 대신 'absolute_error'를 사용합니다. 아래에서 4번째 줄에 loss='absolute_loss'를 loss='absolute_error'로 수정합니다.
  • (p428) 사이킷런 1.0에서 get_feature_names() 메서드를 가진 변환기에 get_feature_names_out() 메서드가 추가되었고 get_feature_names()는 deprecated 되어 1.2 버전에서 삭제될 예정입니다. 주석의 끝에서 2번째 줄에 get_feature_names()를 get_feature_names_out()으로 수정합니다.
  • (p436) 사이킷런 1.0에서 'mse'가 deprecated 되었고 1.2 버전에서 삭제될 예정이기 때문에 대신 'squared_error'를 사용합니다. 위에서 11번째 줄에 criterion='mse'를 criterion='squared_error'로 수정합니다.

사이킷런 ❤️ 판다스

사이킷런 버전 1.0에서 판다스 데이터프레임을 모델이나 변환기에 입력했을 때 열 이름을 feature_names_in_ 속성에 저장합니다. 향후에는 변환기가 판다스 데이터프레임을 입력으로 받으면 출력도 데이터프레임으로 만들 예정입니다. <핸즈온 머신러닝 2판>의 저자 오렐리앙 제롱이 새로 추가된 사이킷런의 데이터프레임 연동 기능에 대해 간단한 튜토리얼을 주피터 노트북으로 만들었습니다. 내용이 좋아 제가 한글로 번역했습니다. 무료한 주말(?)에 재미있게 보세요! 🙂

[파이썬 라이브러리를 활용한 머신러닝], [파이썬을 활용한 머신러닝 쿡북] 사이킷런 1.0 업데이트 완료

안녕하세요. [파이썬 라이브러리를 활용한 머신러닝], [파이썬을 활용한 머신러닝 쿡북]의 주피터 노트북 코드를 사이킷런 1.0 버전에 맞추어 모두 테스트하여 깃허브에 반영하였습니다. 또한 변경이 필요한 본문을 수정하고 주석을 추가했습니다. 다음 에러타 내용을 참고해 주세요.

감사합니다! 🙂

파이썬 라이브러리를 활용한 머신러닝

  1. (p62) 위에서 3번째 줄에 다음처럼 주석을 추가합니다. “보스턴 주택가격 데이터셋<주석>옮긴이_ 보스턴 주택가격 데이터셋의 특성에는 흑인 인구 비율이 들어 있어 요즘 시대에 적절치 않다는 의견이 많았습니다. 사이킷런 1.0 버전에서 load_boston() 함수가 deprecated 되었고 1.2 버전에서 삭제될 예정입니다.</주석>을 사용하겠습니다”
  2. (p136, 137) In [79], [80]에서 Axes3D가 자동으로 그림에 추가되는 방식은 matplotlib 3.4 버전에서 deprecated 되었기 때문에 관련 경고를 피하기 위해 ax = Axes3D(figure, elev=-152, azim=-26)을 ax = Axes3D(figure, elev=-152, azim=-26, auto_add_to_figure=False); figure.add_axes(ax)로 수정합니다.
  3. (p156) In [102]에서 다음처럼 MLPClassifier 객체 생성시 max_iter 매개변수를 지정합니다. mlp = MLPClassifier(max_iter=1000, random_state=0)
  4. (p205) In [26]의 첫 번째 줄에서 np.bool이 1.20버전부터 deprecated 되었기 때문에 대신 bool을 사용합니다. mask = np.zeros(people.target.shape, dtype=bool)
  5. (p223) 4번째 줄에 다음과 같이 주석을 추가합니다. “결과를 비교해 보겠습니다.<주석>옮긴이_ 사이킷런 1.2 버전에서 TSNE 클래스의 init 매개변수의 기본값이 'random'에서 'pca'로 바뀔 예정입니다.</주석> t-SNE는 새 데이터를..”
  6. get_feature_names() 메서드를 가진 변환기에 get_feature_names_out() 메서드가 추가되었고 get_feature_names()는 deprecated 되어 1.2 버전에서 삭제될 예정입니다. 따라서 (p281) 마지막 문장과 In [13],  (p294) 첫 번째 문장과 In [34], (p297) 마지막 문장과 In[39], (p320) 첫 번째 문장과 In [72], (p423) In [16], (p426) In [21], (p430) In [30], (p434) In [35]와 In [36], (p435) In [38], (p437) In [41], (p450) In [51], (p451) In [55]에서 get_feature_names()를 get_feature_names_out()으로 수정합니다.
  7. (p366) In [52]에서 0 나눗셈 경고를 피하기 위해 다음처럼 zero_division 매개변수를 지정합니다. classification_report(y_test, pred_most_frequent, target_names=["9 아님", "9"], zero_division=0))
  8. (p443) 아래에서 4번째 줄에 다음처럼 주석을 추가합니다. “설치 페이지(…)를 참고하세요.<주석>옮긴이_ 최신 버전의 tweepy 패키지를 설치할 경우 konlpy에서 StreamListener가 없다는 에러가 발생하므로 3.10버전을 설치해 주세요. pip install tweepy==3.10</주석> KoNLPy는 5개의…”
  9. (p335) 주석 7번 끝에 다음을 추가합니다. “사이킷런 1.0 버전에서 그룹을 유지하면서 클래스 비율에 맞게 분할하는 StratifiedGroupKFold가 추가되었습니다.”
  10. (p293) 주석 15번 끝에 다음 문장을 추가합니다. “사이킷런 1.0 버전부터는 PolynomialFeatures 클래스의 degree 매개변수에 변환할 최소 차수과 최대 차수를 튜플로 전달할 수 있습니다.”

파이썬을 활용한 머신러닝 쿡북

  1. (p75, 79, 81, 85, 86, 88, 91, 93, 95, 97, 99, 100, 102, 107, 108, 110) 타이타닉 데이터를 다운로드하는 https://tinyurl.com/titanic_csv 주소에 문제가 생겨서 https://bit.ly/titanic_csv_data로 바꿉니다.
  2. (p177) 덧붙임의 첫 번째 문단 끝에 다음 주석을 추가합니다. “…설치할 수 있습니다.<주석>옮긴이_ 최신 버전의 tweepy 패키지가 설치될 경우 konlpy에서 StreamListener가 없다는 에러가 발생하므로 3.10버전을 설치해 주세요. pip install tweepy==3.10</주석>
  3. 사이킷런 1.0에서 get_feature_names() 메서드를 가진 변환기에 get_feature_names_out() 메서드가 추가되었고 get_feature_names()는 deprecated 되어 1.2 버전에서 삭제될 예정입니다. 따라서 (p128) 마지막 줄, (p129) 1번째 줄, (p156) 위에서 15, 17번째 줄, (p179) 마지막 줄, (180) 2번째 줄, (p493) 아래에서 2번째 줄에서 get_feature_names를 get_feature_names_out으로 수정합니다.
  4. (p229) 위에서 3번째 줄에서 corner의 값을 정수로 변환하기 위해 corner[0].astype('int')로 수정합니다.
  5. (p252) 9.4절 [해결]의 첫 번째 문장 끝에 다음 주석을 추가합니다. “… 차원을 축소합니다.<주석>옮긴이_ 기본값인 init=None일 때 n_components가 n_samples나 n_features 보다 작으면 init='nndsvd'가 됩니다. 사이킷런 1.1버전부터 이 값이 'nndsvda'로 바뀔 예정입니다.</주석>
  6. (p252) 아래에서 9번째 줄에서 NMF 객체를 만들 때 반복횟수를 늘려주기 위해 max_iter 매개변수를 추가합니다. nmf = NMF(n_components=10, max_iter=1000, random_state=1)
  7. (p283) 11.2절 [해결]의 첫 번째 문장 끝에 다음 주석을 추가합니다. “…모델을 만듭니다.<주석>옮긴이_ 보스턴 주택가격 데이터셋의 특성에는 흑인 인구 비율이 들어 있어 요즘 시대에 적절치 않다는 의견이 많았습니다. 사이킷런 1.0 버전에서 load_boston() 함수가 deprecated 되었고 1.2 버전에서 삭제될 예정입니다.</주석>
  8. 로지스틱 회귀 객체를 만들 때 반복횟수를 늘려주기 위해 (p300) 위에서 15번째 줄, (p311) 위에서 5번째 줄에 max_iter 매개변수를 추가합니다. classifier = LogisticRegression(max_iter=1000)
  9. (p312) 위에서 4번째 줄에 0 나눗셈 경고를 피하기 위해 다음처럼 zero_division 매개변수를 지정합니다. print(classification_report(target_test, target_predicted, labels=[0,1,2,3], zero_division=0))
  10. 사이킷런 0.22 버전에서 solver 매개변수의 기본값이 'liblinear'에서 'lbfgs'로 변경되었습니다. 'lbfgs'는 'l2' 페널티만 지원합니다. 예제에서 'l1''l2' 페널티를 그리드서치로 탐색하기 위해 solver='liblinear'로 지정합니다. 또 반복 횟수를 늘려주기 위해 max_iter=1000을 추가합니다. (p318) 위에서 13번째 줄, (p320) 아래에서 3번째 줄, (p323) 위에서 15번째 줄, (p325) 아래에서 7번째 줄, (p327) 아래에서 8번째 줄, (p329) 위에서 11번째 줄에서 LogisticRegression()을 LogisticRegression(solver='liblinear', max_iter=1000)으로 바꿉니다.
  11. (p331) 위에서 8번째 줄에 반복 횟수를 늘려 주기 위해 max_iter 변수를 추가합니다. logit = linear_model.LogisticRegressionCV(max_iter=1000, Cs=100)
  12. (p332) 사이킷런 1.0에서 매개변수 변화에 따른 경고가 발생하지 않으므로 아래에서 4번째 줄을 다음처럼 수정합니다. logistic = linear_model.LogisticRegression(max_iter=1000)
  13. 사이킷런 1.0에서 매개변수 변화에 따른 경고가 발생하지 않으므로 위에서 (p333) 5번째 줄에 iid=False, 7번째 줄에 cv=3, 아래에서 4번째 줄에 iid=False, (p334) 위에서 8번째 줄에 cv=3을 삭제합니다.
  14. (p335) 위에서 2 번째 줄 끝에서 시작되는 문장, 아래에서 3번째 줄에 있는 문장, 마지막 줄에 있는 문장인 “경고를 출력하지 않기 위해 … 로 지정합니다”를 삭제합니다.
  15. (p355) 결정 트리의 criterion 매개변수 값인 mae가 사이킷런 1.0에서 deprecated되었고 1.2 버전에서 삭제될 예정입니다(mse도 마찬가지). 대신 'absolute_error'를 사용합니다. 위에서 6번째 줄을 decisiontree_mae = DecisionTreeRegressor(criterion="absolute_error", random_state=0)으로 수정합니다.
  16. (p374) 사이킷런 1.0에서 히스토그램 기반 부스팅이 experimental 모듈 아래에서 벗어났습니다. 따라서 위에서 8번째 줄 끝에서 시작하는 문장부터 12번째 줄까지 다음 내용을 삭제합니다.
    “이 클래스들은 실험적이기 때문에 명시적으로 사용한다는 것을 선언해야 합니다.
    # 히스토그램 기반의 그레이디언트 부스팅을 활성화하고 라이브러리를 임포트합니다.
    from sklearn.experimental import enable_hist_gradient_boosting
  17. (p397) 아래에서 2번째 줄에 compute_class_weight 함수에 키워드 매개변수를 추가합니다. compute_class_weight('balanced', classes=[0,1], y=target)

[혼자 공부하는 머신러닝+딥러닝], [Do It! 딥러닝 입문] 사이킷런 1.0 테스트 완료

[혼자 공부하는 머신러닝+딥러닝], [Do It! 딥러닝 입문]의 주피터 노트북 코드를 최신 사이킷런 1.0 버전에서 모두 테스트하여 깃허브에 반영하였습니다. 책을 보실 때 참고하세요. 감사합니다!