핸즈온 머신러닝

b9267655530_l

이 책은 아마존 베스트 셀러인 오렐리앙 제롱Aurélien Géron의 ‘Hands-On Machine Learning with Scikit-Learn and TensorFlow‘의 번역서입니다.

이 책에는 머신러닝의 이론과 실용적인 가이드라인이 많이 포함되어 있습니다. 이 책이 딥러닝 전문가로 가는 좋은 출발점의 역할을 할 수 있다면 성공이라 생각합니다. 다시 한번 책을 만드는 데 도움을 주신 모든 분들에게 감사드립니다.

  • 온라인/오프라인 서점에서 판매중입니다. [YES24], [교보문고], [한빛미디어], [리디북스]
  • 672 페이지, 종이책: 33,000원—>29,700원, 전자책: 26,400
  • 이 책의 1장과 2장을 ‘핸즈온 머신러닝‘ 페이지에서 읽을 수 있습니다. 넘파이 튜토리얼도 추가되었습니다.
  • 이 책에 실린 코드는 깃허브에서 주피터 노트북으로 볼 수 있습니다. [github], [nbviewer]
  • 이 책의 코드는 scikit-learn 0.19.1, 0.20.0, tensorflow 1.7, 1.8, 1.9, 1.10, 1.11, 1.12 버전에서 테스트 되었습니다.
  • 작업에 대한 간단한 후기를 여기에 적었습니다.
  • 교보문고 Dev READIT 2018에 선택되어 이 책에 대한 칼럼을 썼습니다.

저자 오렐리앙도 아주 기뻐하네요. 🙂

이 페이지에서 책의 에러타와 scikit-learn과 tensorflow 버전 변경에 따른 바뀐 점들을 계속 업데이트 하겠습니다. 구글 그룹스 도서 메일링 리스트에 가입하시면 책의 에러타나 수정사항을 자동으로 수신할 수 있습니다.

이 책에 대해 궁금한 점이나 오류가 있으면 이 페이지 맨 아래 ‘Your Inputs’에 자유롭게 글을 써 주세요. 또 제 이메일을 통해서 알려 주셔도 되고 구글 그룹스 머신러닝 도서 Q&A에 글을 올려 주셔도 좋습니다.

적바림(미처 책에 넣지 못한 내용을 추가하고 있습니다)

감사합니다! 🙂


Outputs (aka. errata)

머신러닝 도서 메일링 리스트에 가입하시면 책의 에러타나 수정사항을 자동으로 수신할 수 있습니다.

  • 1~10: 2쇄에 반영되었습니다.
  • 11~48: 3쇄에 반영되었습니다.
  1. (p506) 주석 21번에 옮긴이의 주석에서 “앞의 코드는 zero_state( ) 함수가 없는 것을 제외하고는 DeviceWrapper 클래스와 거의 동일합니다.”를 “앞의 코드는 셀 상태를 0으로 초기화하는 zero_state( ) 함수가 없는 것을 제외하고는 DeviceWrapper 클래스와 거의 동일합니다. DeviceWrapper 클래스는 텐서플로 1.2에서 tf.nn.rnn_cell.DeviceWrapper로 바뀌었습니다.“로 변경합니다.
  2. (식 4-7, p305 9.6.1절 두 번째 목록, 식 10-2, 식 E-1) 수식에 있는 “(next step)” 윗첨자를 “(다음 스텝)”으로 바꿉니다.
  3. (p585) 코드 실행시 경고 문구를 없애기 위해 페이지 중간에 위치한 q_value를 계산하는 코드에서 “keep_dims” 매개변수를 “keepdims“로 변경합니다. 넘파이(NumPy) API와 맞추기 위해 텐서플로 1.5에서 keep_dims 매개변수가 keepdims로 바뀌었고 향후 keep_dims는 삭제될 예정입니다.
  4. (p11) 두 번째 문단에서 파이썬의 공식 튜토리얼 주소를 ‘https://docs.python.org/3/tutorial/‘에서 한글 문서 주소인 ‘https://docs.python.org/ko/3/tutorial/‘로 변경합니다.
  5. (p73) <표기법> 사이드 노트에서 마지막에서 두 번째 목록의 끝에
    \hat{y}^{(i)} = y^{(i)} = 2,000
    \hat{y}^{(i)} y^{(i)} = 2,000 으로 정정합니다.
  6. (p90) 주석 25번에서 “매개변수를 True로 설정하면 넘겨진 데이터프레임 자체를 수정하고”를 “매개변수를 True로 설정하면 호출된 데이터프레임 자체를 수정하고”로 수정합니다.
  7. (p95) CAUTION_ 박스의 두 번째 줄에서 매끄러운 문맥을 위해 “예를 들어 x가 0에 가까워지면 y가 증가합니다“를 “예를 들어 x가 0에 가까워지면 y가 증가하는 경우“로 바꿉니다.
  8. (p107) 2.5.4 특성스케일링 아래 세 번째 문단에서 “이를 정규화normalization라고 부릅니다.”의 끝에 누락된 소괄호를 “이를 정규화normalization라고 부릅니다).”와 같이 추가합니다.
  9. (p171) 주석 21번에서 “eta0, power_t 두 매개변수를 사용한”에서 “eta0, power_t 두 매개변수(기본값은 각각 0.01, 0.25)를 사용한”으로 내용을 추가합니다.
  10. (p359) 주석 9번에서 “ELU 함수의 도함수는 z < 0 일 때 \alpha(z)이고”를 “ELU 함수의 도함수는 z < 0 일 때 \alpha(\text{exp}(z))이고”로 정정합니다.
  11. (p130) 아래에서 5번째 줄에서 “1,077개를 ‘5 아님’으로 잘못 분류했고(거짓 양성false positive)”를 “1,077개를 ‘5 아님’으로 잘못 분류했고(거짓 음성false negative)”로 정정합니다.(me****ge 님)
  12. (p135) NOTE의 4번째 줄에서 “반면 재현율은 임곗값이 내려감에 따라”를 “반면 재현율은 임곗값이 올라감에 따라”로 정정합니다.(me****ge 님)
  13. (p175) 두 번째 줄에서 \hat{y}=0.56x^2_1+0.93x_1+1\hat{y}=0.56x^2_1+0.93x_1+1.78 로 정정합니다.(me****ge 님)
  14. (p180) 4.5.1절 두 번째 줄에서 \alpha \sum^n_{i=1}\theta^2_1\alpha \sum^n_{i=1}\theta^2_i 로 정정합니다.(me****ge 님)
  15. (p185) 식 4-12의 마지막에 \theta^2_1\theta^2_i 로 정정합니다.(me****ge 님)
  16. (p305) 주석 15번 첫 번째 줄에서 “경사 하강법에서 지역 최솟값으로 빠르게”를 “경사 하강법에서 전역 최솟값으로 빠르게”로 변경합니다.
  17. (p88) 아래에서 3번째 줄에 “ceil 함수를 사용하여 반올림해서”를 “ceil 함수를 사용하여 올림해서”로 정정합니다. (wnghdcjfe 님)
  18. (p340) 주석 23번 끝에 “텐서플로 1.3 부터는 tf.estimator 아래에 DNNClassifier를 포함하여 사전에 정의된 다양한 모델들이 추가되고 있습니다.“를 추가합니다.
  19. (p228) 식 6-1 바로 위 문장의 수식에서 1-(0/54)^2-(49/54)^2 \approx 0.168 를 1-(0/54)^2-(49/54)^2-(5/54)^2 \approx 0.168 로 정정합니다.(me****ge 님)
  20. (p256) 식 7-4에서 \sum 기호 아래 첨자가 i = 1 이 아니고 j=1 입니다.(me****ge 님)
  21. (p177) 첫 번째 문장에서 “단순 선형 회귀 모델([그림 4-15]의 직선)의 학습 곡선을 살펴봅시다.”를 “단순 선형 회귀 모델(직선)의 학습 곡선을 살펴봅시다(그림 4-15).”로 정정합니다.(me****ge 님)
  22. (p181) 마지막 문장에서 “…가까워지는 것을 볼 수 있습니다. 값을 줄이면 모델의 분산은 줄지만..”을  “…가까워지는 것을 볼 수 있습니다. 즉, 모델의 분산은 줄지만..”으로 정정합니다.(me****ge 님)
  23. (p459) 식 13-1에서 x_{i',j',k'} \cdot w_{u,v,k',k} 를 x_{i',j',k'} \times w_{u,v,k',k} 로 정정합니다.

    24번~32번은 최근 텐서플로의 변경사항과 원서 깃허브에 추가된 내용을 반영한 것입니다.

  24. (p104) 주석 41번을 “41. 옮긴이_ 사이킷런 0.20 릴리스에 추가될 CategoricalEncoder는 OrdinalEncoder와 새로운 OneHotEncoder로 리팩토링되었습니다. 새로운 클래스를 사용한 예는 깃허브 노트북을 참고해주세요.“로 변경합니다.
  25. (p215) 그림 5-12에서 수직축에 쓰인 수식 h=w^t \cdot x + bh=w^T \cdot x + b 로 수정합니다.
  26. (p267) 연습문제 9의 세 번째 줄에서 “…이미지의 클래스입니다. 축하합니다.”를 “…이미지의 클래스입니다. 새로운 훈련 세트에 분류기 하나를 훈련시켜 보세요. 축하합니다.”로 변경합니다.
  27. (p339) 10.2절의 두 번째 줄의 “DNNClassifier 파이썬 클래스” 뒤에 다음 주석을 추가합니다. “† 옮긴이_ DNNClassifier는 텐서플로 1.3버전부터 tf.estimator 아래에 포함되었습니다. tf.estimator를 사용한 예는 깃허브의 노트북을 참고하세요.” 그리고 위 18번 변경사항을 취소합니다.
  28. (p341) 메모리 효율을 높이기 위해 마지막 코드 블럭에서 tf.int64tf.int32 로 변경합니다.
  29. (p430) “그래프에서 직접 훈련 데이터 읽기” 섹션의 첫 번째 문장 끝에 다음 주석을 추가합니다. “† 옮긴이_ 텐서플로 1.4에서 추가된 tf.data를 사용하는 예는 깃허브의 노트북을 참고하세요.
  30. (p586) 아래에서 세 번째 줄 중간에 “효율적인 deque 객체를 만들겠습니다.” 뒤에 다음 주석을 추가합니다. “† 옮긴이_ 넘파이 배열을 사용해 더 빠르게 구현한 예는 깃허브의 노트북을 참고하세요.
  31. 텐서플로 1.4버전에서 tf.variance_scaling_initializer() 가 추가되었습니다. 책과 깃허브의 코드에서 tf.contrib.layers.variance_scaling_initializer() 를 tf.variance_scaling_initializer() 로 변경합니다.
    • p357, p527, p528, p544, p562, p567, p583
  32. 텐서플로 1.7버전부터 tf.examples.tutorials.mnist 가 삭제될 예정이라는 경고가 발생합니다. MNIST 데이터를 로드하는 코드를 Keras로 변경합니다.
    • (p346) 첫 번째 코드 블럭에서
      from tensorflow.examples.tutorials.mnist import input_data
      mnist = input_data.read_data_sets("/tmp/data/")

      (X_train, y_train), (X_test, y_test) = tf.keras.datasets.mnist.load_data()
      ... # 스케일 조정
      X_valid, X_train = X_train[:5000], X_train[5000:]
      y_valid, y_train = y_train[:5000], y_train[5000:]
      

      로 변경합니다. 그리고 세 번째 코드 블럭에서

      with tf.Session() as sess:
        init.run()
        for epoch in range(n_epochs):
          for interation in range(mnist.train.num_examples // batch_size):
            X_batch, y_batch = mnist.train.next_batch(batch_size)
            sess.run(training_op, feed_dict={X: X_batch, y: y_batch})
          acc_train = accuracy.eval(feed_dict={X: X_batch, y: y_batch})
          acc_val = accuracy.eval(feed_dict={X: mnist.validation.images,
                                             y: mnist.validation.labels})
          print(epoch, "Train accuracy:", acc_train, "Validation accuray:", acc_val)

      with tf.Session() as sess:
        init.run()
        for epoch in range(n_epochs):
          # shuffle_batch() 함수 정의는 깃허브를 참고하세요
          for X_batch, y_batch in shuffle_batch(X_train, y_train, batch_size):
            sess.run(training_op, feed_dict={X: X_batch, y: y_batch})
          acc_batch = accuracy.eval(feed_dict={X: X_batch, y: y_batch})
          acc_valid = accuracy.eval(feed_dict={X: X_valid, y: y_valid})
          print(epoch, "배치 데이터 정확도:", acc_batch, "검증 세트 정확도:", acc_valid)

      로 변경합니다.

    • (p365) 코드 블럭에서
      with tf.Session() as sess:
        init.run()
        for epoch in range(n_epochs):
          for interation in range(mnist.train.num_examples // batch_size):
            X_batch, y_batch = mnist.train.next_batch(batch_size)
            sess.run([training_op, extra_update_ops], 
                     feed_dict={training: True, X: X_batch, y: y_batch})
          accuracy_val = accuracy.eval(feed_dict={X: mnist.validation.images,
                                                  y: mnist.validation.labels})
          print(epoch, "Validation accuray:", accuracy_val)

      with tf.Session() as sess:
        init.run()
        for epoch in range(n_epochs):
          # shuffle_batch() 함수 정의는 깃허브를 참고하세요
          for X_batch, y_batch in shuffle_batch(X_train, y_train, batch_size):
            sess.run([training_op, extra_update_ops], 
                     feed_dict={training: True, X: X_batch, y: y_batch})
          accuracy_val = accuracy.eval(feed_dict={X: X_valid, y: y_valid})
          print(epoch, "검증 세트 정확도:", accuracy_val)

      로 변경합니다.

    • (p372~373) 11.2.4절의 코드 블럭에서
      n_batches = mnist.train.num_examples // batch_size
      ...
      h2_cache = sess.run(hidden2, feed_dict={X: mnist.train.images})
      ...
      shuffled_idx = np.random.permutation(mnist.train.num_examples)
      ...
      y_batches = np.array_split(mnist.train.labels[shuffled_idx], n_batches)

      n_batches = len(X_train) // batch_size
      ...
      h2_cache = sess.run(hidden2, feed_dict={X: X_train})
      ...
      shuffled_idx = np.random.permutation(len(X_train))
      ...
      y_batches = np.array_split(y_train[shuffled_idx], n_batches)

      로 변경합니다.

    • (p395) 코드 블럭에서
      with tf.Session() as sess:
        init.run()
        for epoch in range(n_epochs):
          for interation in range(mnist.train.num_examples // batch_size):
            X_batch, y_batch = mnist.train.next_batch(batch_size)
            sess.run(training_op, feed_dict={X: X_batch, y: y_batch})
      

      with tf.Session() as sess:
        init.run()
        for epoch in range(n_epochs):
          # shuffle_batch() 함수 정의는 깃허브를 참고하세요
          for X_batch, y_batch in shuffle_batch(X_train, y_train, batch_size):
            sess.run(training_op, feed_dict={X: X_batch, y: y_batch})
      

      로 변경합니다.

    • (p496) 마지막 코드 블럭에서
      for epoch in range(n_epochs):
        for interation in range(mnist.train.num_examples // batch_size):
          X_batch, y_batch = mnist.train.next_batch(batch_size)
          ...
          acc_train = accuracy.eval(feed_dict={X: X_batch, y: y_batch}) 
          acc_test = accuracy.eval(feed_dict={X: X_test, y: y_test}) 
          print(epoch, "훈련 정확도:", acc_train, "테스트 정확도:", acc_test)

      for epoch in range(n_epochs):
        # shuffle_batch() 함수 정의는 깃허브를 참고하세요
        for X_batch, y_batch in shuffle_batch(X_train, y_train, batch_size):
          ...
          acc_batch = accuracy.eval(feed_dict={X: X_batch, y: y_batch})
          acc_valid = accuracy.eval(feed_dict={X: X_valid, y: y_valid}) 
          print(epoch, "배치 데이터 정확도:", acc_batch, "검증 세트 정확도:", acc_valid)

      로 변경합니다.

    • (p528) 첫 번째 코드 블럭에서
      for epoch in range(n_epochs):
        n_batches = mnist.train.num_examples // batch_size
        for iteration in range(n_batches):
          X_batch, y_batch = mnist.train.next_batch(batch_size)

      for epoch in range(n_epochs):
        n_batches = len(X_train) // batch_size
        for iteration in range(n_batches):
          # shuffle_batch() 함수 정의는 깃허브를 참고하세요
          X_batch, y_batch = next(shuffle_batch(X_train, y_train, batch_size))

      로 변경합니다.

    • (p532~533) 15.3.4절 코드 블럭에서
      n_test_digits = 2
      X_test = mnist.test.images[:n_test_digits]
      
      with tf.Session() as sess:
        [...] # 오토인코더 훈련
        outputs_val = outputs.eval(feed_dict={X: X_test})

      n_test_digits = 2
      # X_test = mnist.test.images[:n_test_digits]
      
      with tf.Session() as sess:
        [...] # 오토인코더 훈련
        outputs_val = outputs.eval(feed_dict={X: X_test[:n_test_digits]})

      로 변경합니다.

    • (p545) 15.7.1절 코드 블럭에서
      for epoch in range(n_epochs):
        n_batches = mnist.train.num_examples // batch_size
        for iteration in range(n_batches):
          X_batch, y_batch = mnist.train.next_batch(batch_size)

      for epoch in range(n_epochs):
        n_batches = len(X_train) // batch_size
        for iteration in range(n_batches):
          # shuffle_batch() 함수 정의는 깃허브를 참고하세요
          X_batch, y_batch = next(shuffle_batch(X_train, y_train, batch_size))

      로 변경합니다.

  33. (p339) 10.2절 아래 네 번째 줄에서 “각각의 뉴런 수는 30개와 100개”를 “각각의 뉴런 수는 300개와 100개”로 정정합니다.(me****ge 님)
  34. (p373) 11.2.5절 아래 세 번째 줄에서 “새로운 작업에 필요한 고주순“을 “새로운 작업에 필요한 고수준“으로 정정합니다.(me****ge 님)
  35. (p523) 그림 15-1의 왼쪽에 쓰여진 “인코더“와 “디코더“의 위치가 서로 바뀌어야 합니다.(me****ge 님)
  36. (p570) TIP 아래 문단 끝에 “비슷한 PG 알고리즘 (그리고 이 책의 범위를 벗어난 몬테카를로 트리 검색을 기반으로 했습니다.”에서 빠진 소괄호를 “비슷한 PG 알고리즘 (그리고 이 책의 범위를 벗어난 몬테카를로 트리 검색)을 기반으로 했습니다.”와 같이 추가합니다.(me****ge 님)
  37. (p165) 식 4-5에서 \sum_{i-1}^{m}이 아니고 \sum_{i=1}^{m}입니다.(me****ge 님)
  38. (p374) 주석 26번에서 CNKT가 아니고 CNTK입니다.(me****ge 님)
  39. (p55) ‘믿을 수 없는 데이터의 효과’ 상자글 첫 문장에서 논문 링크 http://goo.gl/R5enIE 가 더이상 유효하지 않으므로 다음 주소로 http://goo.gl/KNZMEA 로 변경합니다.(임*경 님)
  40. (p60, p61, p62) 60페이지 CAUTION 아래 두 번째 문장과, 61페이지 1.4.6절 목록 중 첫 번째 항목과, 62페이지 1.4.7절의 목록 중 세 번째 항목에서 “파라미터“를 혼돈을 줄이기 위해 “모델 파라미터“로 변경합니다.
  41. (p61) 1.4.6절 목록 중 두 번째 항목에서 “특성 엔지니어링“이라 쓴 영어 표기를 “특성 공학“으로 수정합니다.
  42. (p478) 연습문제 위에 있는 상자글의 첫 번째 줄에서 “예를 들어 이미지 분에서는 업샘플링이 유용합니다.”를 “예를 들어 이미지 분에서는 업샘플링이 유용합니다.”로 바로 잡습니다.(me****ge 님)
  43. (p512) 네 번째 줄에서 “이들이 제한 것은”을 “이들이 제한 것은”으로 정정합니다.(me****ge 님)
  44. (p91, 92) 그림 2-11과 2-12의 경도 축의 값이 모두 음수여야 합니다.
  45. (p83) 다섯 번째 줄에서 “housing_media_age”를 “housing_median_age”로 정정합니다.
  46. (p86) 마지막 문장 끝에 다음 주석을 추가합니다. “다음은 이를 구현한 코드입니다.<주석>옮긴이_ crc32() 함수의 결과에 비트 연산을 하는 이유는 파이썬 2와 호환성을 유지하기 위해서 입니다.</주석>
  47. (p322) NOTE_ 박스의 마지막 문장 “예를 들어 이전 코드에서 만들어진 …. 이름에 “relu_1“에서 “relu_5“까지 접두사를…”를 오해가 없도록 “예를 들어 앞의 코드에서 만들어진 …. 이름에 “relu_1/“에서 “relu_5/“까지 접두사를…”와 같이 수정합니다.
  48. (p80) 첫 번째 코드 블럭에서 HOUSING_PATH와 HOUSING_URL을 설정 코드를 윈도우 환경을 위해 다음과 같이 수정합니다.(pistolet 님)
    HOUSING_PATH = os.path.join("datasets", "housing")
    HOUSING_URL = DOWNLOAD_ROOT + "datasets/housing/housing.tgz"
  49. (p158) 주석 3에서 옮긴이의 주석을 “선형 최소 제곱법을 설명하는 위키백과 문서(https://goo.gl/Lf8VHJ)를 참고하세요.”에서 “정규 방정식의 증명은 위키백과 문서(https://goo.gl/WkNEXH)를 참고하세요.”로 수정합니다.
  50. (p175) 주석 26에서 “interaction_only=False로 지정하면”을 “interaction_only=True로 지정하면”로 정정합니다.
  51. (p466) 그림 13-9 아래 TIP 박스에서 “9 × 9 커널”을 “5 × 5 커널”로 정정합니다. 주석 24에서 “9 × 9 합성곱”을 “5 × 5 합성곱”으로, “9 × 9 필터는 81개의 파라미터”를 “5 × 5 필터는 25개의 파라미터”로 정정합니다.(박*찬 님)
  52. (p215) 5.4.2절 첫 문장에서 “가중치 벡터 ||w||의 노름과 같습니다.”를 “가중치 벡터의 노름 ||w||와 같습니다.”로 정정합니다.
  53. (p641) 마지막 줄에서 \frac{\partial{f}}{\partial{y}}(3, 4) 를 \frac{\partial{f}}{\partial{x}}(3, 4) 로 정정합니다.
  54. 사이킷런 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 버전에서 RandomForestClassifier, RandomForestRegressor 모델의 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')로 변경합니다.
    • SVC, SVR ​클래스의 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')로 변경합니다.
    • LinearSVCverbose 매개변수가 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)으로 변경합니다.
  55. (p468, p541, p543, p565) cross entropy의 번역으로 ‘크로스 엔트로피’와 ‘교차 엔트로피’를 혼용하여 사용했습니다. 일관성을 위해 ‘교차 엔트로피‘를 ‘크로스 엔트로피‘로 정정합니다.
  56. (p243) 주석 1번에서 이항 계수 공식이 잘못 옮겨져 있습니다. \frac{n}{k}p^k(1-p)^{(n-k)}를 {n \choose k}p^k(1-p)^{(n-k)}로 정정하고 \frac{1000}{1}0.51^1(1-0.51)^{(1000-1)}{1000 \choose 1}0.51^1(1-0.51)^{(1000-1)}로 정정합니다.
  57. (p243) 주석 1번에서 binom.cdf() 함수를 사용하는 방법을 올바르게 설명하지 못해 수정합니다. 1-scipy.stats.binom.cdf(499, 1000, 0.51) = 0.747from scipy.stats import binom; 1-binom.cdf(499, 1000, 0.51) = 0.747으로 변경합니다. 1-scipy.stats.binom.cdf(4999, 10000, 0.51) = 0.9781-binom.cdf(4999, 10000, 0.51) = 0.978으로 변경합니다.
  58. (p169) 페이지 첫 문장에서 “천천히 냉각시키는 어닐링annealing(담금질) 과정”을 “천천히 냉각시키는 어닐링annealing(풀림) 과정”으로 변경합니다.(이*혁 님)
  59. (p271) 주석 3번에서 “안쪽 사각형의 너비는“을 “안쪽 사각형의 면적은“으로 정정합니다.
  60. (p285) 8.4절 두 번째 문단의 첫 문장에서 “복잡한 비선형 투영으로의 차원 축소를 가능하게 할“을 보다 명확한 표현인 “차원 축소를 위한 복잡한 비선형 투형을 수행할“로 바꿉니다.
  61. (p74, p656) 2.2.3절 위에 있는 리스트의 첫 번째 항목과 찾아 보기에서 “Euclidian norm”을 “Euclidean norm”으로 정정합니다.
  62. (p356) 표 11-1의 로지스틱과 하이퍼볼릭 탄젠트 공식이 서로 바뀌었습니다.(Kim **youn 님)

Your Inputs

핸즈온 머신러닝”에 대한 17개의 생각

  1. 어!이사람아

    1쇄를 엄청나게 본건 아니고 1회독 정도 한상태라… 어떤점이 바뀌었나 궁금해서 한빛 사이트가서
    책의 색인 부분을 살펴봤는데 .. 1쇄에서 보지못한 단어들이 무지하게 나오더군요ㅠㅠ
    이정도면 2부 딥러닝 파트는 대부분이 바뀌었다고 봐도 될정도 인데.. 정말 고생 많으셨습니다!

    Liked by 1명

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

      네, 맞습니다. 2부 파트가 좀 많이 바뀌었습니다. 여러 실수도 있고 또 텐서플로가 많이 변경된 탓도 있었던 것 같습니다. 덕담해주셔서 감사드립니다! 🙂

      좋아요

      응답
  2. gonigoni

    앗 한가지만 더 여쭤보겠습니다.
    전자책은 위 오류사항 수정 같은 것들이 지속적으로 반영이 되는건가요~?

    좋아요

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

        아 그런데 구매하신 후에도 계속 업데이트된 전자 문서를 받을 수 있는지는 구매처의 정책에 따라 다를 것 같아 문의해 보시는게 좋을 듯 하네요.

        좋아요

  3. duhee

    1부 2장 보는 중인데 파이썬은 어느정도 다뤄봤는데 사이킷런을아예 못다뤄봐서 보기가 좀 힘드네요. 모든 코드의 함수나 라이브러리 이용방법 등을 숙지해야 되나요?

    좋아요

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

      사이킷런이나 텐서플로 자체가 학습의 목적은 아니지만 주어진 문제를 해결하려면 불가피하게 이런 도구를 익숙하게 다루어야 편리합니다. 라이브러리 하나 하나가 꽤 방대하기 때문에 조금씩 알아 간다고 생각하시면 좋습니다.

      좋아요

      응답
  4. Koo

    안녕하세요! 책 잘보고 있습니다.
    앙상블 단원에서 궁금한 점이 있는데요.
    책에는 결정트리를 부스팅한 아다부스트와 그래디언트부스트가 나와있습니다.
    그런데 부스팅이 예측기의 오차를 추가적으로 더 학습해서 강한 모델을 만들자는 컨셉이라면, SVM이나 로지스틱 회귀에서도 부스팅기법을 이용해서 학습할 수 있는 것인가요?

    좋아요

    응답
  5. Koo

    이번에도 질문거리 하나를 가지고 왔습니다
    책에서 SGD파트를 보면 ‘샘플을 무작위로 선택하기 때문에 어떤 샘플은 한 에포크에서 여러번 선택될 수 있고 어떤 샘플은 전혀 선택되지 못할 수도 있습니다.’라는 문장이 있는데요.
    중복을 허용해서 샘플링하고 있는 것이니 SGD가 배깅/부트스트래핑를 활용한다고 볼 수 있을 것 같은데 맞게 이해했는지 궁금합니다.
    책 정말 잘보고 있고, 감사합니다!

    좋아요

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

      안녕하세요. 이 문단의 내용은 바로 그 위의 구현에 대한 설명입니다. 보통은 한 번 에포크를 처리할 때 샘플을 뒤섞고 전체 샘플을 차례대로 순회하는 것이 일반적인 SGD 구현입니다. SGDClassifier 클래스의 기본 동작 방식도 이와 같습니다. 경우에 따라서 뒤섞지 않고 에포크마다 동일한 순서로 샘플을 처리하거나 에포크 안에서 중복을 허용해서 샘플링하는 구현도 더러 있는 것 같습니다. 🙂

      좋아요

      응답
  6. 김도윤

    #1
    오류사항이 있는것 같습니다.
    (p 356) 표 11-1의 활성화 함수 종류에 따른 초기화 매개변수에서, 로지스틱과 tanh의 초기화 값이 바뀌어야 할 것 같습니다. 그리고 그보다도 조판을 명확하게 바꾸는 것을 심각하게 고려해주셨으면 합니다.

    저는 타 분야 전공으로 이 책을 통해 입문해 보려고 모든 식을 다 유도해가며 익히고 있는데, 가장 눈에 띄고 이해가 가지 않는 부분이 이 표의 tanh (수정이 된다면 logistic이 되어야할) 초기화조건에 적혀있는 ‘4제곱근’ 이었습니다. 직관적으로 암만 해도 나올 수 없는 형태의 초기화조건 같아서 유도를 해보려 했습니다. 나중에 모든 식을 다 유도하고 나서야 ‘곱하기 4’라는 것을 알았지만 이건 누가 봐도 ‘4제곱근’에 가깝다고 봐야 할 것 같습니다.

    결국 Glorot의 2010년 논문, He의 2015년 논문 모두 읽어보고서야 나름 확신을 가지고 오타가 아니냐고 질문을 올릴 수 있게 됐네요. Logistic 함수의 미분이 Logistic'(z=0) = 1/4이고, Tanh'(z=0)=1 이니까요.

    원 저자도, 번역가도, 초판 발행 후 2년이 지나도록 어느 독자도 문제를 발견하지 못했다면 제가 틀릴 가능성이 훨씬 높을 텐데, 계산이 계속 안 맞으니 꽤나 골치가 아팠네요. 그래서 지금도 상당히 조심스럽긴 합니다. 틀린 소리 할까봐 ㅠㅠ. 이 분야가 전공인 사람들에게는 너무 당연한 부분이라, 그냥 ‘오타네’ 하고 머릿속에서 알아서 수정이 잘 될 수도 있을 것 같습니다만, 저같은 타 분야의 초심자에게는 며칠동안 표 하나에 묶여버릴 만한 장애물이 되기도 합니다.

    결국 인터넷에 돌아다니는 ‘불법 스캔한 pdf’ 버전까지 찾아 보니 원서의 활자는 그래도 ‘곱하기 4’에 조금 더 가까워 보이긴 합니다만, 로지스틱과 tanh의 순서는 여전히 그대로네요. O’Reilly 출판사의 Errata 페이지에도 글을 올리긴 했는데, 최소 한 달에서 길게는 1년 가까이 걸려 확인된 것도 있는 것 같아, 여기에 다시 올립니다.

    저는 초판 2쇄를 가지고 있는 터라, 요즘 2부 읽을 때는 제가 구매한 책, 여기 Errata 페이지, 원서 Errata 페이지, ‘불법 스캔한 pdf’ 이렇게 다 펼쳐놓고 보고 있습니다. 그래서인지 진도가 많이 느려지네요. 그런데 2쇄도 1쇄와 비교해 많이 달라진 상태라 하니, 어느 정도 이해는 가네요. 앞으로 컴퓨터 관련 서적은 업데이트만 반영이 된다면 E-Book으로 사야 할 것 같네요. 그래도 분명히 최고의 책에 걸맞는 매끄러운 번역임은 틀림 없는 것 같습니다. 정말입니다 ㅎ.

    #2
    건의사항도 있습니다.
    컴퓨터 사이언스 하는 사람들에게는 익숙하겠지만, Linear Transform의 방식에 대한 소개를 주석으로 간단히 언급해주셨으면 합니다. 수학이나 통계, 그 외의 대부분의 자연과학의 수학적 방법론에서는 Left Multiplication이 일종의 Convention인데, 코딩을 할 때에는 그 편리함 때문에 Right Multiplication을 사용하는 점을 한 번은 언급하면 좋을 것 같습니다.
    1부의 앞부분에도 이와 관련된 오타 아닌 오타들이 꽤 있지만 (transpose 관련), 이 점을 미리 언급하면 Left-Right이 하나의 식에 혼재 되어 있어도 적당히 이해하고 지나갈 수 있을 것 같습니다. 사실 coding 예제에서는 아무 설명 없이 X 다음에 W를 곱하고 있는데, 보기에 따라 매끄럽지 않을 수도 있을 것 같습니다.

    #3
    질문. 사실은 더 큰 궁금증이 있습니다.
    Glorot and Bengio의 initialization에서는 forward-backward propagation의 절충안으로 fan-in과 fan-out의 산술평균을 제시했습니다. 그리고 He et al.의 논문에서는 ReLU와 같이 Input이 Centralize 되지 않은 경우 다행스럽게도 적절한 initialization을 다시 찾을 수 있는데, 역시 이 경우도 forward-backward propagation의 경우가 각각 fan-in과 fan-out에 의존합니다.
    다만 He의 경우, 산술평균이 아닌 fan-in 혹은 fan-out 중 어느 하나를 택하더라도 Gradient와 Input의 분산이 DNN의 깊이에 의존하지 않는다는 것을 언급합니다.

    He, et al. [arXiv:1502.01852]
    “We note that it is sufficient to use either Eqn.(14) or Eqn.(10) alone. For example, if we use Eqn.(14), then the product in Eqn.(13), the product (…)=1, and in Eqn.(9) the product (…) =c2/dL , which is not a diminishing number in common network designs. This means that if the initialization properly scales the backward signal, then this is also the case for the forward signal; and vice versa.”

    그렇다면, 이 상황에서 책에 있는 것처럼 ReLU의 경우에도 fan-in과 fan-out의 산술평균을 취함으로써 얻는 실익이 정확히 무엇인가요? 예를 들어 He의 원래 논문에 제시한 대로라면 Layer의 width가 많이 바뀌는 경우에도 상관없이 Input의 n_feature 와 Final output의 n_feature만 고정되면, forward-backward의 양방향 분산이 그대로 유지되는데, 산술평균으로 그것을 (약간?) 흐트러뜨리는 대신 더 좋은 무언가를 얻게 되는것인가요? 산술평균 대신 기하평균을 쓰면 원 논문의 Robust한 성질도 유지하면서 Layer마다의 in-out을 모두 반영하는 것이 가능할 것 같은데, 산술평균이 가지는 큰 장점이 무엇인 지 궁금합니다.

    Liked by 1명

    응답
    1. 김도윤

      구글 그룹이 있는 것을 깜빡하고 여기에 너무 긴 글을 올렸네요.
      글을 옮겼는데, 이 글은 못 지우네요; 죄송합니다

      좋아요

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

      안녕하세요. 좋은 의견 감사드립니다. 1)말씀하신 대로 먼가 이상하네요. 자료를 다시 확인하고 수정하도록 하겠습니다. 정말 4제곱근으로 보이네요. ㅠ.ㅠ 2)깃허브에 math_linear_algebra.ipynb 노트북이 있는데 아직 번역을 못하고 있습니다. 이 노트북을 번역하면서 의견 주신 부분을 반영하도록 하겠습니다. 3)제가 답변드릴 수 있는 범위가 아닌 것 같습니다. 🙂

      좋아요

      응답

답글 남기기

아래 항목을 채우거나 오른쪽 아이콘 중 하나를 클릭하여 로그 인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Google+ photo

Google+의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

%s에 연결하는 중

This site uses Akismet to reduce spam. Learn how your comment data is processed.