텐서플로 2와 머신러닝으로 시작하는 자연어 처리 (개정판)

로지스틱 회귀부터 BERT와 GPT2까지

텐서플로 2를 기반으로 한국어 BERT, GPT를 활용한 NSMC, KorNLI, KorSTS, KorQuAD, NER 모델 구현을 추가했습니다!

이 책은 다른 자연어 처리 서적과는 다른 세 가지 특징이 있습니다. 첫째, 자연어 처리에 활용되는 개념적인 설명에서 끝나는 것이 아니라 모델 구현에 집중합니다. 둘째, 실무에서 자연어 처리 문제를 해결하는 데 도움이 되고자 감정분석부터 유사도 처리, 챗봇 그리고 버트와 GPT에서 할 수 있는 모든 하위 문제를 다룹니다. 셋째, 영어 데이터뿐만 아니라 한글 데이터를 활용한 문제 해결까지 다룹니다.

특히 이번 개정판에서는 다양한 자연어 처리 문제를 사전학습 모델인 버트와 GPT2를 통해 풀었습니다. 이번에 추가된 7장의 모든 실습을 수행하고 나면 한층 더 높은 수준의 최신 자연어 처리 기법을 이해할 수 있습니다. 실습을 통해 자연어 처리를 다룰 자신감이 생겼다면 여러분은 이미 딥러닝 자연어 처리 전문가로서의 첫발을 내디딘 것입니다.

 

추천사

"이론적인 설명에서 그치지 않고 데이터셋을 자세히 들여다보면서 인사이트를 얻고, 코드 레벨까지 깊게 내려가면서 이론을 손으로 만지듯 더듬으면서 이해할 수 있게 해주며, 간단한 딥러닝 코드가 만들어 내는 경이로운 정확도를 직접 확인할 수 있게 해주는 멋진 가이드가 될 것이다." - 김성훈(홍콩과기대 / 네이버 Clova AI)

 

"딥러닝의 필수 요소에 대한 소개, 트랜스포머(Transformer) 같은 최신 모델에 대한 구체적인 설명까지 필요한 내용을 빠짐없이 다뤘습니다. 자연어 처리에 입문하려는 분들에게 이 책이 하나의 선택지로 자리하게 된 것을 다행스럽게 생각합니다." - 박규병(카카오브레인 A.I. Researcher)

 

"단순히 최신 딥러닝 기반 자연어 처리 기술을 소개하는 것이 아니라 실질적인 코딩과 한국어의 특성 등을 충분히 어필하고 있기에 실제 자연어 처리를 도입해서 새로운 서비스나 앱 등을 개발하려는 분들에게 큰 도움이 될 것이다." - 정지훈(경희사이버대 선임강의 교수, 모두의 연구소 Chief Vision Officer)

 

"복잡한 이론적 내용 때문에 어렵게만 여겨지던 딥러닝을 이 책을 통해 많은 사람들이 쉽고 재미있게 배울 수 있을 것이다." - 주재걸(고려대 컴퓨터학과 교수)

 

"이런 좋은 책을 한글로 써주신 저자분께 감사드리며, 자연어 처리에 관심이 있는 분들께 많은 도움이 되리라 생각합니다. 강추합니다." - 조대협(구글-조대협의 블로그)

 

"한국어로 쓰여진 자연어 처리 서적 가운데 이보다 방대하고 친절한 책은 없을 것이다." - 이기창(네이버 Clova Chatbot, http://ratsgo.github.io의 블로그)

 

도서 상세 이미지

전창욱

배우고 성장하기 위해 끊임없이 공부하는 것을 즐기며, 해마다 목표를 정하고 이뤄가는 재미에 푹 빠져 살아가고 있습니다. 배운 것을 만들어 보고 이론과 실습을 함께 키워나가고 삶의 방향성을 찾기 위해 책을 읽는 시니어 개발자입니다. 머신러닝 공부를 하면서 2016년 Google Hack Fair, Seoul Make Fair에 참여했고, 국립과천과학관 관장상과 2017년 서울혁신챌린지 혁신챌린지상을 수상했으며, KBS 시사교양 프로그램인 『명견만리』에 출연하고, 2018년 국어 정보처리 시스템 경진대회에서 금상을 수상, 2019년 국어 정보처리 학회에서 논문 발표, 2020년 LG AWARDS를 수상, 2020년 7월 현재 Korquad 1.0에서 1위를 차지하고 있습니다. 전 DeepNLP 연구실 리더였으며, 현재는 LG에서 딥러닝을 활용한 자연어처리 연구 개발을 하고 있습니다.

최태균

클래식 음악을 듣기 좋아하고 오랫동안 산책을 즐기는 소프트웨어 개발자입니다. 컴퓨터 분야에 이것저것 관심을 두다 딥러닝과 자연어 처리를 우연히 접하게 되어 재미를 키워가고 있습니다. 서경대학교 컴퓨터과학과를 졸업했고 현재는 네이버에서 근무하고 있습니다.

조중현

중앙대학교에서 수학을 전공했으며, 우연한 기회로 개발을 접하게 됐습니다. 그 후 딥러닝이라는 분야에 관심을 가지고, 그중에서도 자연어 처리 분야를 집중적으로 공부하고 있습니다. 다양한 어려운 문제를 새로운 모델을 통해 해결하는 것이 딥러닝의 매력이라 생각합니다. 계속해서 세상의 많은 문제들을 딥러닝을 통해 해결하는 것을 목표로 삼고 있습니다.

신성진

퍼듀 대학교 산업공학과를 졸업하고 NAVER Clova의 Conversation팀에서 리서치 엔지니어(Research Engineer)로 일하고 있습니다. 머신러닝과 자연어 처리 분야의 전문가가 되기 위해 모두의 연구소 DeepNLP 연구실을 창설했습니다. 관심사는 멀티모달 대화 인터페이스이며, 해당 분야의 미래를 선도하기 위해 연구/개발에 힘쓰고 있습니다.

  • ▣ 01장: 들어가며
    • 이 책의 목표와 활용법
      • 아나콘다 설치
    • 실습 환경 구축
      • 가상 환경 구성
      • 실습 프로젝트 구성
      • pip 설치
      • 주피터 노트북
    • 정리
    •  
  • ▣ 02장: 자연어 처리 개발 준비
    • 텐서플로
      • tf.keras.layers
      • TensorFlow 2.0
    • 사이킷런
      • 사이킷런을 이용한 데이터 분리
      • 사이킷런을 이용한 지도 학습
      • 사이킷런을 이용한 비지도 학습
      • 사이킷런을 이용한 특징 추출
      • TfidfVecotorizer
    • 자연어 토크나이징 도구
      • 영어 토크나이징 라이브러리
      • 한글 토크나이징 라이브러리
      • 넘파이
    • 그 밖의 라이브러리(전처리)
      • 판다스
      • Matplotlib
      • 맷플롯립 설치
      • Matplotlib.pyplot
      • re
    • 캐글 사용법
    • 정리
    •  
  • ▣ 03장: 자연어 처리 개요
    • 단어 표현
    • 텍스트 분류
      • 텍스트 분류의 예시
    • 텍스트 유사도
    • 자연어 생성
    • 기계 이해
    • 데이터 이해하기
    • 정리
    •  
  • ▣ 04장: 텍스트 분류
    • 영어 텍스트 분류
      • 문제 소개
      • 데이터 분석 및 전처리
      • 모델링 소개
      • 회귀 모델
      • TF-IDF를 활용한 모델 구현
      • 랜덤 포레스트 분류 모델
      • 순환 신경망 분류 모델
      • 컨볼루션 신경망 분류 모델
      • 마무리
    • 한글 텍스트 분류
      • 문제 소개
      • 데이터 전처리 및 분석
      • 모델링
      • 참고 자료
    • 정리
    •  
  • ▣ 05장: 텍스트 유사도
    • 문제 소개
    • 데이터 분석과 전처리
      • XG 부스트 텍스트 유사도 분석 모델
    • 모델링
      • CNN 텍스트 유사도 분석 모델
      • MaLSTM
    • 정리
    •  
  • ▣ 06장: 챗봇 만들기
    • 데이터 소개
    • 데이터 분석
    • 시퀀스 투 시퀀스 모델
      • 모델 소개
    • 트랜스포머 모델
      • 모델 구현
    • 정리
    •  
  • ▣ 07장: 사전 학습 모델
    • 버트
    • 버트를 활용한 미세 조정 학습
      • 버트를 활용한 한국어 텍스트 분류 모델
      • 버트를 활용한 한국어 자연어 추론 모델
      • 버트를 활용한 한국어 개체명 인식 모델
      • 버트를 활용한 한국어 텍스트 유사도 모델
      • 버트를 활용한 한국어 기계 독해 모델
    • GPT
      • GPT1
      • GPT2
    • GPT2를 활용한 미세 조정 학습
      • GPT2를 활용한 한국어 언어 생성 모델
      • GPT2를 활용한 한국어 텍스트 분류 모델
      • GPT2를 활용한 한국어 자연어 추론 모델
      • GPT2를 활용한 한국어 텍스트 유사도 모델
  • 27쪽, 첫 번째 코드 블록의 마지막 줄

    activation=tf.nn.relu)(input)
    

    ==>

    activation=tf.nn.relu)(inputs)
    
  • 27쪽, 2번째 코드 블록의 4번째 줄

    dropout = tf.keras.layers.Dropout(rate=0.2)(input)
    

    ==>

    dropout = tf.keras.layers.Dropout(rate=0.2)(inputs)
    
  • 28쪽, 첫 번째 코드 블록의 마지막 줄

    activation=tf.nn.relu)(input)
    

    ==>

    activation=tf.nn.relu)(dropout)
    
  • 39쪽, 첫 번째 코드 블록의 12번째 줄

    tokenizer = preprocessing.text.Tokenizer() tokenizer.fit_on_texts(samples)
    

    ==>

    tokenizer = preprocessing.text.Tokenizer()
    tokenizer.fit_on_texts(samples)
    
  • 61쪽, 3번째 코드 블록의 마지막 줄

    print(tfidf_vectorizer.transform(text_data).toarray())
    

    ==>

    print(tfidf_vectorizer.transform(sentence).toarray())
    
  • 64쪽, 두 번째 문단

    컴퓨터 저장 공간이 넉넉하지 않을 때는 ‘all-corpora’만 선택해서 다운로드를 진행하면 된다.

    ==>

    ‘all’을 선택해 전체 패키지를 다운로드한다. 컴퓨터 저장 공간이 넉넉하지 않을 때는 ‘all-corpora’만 선택해서 다운로드를 진행하면 된다.

  • 102쪽, 마지막 줄

    이후 내려받은 파일을 다음 위치에 저장한다.

    ==>

    이후 내려받은 파일을 사용자 홈 디렉터리의 .kaggle 폴더에 저장한다.

  • 147쪽, 첫 번째 코드 블록 아래 문단부터 다음 페이지 첫 번째 문단까지

    이 명령을 입력하면 다음과 같이 출력되면서 4개의 파일을 다운로드한다.

    (중략)

    마지막으로 압축을 완전히 다 풀었으면 파일 처리를 마치기 위해 ZipFile 객체의 close 함수를 호출한다.

    ==>

    캐글에서 다운로드한 압축 파일을 풀고, 다음 4개의 파일을 data_in 폴더로 이동한다.

    - labeledTrainData.tsv
    - unlabeledTrainData.tsv
    - testData.tsv
    - sampleSubmission.csv
    
  • 151쪽, 첫 번째 코드 블록 1~2번째 줄

    train_lenght
    

    ==>

    train_length
    
  • 151쪽, 세 번째 코드 블록 10번째 줄

    train_lenght
    

    ==>

    train_length
    
  • 153쪽, 첫 번째 코드 블록 7번째 줄

    train_lenght
    

    ==>

    train_length
    
  • 158쪽, 첫 번째 코드 블록의 5번째 줄

    from bs4 import Beautiful Soup
    

    ==>

    from bs4 import BeautifulSoup
    
  • 159쪽, 첫 번째 코드 블록의 2번째 줄

    review_text = Beautiful Soup(review,"html5lib").get_text() # HTML 태그 제거
    

    ==>

    review_text = BeautifulSoup(review,"html5lib").get_text() # HTML 태그 제거
    
  • 161쪽, 첫 번째 코드 블록의 5번째 줄

    review_text = Beautiful Soup(review, "html5lib").get_text()
    

    ==>

    review_text = BeautifulSoup(review, "html5lib").get_text()
    
  • 163쪽, 맨 마지막 코드 블록의 마지막 줄

    data_configs['vocab_size'] = len(word_vocab)+1
    

    ==>

    data_configs['vocab_size'] = len(word_vocab)
    
  • 164쪽, 첫 번째 코드 블록의 5번째 줄

    print('Shape of train data: ', inputs.shape)
    

    ==>

    print('Shape of train data: ', train_inputs.shape)
    
  • 165쪽, 그림 4.9를 다음 그림으로 교체

    nlp-tf2-4.9.png

  • 166쪽, 첫 번째 코드 블록의 밑에서 2번째 줄

    if not os.path.exists(DATA_OUT_PATH):
    

    ==>

    if not os.path.exists(DATA_IN_PATH):
    
  • 167쪽, 첫 번째 코드 블록의 아래 코드를 삭제

    tokenizer.fit_on_texts(clean_test_reviews)
    
  • 170쪽, 첫 번째 코드 블록의 4번째 줄

    train_data = pd.read_csv(DATA_IN_PATH + TRAIN_CLEAN_DATA, header=0, delimiter="\t", quoting=3)
    

    ==>

    train_data = pd.read_csv(DATA_IN_PATH + TRAIN_CLEAN_DATA)
    
  • 172쪽, 2번째 코드 블록

    print("Accuracy: %f".format(lgs.score(X_eval, y_eval))) # 검증 데이터로 성능 측정
    

    ==>

    print("Accuracy: %f" % lgs.score(X_eval, y_eval)) # 검증 데이터로 성능 측정
    
  • 173쪽, 2번째 코드 블록

    testDataVecs = vectorizer.transform(test['review'])
    

    ==>

    testDataVecs = vectorizer.transform(test_data['review'])
    
  • 173쪽, 마지막 코드 블록의 마지막 줄

    answer_dataset.to_csv(DATA_OUT_PATH + 'lgs_tfidf_answer.csv')
    

    ==>

    answer_dataset.to_csv(DATA_OUT_PATH + 'lgs_tfidf_answer.csv', index=False, quoting=3)
    
  • 182쪽, 첫 번째 코드 블록의 2번째 줄

    answer_dataset.to_csv(DATA_OUT_PATH + 'lgs_answer.csv')
    

    ==>

    answer_dataset.to_csv(DATA_OUT_PATH + 'lgs_w2v_answer.csv', index=False, quoting=3)
    
  • 195쪽, 2번째 코드 블록의 첫 번째 줄

    # overfitting을 막기 위한 ealrystop 추가
    

    ==>

    # overfitting을 막기 위한 earlystop 추가
    
  • 197쪽, 그림 4.19 제목

    로스값

    ==>

    손실값

  • 204쪽, 두 번째 문단

    로스 함수

    ==>

    손실 함수

  • 206쪽, 첫 번째 코드 블록 8번째 줄

    SAVE_FILE_NM = 'weight.h5’
    

    ==>

    SAVE_FILE_NM = 'weights.h5’
    
  • 206쪽, 2번째 코드 블록의 2번째 줄

    predictions = predictions.numpy()
    

    ==>

    predictions = predictions.squeeze(-1)
    
  • 211쪽, 세 번째 코드 블록 1~2번째 줄

    train_lenght
    

    ==>

    train_length
    
  • 212쪽, 첫 번째 코드 블록 2번째 줄

    train_lenght
    

    ==>

    train_length
    
    • 212쪽, 두 번째 코드 블록 1~5번째 줄
    train_lenght
    

    ==>

    train_length
    
  • 213쪽, 첫 번째 코드 블록 1~2번째 줄

    train_lenght
    

    ==>

    train_length
    
  • 213쪽, 세 번째 코드 블록 7번째 줄

    train_lenght
    

    ==>

    train_length
    
  • 214쪽, 14번 각주 내용

    https://software.naver.com/search.nhn?query=한글폰트

  • 227쪽, 첫 번째 문단

    로스값을

    ==>

    손실값을

  • 232쪽, 코드 블록 바로 윗 문단

    캐글의 “Quora Question Pairs” 대회에 들어간 후

    ==>

    캐글의 “Quora Question Pairs” 대회에 들어가 대회 규정에 동의한 후

  • 232쪽, 맨 아래 줄부터

    그러고 나면 다음과 같은 메시지가 나타나면서 데이터 다운로드가 진행되는 것을 확인할 수 있다.

    (중략)

    이 폴더를 확인해 보면 다음과 같은 세 가지 데이터 파일이 있을 것이다.

    ==>

    캐글에서 다운로드한 파일의 압축을 풀고, 아래 3개의 파일을 data_in 폴더로 이동한다.

  • 294쪽, 두 번째 문단

    우선 이 모델은 재귀 순환 신경망(RNN) 모델을 기반으로 하며,

    ==>

    우선 이 모델은 순환 신경망(Recurrent Neural Networks, RNN) 모델을 기반으로 하며,

  • 294쪽, 4~5번째 문단

    재귀 순환 신경망

    ==>

    순환 신경망

  • 295쪽, 두 번째 문단

    재현 신경망

    ==>

    순환 신경망

  • 303쪽, 두 번째 코드 블록 3번째 줄

    PATH = 'data_in/ChatBotData.csv'
    

    ==>

    PATH = 'data_in/ChatBotData.csv_short'
    
  • 308쪽, 두 번째 문단

    해당 모델의 중간에 사용되는 신경망으로는 재귀 신경망을 사용하는데, 다양한 종류의 재현 신경망 중에서

    ==>

    해당 모델의 중간에 사용되는 신경망으로는 순환 신경망을 사용하는데, 다양한 종류의 순환 신경망 중에서

  • 309쪽, 2~3번째 문단

    재귀 순환망

    ==>

    순환 신경망

  • 311쪽, 두 번째 문단

    재귀 순환망

    ==>

    순환 신경망

  • 353쪽, 첫 번째 문단

    로스값을

    ==>

    손실값을

  • 354쪽, 두 번째 문단

    로스 함수

    ==>

    손실 함수

  • 369쪽, 코드 블록

    pip install transformers
    

    ==>

    pip install transformers==2.11.0
    
  • 388쪽, 마지막 예제 코드의 2번째 줄

    plt.hist(train_length, bins=200, range=[0,200], facecolor='r', density=True, label='train')
    

    ==>

    plt.hist(train_bert_token_counts, bins=200, range=[0,200], facecolor='r', density=True, label='train')
    
  • 399쪽, 코드 블록 아래

    로스 값

    ==>

    손실값

  • 427쪽, 첫 번째 수식을 다음 수식으로 교체

    nlp-tf2-p427.png

  • 431쪽, 첫 번째 코드 블록 아래

    로스 값

    ==>

    손실값

  • 454쪽

    그림 7.48 KorSTS 모델의 손실 함수 그래프

    그림 7.49 KorSTS 모델의 피어슨 상관계수 그래프

    ==>

    그림 7.48 KorSTS 모델의 피어슨 상관계수 그래프

    그림 7.49 KorSTS 모델의 손실 함수 그래프

  • 462쪽, 첫 번째 문단 아래

    아웃라이어

    ==>

    이상치

  • 480쪽, 첫 번째 문단에 import 문 추가

    import wget
    
  • 482쪽, 첫 번째 코드 블록

    !wget -P ./bert-base-multilingual-cased/ https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-multilingual-cased-config.json
    !mv ./bert-base-multilingual-cased/bert-base-multilingual-cased-config.json ./bert-base-multilingual-cased/config.json
    !wget -P ./bert-base-multilingual-cased/ https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-multilingual-cased-tf_model
    !mv ./bert-base-multilingual-cased/bert-base-multilingual-cased-tf_model.h5 ./bert-base-multilingual-cased/tf_model.h5
    

    ==>

    wget.download('https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-multilingual-cased-config.json', out='./bert-base-multilingual-cased/')
    os.rename('./bert-base-multilingual-cased/bert-base-multilingual-cased-config.json', './bert-base-multilingual-cased/config.json')
    wget.download('https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-multilingual-cased-tf_model.h5', out='./bert-base-multilingual-cased/')
    os.rename('./bert-base-multilingual-cased/bert-base-multilingual-cased-tf_model.h5', './bert-base-multilingual-cased/tf_model.h5')
    
  • 506쪽, 첫 번째 코드 블록

    !wget https://github.com/NLP-kr/tensorflow-ml-nlp-tf2/releases/download/v1.0/gpt_ckpt.zip -O gpt_ckpt.zip
    !unzip -o gpt_ckpt.zip
    

    ==>

    import wget
    import zipfile
    
    wget.download('https://github.com/NLP-kr/tensorflow-ml-nlp-tf2/releases/download/v1.0/gpt_ckpt.zip')
    with zipfile.ZipFile('gpt_ckpt.zip') as z:
        z.extractall()
    
  • 512쪽, 소설 텍스트 데이터 전처리하기'의 첫 번째 코드 블록 4번째 줄

    sents = [s[:-1] for s in open(DATA_IN_PATH + TRAIN_DATA_FILE).readlines()]
    

    ==>

    sents = [s[:-1] for s in open(DATA_IN_PATH + TRAIN_DATA_FILE, 'rb', encoding='utf-8).readlines()]
    
  • 522쪽, 그림 7.74

    로스 함수

    ==>

    손실 함수

  • 523쪽, 첫 번째 줄

    로스 그래프

    ==>

    손실 그래프

  • 527쪽, 두 번째 코드 블록 1, 5번째 줄

    infer_model
    

    ==>


    sim_model
  • 527쪽, 두 번째 코드 블록 아래 문단

    로스 함수

    ==>

    손실 함수

  • 528쪽, 첫 번째 코드 블록 5번째 줄

    infer_model
    

    ==>

    sim_model
    
  • 528쪽, 첫 번째 코드 블록 아래 문단

    로스 그래프

    ==>

    손실 그래프

  • 530쪽, 첫 번째 코드 블록 11, 13번째 줄

    infer_model
    

    ==>

    sim_model
    
  • 541쪽, 3번째 아래 문단 삭제

    여러분은 4장부터 7장까지 모든 실습을 마쳤다. 다뤄본 실습들은 실제 자연어 처리에서 충분히 다뤄볼 수 있는 문제들이다. 특히 이번 7장에서는 다양한 자연어 처리 문제들을 사전학습 모델인 버트와 GPT2를 통해 풀었다. 사전 학습 모델과 미세조정에 대한 새로운 콘셉트를 이해하고 문제를 풀어가는 방법이 기존 장들에 비해 어렵지만 7장의 모든 실습을 수행했다면 한층 더 높은 수준의 최신 자연어 처리 방법을 이해했을 것으로 본다. 실습을 통해 자연어 처리 기술을 다뤄 볼 자신감이 생겼다면 여러분은 이미 딥러닝 자연어 처리 전문가의 첫발을 내디딘 것이다. 이제 지금껏 다뤄본 텍스트 분류, 텍스트 유사도, 개체명 인식 그리고 기계 독해 모델들을 가지고 자연어 처리 현장에 새로운 기술들을 적용해보는 선구자가 되길 바란다.