HOME / CATALOG / 데이터 사이언스
데이터 사이언스

파이썬 머신러닝 완벽 가이드 (개정판)

다양한 캐글 예제와 함께 기초 알고리즘부터 최신 기법까지 배우는
지은이 권철민
도서 정보
출간일
2020년 2월 7일
쪽수
648쪽
ISBN
9791158391928
시리즈
데이터 사이언스 시리즈_050
정가
38,000원
난이도
도서 소개
저자 소개
목차
예제 코드
정오표
관련 자료

도서 소개

자세한 이론 설명과 파이썬 실습을 통해 머신러닝을 완벽하게 배울 수 있습니다!

《파이썬 머신러닝 완벽 가이드》는 이론 위주의 머신러닝 책에서 탈피해 다양한 실전 예제를 직접 구현해 보면서 머신러닝을 체득할 수 있도록 만들었습니다. 캐글과 UCI 머신러닝 리포지토리에서 난이도가 있는 실습 데이터를 기반으로 실전 예제를 구성했고, XGBoost, LightGBM, 스태킹 기법 등 캐글의 많은 데이터 사이언스에서 애용하는 최신 알고리즘과 기법에 대해 매우 상세하게 설명했습니다. 이번 개정판에서는 사이킷런 및 기타 라이브러리의 업데이트에 따른 전반적인 내용 및 소스코드 업데이트와 함께 질의 사항이 많은 부분들에 대한 상세한 설명을 추가했습니다.

 

★ 이 책의 특징 ★

  • 분류, 회귀, 차원 축소, 클러스터링 등 핵심 머신러닝 알고리즘에 대한 깊이 있는 설명
  • 데이터 전처리, 머신러닝 알고리즘 적용, 하이퍼 파라미터 튜닝, 성능 평가 등 최적 머신러닝 모델 구성 방안 제시
  • XGBoost, LightGBM, 스태킹 등 머신러닝 최신 기법에 대한 상세한 설명과 활용법
  • 난이도 높은 캐글 문제를 직접 따라 해 보면서 실무 머신러닝 애플리케이션 개발 방법 체득(산탄테르 은행 고객 만족 예측, 신용카드 사기 검출, 부동산 가격 예측 고급 회귀 기법, Mercari 쇼핑몰 가격 예측 등)
  • 텍스트 분석과 NLP를 위한 기반 이론과 다양한 실습 예제 제공(텍스트 분류, 감성 분석, 토픽 모델링, 문서 유사도, 문서 군집화와 유사도, KoNLPy를 이용한 네이버 영화 감성 분석 등)
  • 다양한 추천 시스템을 직접 파이썬 코드로 구축하는 법을 제공

 

도서 상세 이미지

저자 소개

권철민

엔코아 컨설팅, 한국 오라클을 거쳐 현재 kx systems에서 고성능 인메모리 DB인 kdb+의 Machine Learning 컨설턴트로 근무 중이다. 지난 20년간 50여 개 이상의 주요 고객사에서 데이터컨설팅 분야에 매진해 왔으며, 최근 몇 년간은 AI 기반의 Advanced Analytics 분야에 집중하고 있다. 직접 구현해 보지 않으면 절대 이해하지 못하는 평범한 두뇌의 소유자이며, 절망적인 프로젝트에 참여해 자기학대적인 노력으로 문제를 해결하는 이상한 성격의 소유자이기도 하다.

목차

  • ▣ 1장: 파이썬 기반의 머신러닝과 생태계 이해
    • 1.1. 머신러닝의 개념
      • 머신러닝의 분류
      • 데이터 전쟁
      • 파이썬과 R 기반의 머신러닝 비교
    • 1.2. 파이썬 머신러닝 생태계를 구성하는 주요 패키지
      • 파이썬 머신러닝을 위한 S/W 설치
    • 1.3. 넘파이
      • 넘파이 ndarray 개요
      • ndarray의 데이터 타입
      • ndarray를 편리하게 생성하기 – arange, zeros, ones
      • ndarray의 차원과 크기를 변경하는 reshape( )
      • 넘파이의 ndarray의 데이터 세트 선택하기 – 인덱싱(Indexing)
      • 행렬의 정렬 – sort( )와 argsort( )
      • 선형대수 연산 – 행렬 내적과 전치 행렬 구하기
    • 1.4. 데이터 핸들링 – 판다스
      • 판다스 시작 – 파일을 DataFrame으로 로딩, 기본 API
      • DataFrame과 리스트, 딕셔너리, 넘파이 ndarray 상호 변환
      • DataFrame의 컬럼 데이터 세트 생성과 수정
      • DataFrame 데이터 삭제
      • Index 객체
      • 데이터 셀렉션 및 필터링
      • 정렬, Aggregation 함수, GroupBy 적용
      • 결손 데이터 처리하기
      • apply lambda 식으로 데이터 가공
    • 1.5. 정리
    •  
  • ▣ 2장: 사이킷런으로 시작하는 머신러닝
    • 2.1. 사이킷런 소개와 특징
    • 2.2. 첫 번째 머신러닝 만들어 보기 – 붓꽃 품종 예측하기
    • 2.3. 사이킷런의 기반 프레임워크 익히기
      • Estimator 이해 및 fit( ), predict( ) 메서드
      • 사이킷런의 주요 모듈
      • 내장된 예제 데이터 세트
    • 2.4. Model Selection 모듈 소개
      • 학습/테스트 데이터 세트 분리 – train_test_split()
      • 교차 검증
      • GridSearchCV – 교차 검증과 최적 하이퍼 파라미터 튜닝을 한 번에
    • 2.5. 데이터 전처리
      • 데이터 인코딩
      • 피처 스케일링과 정규화
      • StandardScaler
      • MinMaxScaler
      • 학습 데이터와 테스트 데이터의 스케일링 변환 시 유의점
    • 2.6. 사이킷런으로 수행하는 타이타닉 생존자 예측
    • 2.7. 정리
    •  
  • ▣ 3장: 평가
    • 3.1. 정확도(Accuracy)
    • 3.2. 오차 행렬
    • 3.3. 정밀도와 재현율
      • 정밀도/재현율 트레이드오프
      • 정밀도와 재현율의 맹점
    • 3.4. F1 스코어
    • 3.5. ROC 곡선과 AUC
    • 3.6. 피마 인디언 당뇨병 예측
    • 3.7. 정리
    •  
  • ▣ 4장: 분류
    • 4.1. 분류(Classification)의 개요
    • 4.2. 결정 트리
      • 결정 트리 모델의 특징
      • 결정 트리 파라미터
      • 결정 트리 모델의 시각화
      • 결정 트리 과적합(Overfitting)
      • 결정 트리 실습 – 사용자 행동 인식 데이터 세트
    • 4.3. 앙상블 학습
      • 앙상블 학습 개요
      • 보팅 유형 – 하드 보팅(Hard Voting)과 소프트 보팅(Soft Voting)
      • 보팅 분류기(Voting Classifier)
    • 4.4. 랜덤 포레스트
      • 랜덤 포레스트의 개요 및 실습
      • 랜덤 포레스트 하이퍼 파라미터 및 튜닝
    • 4.5. GBM(Gradient Boosting Machine)
      • GBM의 개요 및 실습
      • GBM 하이퍼 파라미터 및 튜닝
    • 4.6. XGBoost(eXtra Gradient Boost)
      • XGBoost 개요
      • XGBoost 설치하기
      • 파이썬 래퍼 XGBoost 하이퍼 파라미터
      • 파이썬 래퍼 XGBoost 적용 – 위스콘신 유방암 예측
      • 사이킷런 래퍼 XGBoost의 개요 및 적용
    • 4.7. LightGBM
      • LightGBM 설치
      • LightGBM 하이퍼 파라미터
      • 하이퍼 파라미터 튜닝 방안
      • 파이썬 래퍼 LightGBM과 사이킷런 래퍼 XGBoost, LightGBM 하이퍼 파라미터 비교
      • LightGBM 적용 – 위스콘신 유방암 예측
    • 4.8. 분류 실습 – 캐글 산탄데르 고객 만족 예측
      • 데이터 전처리
      • XGBoost 모델 학습과 하이퍼 파라미터 튜닝
      • LightGBM 모델 학습과 하이퍼 파라미터 튜닝
    • 4.9. 분류 실습 – 캐글 신용카드 사기 검출
      • 언더 샘플링과 오버 샘플링의 이해
      • 데이터 일차 가공 및 모델 학습/예측/평가
      • 데이터 분포도 변환 후 모델 학습/예측/평가
      • 이상치 데이터 제거 후 모델 학습/예측/평가
      • SMOTE 오버 샘플링 적용 후 모델 학습/예측/평가
    • 4.10. 스태킹 앙상블
      • 기본 스태킹 모델
      • CV 세트 기반의 스태킹
    • 4.11. 정리
    •  
  • ▣ 5장: 회귀
    • 5.1. 회귀 소개
    • 5.2. 단순 선형 회귀를 통한 회귀 이해
    • 5.3. 비용 최소화하기 – 경사 하강법(Gradient Descent) 소개
    • 5.4. 사이킷런 LinearRegression을 이용한 보스턴 주택 가격 예측
      • LinearRegression 클래스 – Ordinary Least Squares
      • 회귀 평가 지표
      • LinearRegression을 이용해 보스턴 주택 가격 회귀 구현
    • 5.5. 다항 회귀와 과(대)적합/과소적합 이해
      • 다항 회귀 이해
      • 다항 회귀를 이용한 과소적합 및 과적합 이해
      • 편향-분산 트레이드오프(Bias-Variance Trade off)
    • 5.6. 규제 선형 모델 – 릿지, 라쏘, 엘라스틱넷
      • 규제 선형 모델의 개요
      • 릿지 회귀
      • 라쏘 회귀
      • 엘라스틱넷 회귀
      • 선형 회귀 모델을 위한 데이터 변환
    • 5.7. 로지스틱 회귀
    • 5.8. 회귀 트리
    • 5.9. 회귀 실습 – 자전거 대여 수요 예측
      • 데이터 클렌징 및 가공
      • 로그 변환, 피처 인코딩과 모델 학습/예측/평가
    • 5.10. 회귀 실습 – 캐글 주택 가격: 고급 회귀 기법
      • 데이터 사전 처리(Preprocessing)
      • 선형 회귀 모델 학습/예측/평가
      • 회귀 트리 모델 학습/예측/평가
      • 회귀 모델의 예측 결과 혼합을 통한 최종 예측
      • 스태킹 앙상블 모델을 통한 회귀 예측
    • 5.11. 정리
    •  
  • ▣ 6장: 차원 축소
    • 6.1. 차원 축소(Dimension Reduction) 개요
    • 6.2. PCA(Principal Component Analysis)
      • PCA 개요
    • 6.3. LDA(Linear Discriminant Analysis)
      • LDA 개요
      • 붓꽃 데이터 세트에 LDA 적용하기
    • 6.4. SVD(Singular Value Decomposition)
      • SVD 개요
      • 사이킷런 TruncatedSVD 클래스를 이용한 변환
    • 6.5. NMF(Non-Negative Matrix Factorization)
      • NMF 개요
    • 6.6. 정리
    •  
  • ▣ 7장: 군집화
    • 7.1. K-평균 알고리즘 이해
      • 사이킷런 KMeans 클래스 소개
      • K-평균을 이용한 붓꽃 데이터 세트 군집화
      • 군집화 알고리즘 테스트를 위한 데이터 생성
    • 7.2. 군집 평가(Cluster Evaluation)
      • 실루엣 분석의 개요
      • 붓꽃 데이터 세트를 이용한 군집 평가
      • 군집별 평균 실루엣 계수의 시각화를 통한 군집 개수 최적화 방법
    • 7.3. 평균 이동
      • 평균 이동(Mean Shift)의 개요
    • 7.4. GMM(Gaussian Mixture Model)
      • GMM(Gaussian Mixture Model) 소개
      • GMM을 이용한 붓꽃 데이터 세트 군집화
      • GMM과 K-평균의 비교
    • 7.5. DBSCAN
      • DBSCAN 개요
      • DBSCAN 적용하기 – 붓꽃 데이터 세트
      • DBSCAN 적용하기 – make_circles( ) 데이터 세트
    • 7.6. 군집화 실습 – 고객 세그먼테이션
      • 고객 세그먼테이션의 정의와 기법
      • 데이터 세트 로딩과 데이터 클렌징
      • RFM 기반 데이터 가공
      • RFM 기반 고객 세그먼테이션
    • 7.7. 정리
    •  
  • ▣ 8장: 텍스트 분석
    • NLP이냐 텍스트 분석이냐?
    • 8.1. 텍스트 분석 이해
      • 텍스트 분석 수행 프로세스
      • 파이썬 기반의 NLP, 텍스트 분석 패키지
    • 8.2. 텍스트 사전 준비 작업(텍스트 전처리) – 텍스트 정규화
      • 클렌징
      • 텍스트 토큰화
      • 스톱 워드 제거
      • Stemming과 Lemmatization
    • 8.3. Bag of Words – BOW
      • BOW 피처 벡터화
      • 사이킷런의 Count 및 TF-IDF 벡터화 구현: CountVectorizer, TfidfVectorizer
      • BOW 벡터화를 위한 희소 행렬
      • 희소 행렬 – COO 형식
      • 희소 행렬 – CSR 형식
    • 8.4. 텍스트 분류 실습 – 20 뉴스그룹 분류
      • 텍스트 정규화
      • 피처 벡터화 변환과 머신러닝 모델 학습/예측/평가
      • 사이킷런 파이프라인(Pipeline) 사용 및 GridSearchCV와의 결합
    • 8.5. 감성 분석
      • 감성 분석 소개
      • 지도학습 기반 감성 분석 실습 – IMDB 영화평
      • 비지도학습 기반 감성 분석 소개
      • SentiWordNet을 이용한 감성 분석
      • VADER를 이용한 감성 분석
    • 8.6. 토픽 모델링(Topic Modeling) – 20 뉴스그룹
    • 8.7. 문서 군집화 소개와 실습(Opinion Review 데이터 세트)
      • 문서 군집화 개념
      • Opinion Review 데이터 세트를 이용한 문서 군집화 수행하기
      • 군집별 핵심 단어 추출하기
    • 8.8. 문서 유사도
      • 문서 유사도 측정 방법 – 코사인 유사도
      • 두 벡터 사잇각
      • Opinion Review 데이터 세트를 이용한 문서 유사도 측정
    • 8.9. 한글 텍스트 처리 – 네이버 영화 평점 감성 분석
      • 한글 NLP 처리의 어려움
      • KoNLPy 소개
      • 데이터 로딩
    • 8.10. 텍스트 분석 실습–캐글 Mercari Price Suggestion Challenge
      • 데이터 전처리
      • 피처 인코딩과 피처 벡터화
      • 릿지 회귀 모델 구축 및 평가
      • LightGBM 회귀 모델 구축과 앙상블을 이용한 최종 예측 평가
    • 8.11. 정리
    •  
  • ▣ 9장: 추천 시스템
    • 9.1. 추천 시스템의 개요와 배경
      • 추천 시스템의 개요
      • 온라인 스토어의 필수 요소, 추천 시스템
      • 추천 시스템의 유형
    • 9.2. 콘텐츠 기반 필터링 추천 시스템
    • 9.3. 최근접 이웃 협업 필터링
    • 9.4. 잠재 요인 협업 필터링
      • 잠재 요인 협업 필터링의 이해
      • 행렬 분해의 이해
      • 확률적 경사 하강법을 이용한 행렬 분해
    • 9.5. 콘텐츠 기반 필터링 실습 – TMDB 5000 영화 데이터 세트
      • 장르 속성을 이용한 영화 콘텐츠 기반 필터링
      • 데이터 로딩 및 가공
      • 장르 콘텐츠 유사도 측정
      • 장르 콘텐츠 필터링을 이용한 영화 추천
    • 9.6. 아이템 기반 최근접 이웃 협업 필터링 실습
      • 데이터 가공 및 변환
      • 영화 간 유사도 산출
      • 아이템 기반 최근접 이웃 협업 필터링으로 개인화된 영화 추천
    • 9.7. 행렬 분해를 이용한 잠재 요인 협업 필터링 실습
    • 9.8. 파이썬 추천 시스템 패키지 – Surprise
      • Surprise 패키지 소개
      • Surprise를 이용한 추천 시스템 구축
      • Surprise 주요 모듈 소개
      • Surprise 추천 알고리즘 클래스
      • 베이스라인 평점
      • 교차 검증과 하이퍼 파라미터 튜닝
      • Surprise를 이용한 개인화 영화 추천 시스템 구축
    • 9.9. 정리

예제 코드

정오표

  • 43쪽, 본문 밑에서 4번째 줄

    디렉터리에 있다고 가정하고 itanic_train.csv 파일을

    ==>

    디렉터리에 있다고 가정하고 titanic_train.csv 파일을

  • 67쪽, 본문에서 2번째 [Output]까지의 내용 구성을 다음과 같이 변경

    # data_df를 reset_index()로 새로운 숫자형 인덱스를 생성
    data_df_reset = data_df.reset_index()
    data_df_reset = data_df_reset.rename(columns={'index':'old_index'})
    
    # 인덱스값에 1을 더해서 1부터 시작하는 새로운 인덱스값 생성
    data_df_reset.index = data_df_reset.index+1
    data_df_reset

    【Output】

    ml-definitive-guide-p67

    이제 인덱스값이 1부터 시작하는 integer형입니다. ix[0, 1]이 어떤 값을 반환하는지 확인해 보겠습니다.

    # 아래 코드는 오류를 발생합니다.
    data_df_reset.ix[0,1]

    【Output】

    KeyError Traceback (most recent call last)
    ~\Anaconda3\lib\site-packages\pandas\core\indexes\base.py in get_loc(self, key, method, tolerance)
       3062              try:
       -> 3063              return self._engine.get_loc(key)
       3064              except KeyError:
  • 101쪽, 열 번째 줄

    데이트를 분리하기 전에

    ==>

    데이터를 분리하기 전에

  • 103쪽, 그림

    테스트 데이트 세트

    ==>

    테스트 데이터 세트

  • 108쪽, 페이지 상단 예제 코드의 2번째 줄

    print('검증 레이블 데이터 분포:\n', label_test.value_counts())iris_df['label'].value_counts()

    ==>

    print('검증 레이블 데이터 분포:\n', label_test.value_counts())
  • 115쪽, 상단 예제 코드의 6번째 줄

    iris = load_iris()

    ==>

    iris_data = load_iris()
  • 153쪽, 페이지 상단 그림을 다음 그림으로 교체

    pymldg-rev-p153.png

  • 171쪽, 페이지 하단 예제 코드를 다음 내용으로 교체

    from sklearn.metrics import roc_curve
    
    # 레이블 값이 1일때의 예측 확률을 추출
    pred_proba_class1 = lr_clf.predict_proba(X_test)[:, 1]
    
    fprs , tprs , thresholds = roc_curve(y_test, pred_proba_class1)
    # 반환된 임곗값 배열에서 샘플로 데이터를 추출하되, 임곗값을 5 Step으로 추출.
    # thresholds[0]은 max(예측확률)+1로 임의 설정됨. 이를 제외하기 위해 np.arange는 1부터 시작
    thr_index = np.arange(1, thresholds.shape[0], 5)
    print('샘플 추출을 위한 임곗값 배열의 index:', thr_index)
    print('샘플 index로 추출한 임곗값: ', np.round(thresholds[thr_index], 2))
    
    # 5 step 단위로 추출된 임계값에 따른 FPR, TPR 값
    print('샘플 임곗값별 FPR: ', np.round(fprs[thr_index], 3))
    print('샘플 임곗값별 TPR: ', np.round(tprs[thr_index], 3))
  • 172쪽, 페이지 상단 Output을 다음 내용으로 교체

    샘플 추출을 위한 임곗값 배열의 index: [ 1  6 11 16 21 26 31 36 41 46 51]
    샘플 index로 추출한 임곗값:  [0.97 0.65 0.63 0.56 0.45 0.38 0.31 0.13 0.12 0.11 0.1 ]
    샘플 임곗값별 FPR:  [0.    0.017 0.034 0.076 0.127 0.186 0.237 0.576 0.619 0.754 0.814]
    샘플 임곗값별 TPR:  [0.033 0.639 0.705 0.754 0.803 0.852 0.902 0.902 0.951 0.967 1.   ]
  • 173쪽, 예제를 다음 코드로 교체

    from sklearn.metrics import roc_auc_score
    
    pred_proba = lr_clf.predict_proba(X_test)[:, 1]
    roc_score = roc_auc_score(y_test, pred_proba)
    print('ROC AUC 값: {0:.4f}'.format(roc_score))
  • 173쪽, 예제의 출력 결과를 다음 내용으로 교체

    ROC AUC 값: 0.9024
  • 174쪽, 첫 번째 줄

    ROC AUC 값은 약 0.8987로 측정됐습니다.

    ==>

    ROC AUC 값은 약 0.9024로 측정됐습니다.

  • 184쪽, 밑에서 8번째 줄

    유연하게 적용될 수 알고리즘입니다.

    ==>

    유연하게 적용될 수 있는 알고리즘입니다

  • 197쪽, 밑에서 7번째 줄

    DecisionTreeClassifierr 객체의

    ==>

    DecisionTreeClassifier 객체의

  • 201쪽, 본문 첫 번째 줄

    이번에는 min_samples_leaf = 6을 설정해 6개 이하의 데이터는

    ==>

    이번에는 min_samples_leaf = 6을 설정해 6개 이상의 데이터는

  • 203쪽, 밑에서 6번째 줄

    위에서 피처명을 가지고 있는 features_info.txt 파일은 중복된 피처명을 가지고 있습니다

    ==>

    위에서 피처명을 가지고 있는 features.txt 파일은 중복된 피처명을 가지고 있습니다

  • 271쪽, 본문 그림을 다음 그림으로 교체

    pymldg-rev-p271.png

  • 271쪽, 아홉 번째 줄

    사분위는 전체 데이트를 값이 높은 순으로 정렬하고

    ==>

    사분위를 전체 데이터를 값이 높은 순으로 정렬하고

  • 283쪽, 세 번째 줄

    최종 테스트 데이트 세트를 생성합니다.

    ==>

    최종 테스트 데이터 세트를 생성합니다.

  • 285쪽, 그림

    테스트 데이트를 모두 합쳐서

    ==>

    테스트 데이터를 모두 합쳐서

  • 325쪽, 예제 코드를 다음 코드로 교체

    from sklearn.linear_model import Lasso, ElasticNet
    
    # alpha값에 따른 회귀 모델의 폴드 평균 RMSE를 출력하고 회귀 계수값들을 DataFrame으로 반환
    def get_linear_reg_eval(model_name, params=None, X_data_n=None, y_target_n=None,
                            verbose=True, return_coeff=True):
        coeff_df = pd.DataFrame()
        if verbose : print('####### ', model_name , '#######')
        for param in params:
            if model_name =='Ridge': model = Ridge(alpha=param)
            elif model_name =='Lasso': model = Lasso(alpha=param)
            elif model_name =='ElasticNet': model = ElasticNet(alpha=param, l1_ratio=0.7)
            neg_mse_scores = cross_val_score(model, X_data_n,
                                                 y_target_n, scoring="neg_mean_squared_error", cv = 5)
            avg_rmse = np.mean(np.sqrt(-1 * neg_mse_scores))
            print('alpha {0}일 때 5 폴드 세트의 평균 RMSE: {1:.3f} '.format(param, avg_rmse))
            # cross_val_score는 evaluation metric만 반환하므로 모델을 다시 학습하여 회귀 계수 추출
    
            model.fit(X_data_n , y_target_n)
            if return_coeff:
                # alpha에 따른 피처별 회귀 계수를 Series로 변환하고 이를 DataFrame의 칼럼으로 추가.
                coeff = pd.Series(data=model.coef_ , index=X_data_n.columns )
                colname='alpha:'+str(param)
                coeff_df[colname] = coeff
    
        return coeff_df
    # end of get_linear_regre_eval
  • 331쪽, 페이지 상단 예제 코드의 밑에서 2번째 줄

    get_linear_reg_eval('Ridge', params=alphas, X_data_n=X_data_scaled,
                        y_target_n=y_target, verbose=False)

    ==>

    get_linear_reg_eval('Ridge', params=alphas, X_data_n=X_data_scaled,
                        y_target_n=y_target, verbose=False, return_coeff=False)
  • 356쪽, 페이지 상단 코드의 2번째 줄

    sns.distplot(trainDF['SalePrice'])

    ==>

    sns.distplot(house_df['SalePrice'])
  • 365쪽, 본문 6번째 줄

    왜곡 정도가 높다고 판단지만, 상황에 따라

    ==>

    왜곡 정도가 높다고 판단하지만, 상황에 따라

  • 466쪽, 본문 2번째 줄

    머신러닝이 보편화되면서 NLP(National Language Processing)와

    ==>

    머신러닝이 보편화되면서 NLP(Natural Language Processing)와

  • 515쪽, 본문 첫 번째 줄

    components_는 array[8, 4000]으로 구성돼 있습니다.

    ==>

    components_는 array[8, 1000]으로 구성돼 있습니다.

WHERE TO BUY · 정가 38,000원
WHERE TO BUY · 정가 38,000원