핸즈온 머신러닝

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, tensorflow 1.7, 1.8, 1.9, 1.10 버전에서 테스트 되었습니다.
  • 작업에 대한 간단한 후기를 여기에 적었습니다.
  • 교보문고 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로 지정하면”로 정정합니다.

 


 

Your Inputs

 

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

  1. 어!이사람아

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

    Liked by 1명

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

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

      좋아요

      응답
  2. gonigoni

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

    좋아요

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

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

        좋아요

  3. duhee

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

    좋아요

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

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

      좋아요

      응답

답글 남기기

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

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.