Natural Language Processing with PyTorch
  • 소개글
  • 서문
  • Index
  • 딥러닝을 활용한 자연어 처리 개요
    • 자연어 처리란 무엇일까?
    • 딥러닝 소개
    • 왜 자연어 처리는 어려울까?
    • 무엇이 한국어 자연어 처리를 더욱 어렵게 만들까?
    • 자연어 처리의 최근 추세
  • 기초 수학
    • 서문
    • 랜덤 변수와 확률 분포
    • 쉬어가기: 몬티 홀 문제
    • 기대값과 샘플링
    • Maximum Likelihood Estimation
    • 정보 이론
    • 쉬어가기: MSE 손실 함수와 확률 분포 함수
    • 마치며
  • Hello 파이토치
    • 딥러닝을 시작하기 전에
    • 설치 방법
    • 짧은 튜토리얼
    • 쉬어가기: 윈도우즈 개발 환경 구축
  • 전처리
    • 전처리란
    • 코퍼스 수집
    • 코퍼스 정제
    • 분절
    • 병렬 코퍼스 정렬
    • 서브워드 분절
    • 분절 복원
    • 토치텍스트
  • 유사성과 모호성
    • 단어의 의미
    • One-hot 인코딩
    • 시소러스를 활용한 단어 의미 파악
    • 특징
    • 특징 추출하기: TF-IDF
    • 특징 벡터 만들기
    • 특징 유사도 구하기
    • 단어 중의성 해소
    • Selectional Preference
    • 마치며
  • 단어 임베딩
    • 들어가며
    • 차원 축소
    • 흔한 오해 1
    • Word2Vec
    • GloVe
    • Word2Vec 예제
    • 마치며
  • 시퀀스 모델링
    • 들어가며
    • Recurrent Neural Network
    • Long Short Term Memory
    • Gated Recurrent Unit
    • 그래디언트 클리핑
    • 마치며
  • 텍스트 분류
    • 들어가기
    • 나이브 베이즈를 활용하기
    • 흔한 오해 2
    • RNN을 활용하기
    • CNN을 활용하기
    • 쉬어가기: 멀티 레이블 분류
    • 마치며
  • 언어 모델링
    • 들어가며
    • n-gram
    • 언어 모델의 평가 방법
    • SRILM을 활용한 n-gram 실습
    • NNLM
    • 언어 모델의 활용
    • 마치며
  • 신경망 기계번역
    • 들어가며
    • Sequence-to-Sequence
    • Attention
    • Input Feeding
    • 자기회귀 속성과 Teacher Forcing 훈련 방법
    • 탐색(추론)
    • 성능 평가
    • 마치며
  • 신경망 기계번역 심화 주제
    • 다국어 신경망 번역
    • 단일 언어 코퍼스를 활용하기
    • 트랜스포머
    • 마치며
  • 강화학습을 활용한 자연어 생성
    • 들어가며
    • 강화학습 기초
    • 정책 기반 강화학습
    • 자연어 생성에 강화학습 적용하기
    • 강화학습을 활용한 지도학습
    • 강화학습을 활용한 비지도학습
    • 마치며
  • 듀얼리티 활용
    • 들어가며
    • 듀얼리티를 활용한 지도학습
    • 듀얼리티를 활용한 비지도학습
    • 쉬어가기: Back-translation을 재해석하기
    • 마치며
  • NMT 시스템 구축
    • 파이프라인
    • 구글의 NMT
    • 에딘버러 대학의 NMT
    • MS의 NMT
  • 전이학습
    • 전이학습이란?
    • 기존의 사전 훈련 방식
    • ELMo
    • BERT
    • GPT-2
    • XLNet
    • 마치며
  • 이 책을 마치며
  • 참고문헌
Powered by GitBook
On this page
  • SRILM 설치하기
  • 데이터셋 준비하기
  • 기본 사용법
  • 언어모델 만들기
  • 문장 생성하기
  • 평가
  • 인터폴레이션
  1. 언어 모델링

SRILM을 활용한 n-gram 실습

Previous언어 모델의 평가 방법NextNNLM

Last updated 5 years ago

SRILM은 음성 인식이나 분절, 기계번역 등에 쓰이는 n-gram 언어 모델을 쉽게 구축하고 적용할 수 있는 툴킷입니다.

SRI speech research lab에서 1995년부터 연구, 개발해 온 유서깊은 툴킷입니다.

SRILM 설치하기

다음 사이트( 간단한 정보를 기입한 후 내려받을 수 있습니다. 이후에 다음과 같이 디렉터리를 만들고 그 안에 압축을 풉니다.

$ mkdir srilm
$ cd ./srilm
$ tar –xzvf ./srilm-1.7.2.tar.gz

디렉터리 내부에 Makefile을 열어 7번째 라인의 SRILM의 경로 지정 후에 주석을 해제합니다. 그리고 make 명령을 통해 SRILM을 빌드합니다.

$ vi ./Makefile
$ make

빌드가 정상적으로 완료되면 PATH에 SRILM/bin 내부에 새롭게 생성된 디렉터리를 등록한 후 익스포트합니다.

PATH={SRILM_PATH}/bin/{MACHINE}:$PATH
#PATH=/home/khkim/Workspace/nlp/srilm/bin/i686-m64:$PATH
export PATH

다음과 같이 ngram-count와 ngram이 정상적으로 동작하는 것을 확인합니다.

$ source ~/.profile
$ ngram-count -help
$ ngram -help

데이터셋 준비하기

이전 전처리 장에서 다루었던 대로 분절이 완료된 파일을 데이터로 사용합니다. 그렇게 준비된 파일을 훈련 데이터와 테스트 데이터로 나누어 준비합니다.

기본 사용법

다음은 주로 SRILM에서 사용되는 프로그램들의 주요 인자에 대한 설명입니다.

  • ngram-count: LM을 훈련

    • vocab: lexicon file name

    • text: training corpus file name

    • order: n-gram count

    • write: output countfile file name

    • unk: mark OOV as

    • kndiscountn: Use Kneser-Ney discounting for N-grams of order n

  • ngram: LM을 활용

    • ppl: calculate perplexity for test file name

    • order: n-gram count

    • lm: language model file name

언어모델 만들기

앞에서 나온 대로, 언어 모델을 훈련하기 위해서는 ngram-count 모듈을 이용합니다. 다음의 명령어는 예를 들어 kndiscount를 사용한 상태에서 3-gram을 훈련하고 언어 모델과 언어 모델을 구성하는 어휘 사전을 출력하도록 하는 명령입니다.

$ time ngram-count -order 3 -kndiscount -text <text_fn> -lm <output_lm_fn> -write_vocab <output_vocab_fn> -debug 2

문장 생성하기

다음 명령은 ngram-count 모듈을 사용해서 만들어진 언어 모델을 활용하여 문장을 생성합니다. 문장을 생성한 이후에는 전처리 장에서 다루었듯이 분절을 복원하는 작업을 수행해주어야 합니다. 리눅스 파이프라인을 연계하여 sed를 통한 정규 표현식을 사용하여 분절을 복원하도록 했습니다.

$ ngram -lm <input_lm_fn> -gen <n_sentence_to_generate> | sed "s/ //g" | sed "s/▁▁/ /g" | sed "s/▁//g" | sed "s/^\s//g"

이와 같이 매번 sed와 정규 표현식을 통하는 것이 번거롭다면, 파이썬으로 직접 해당 작업을 하도록 코드를 작성하는 것도 좋은 방법입니다.

평가

이렇게 언어 모델을 훈련하고 나면 테스트 데이터에 대해서 평가를 통해 얼마나 훌륭한 언어 모델이 만들어졌는지 평가해야 합니다. 언어 모델에 대한 성능평가는 다음과 같은 명령을 통해 수행될 수 있습니다.

$ ngram -ppl <test_fn> -lm <input_lm_fn> -order 3 -debug 2

다음은 앞의 명령에 대한 예시입니다. 실행을 하면 OoVs(Out of Vocabularies, 테스트 데이터에서 보지 못한 단어)와 해당 테스트 문장들에 대한 PPL이 나옵니다. 주로 문장 수에 대해서 평균을 계산한 (ppl1이 아닌) ppl을 참고하면 됩니다.

$ ngram -ppl ./data/test.refined.tok.bpe.txt -lm ./data/ted.aligned.en.refined.tok.bpe.lm -order 3 -debug 2
...
...
file ./data/test.refined.tok.bpe.txt: 1000 sentences, 13302 words, 32 OOVs
0 zeroprobs, logprob= -36717.49 ppl= 374.1577 ppl1= 584.7292

앞의 평가 과정에서는 1,000개의 테스트 문장에 대해서 13,302개의 단어가 포함되어 있었고, 개중에 32개의 OoV가 발생했습니다. 결국 이 테스트에 대해서는 약 374의 ppl이 측정되었습니다. 이 ppl을 여러 가지 하이퍼파라미터 튜닝 또는 적절한 훈련데이터 추가를 통해서 낮추는 것이 관건이 될 것입니다. 그리고 -debug 파라미터를 2를 주어, 다음과 같이 더 자세한 각 문장과 단어별 로그를 볼 수 있습니다. 실제 언어 모델에서 어떤 n-gram이 일치(hit)되었는지 이에 대한 확률을 볼 수 있습니다. 3-gram이 없는 경우에는 2-gram이나 1-gram으로 백오프되는 것을 확인할 수 있고, 백오프 시에는 확률이 굉장히 떨어지는 것을 볼 수 있습니다.

필자가 직접 크롤링하고 분절한 TED 코퍼스에 대해 실험한 결과입니다.

▁▁I ▁▁m ▁▁pleased ▁▁with ▁▁the ▁▁way ▁▁we ▁▁handled ▁▁it ▁.
p( ▁▁I | <s> )     = [2gram] 0.06806267 [ -1.167091 ]
p( ▁▁m | ▁▁I ...)     = [1gram] 6.597231e-06 [ -5.180638 ]
p( ▁▁pleased | ▁▁m ...)     = [1gram] 6.094323e-06 [ -5.215075 ]
p( ▁▁with | ▁▁pleased ...)     = [2gram] 0.1292281 [ -0.8886431 ]
p( ▁▁the | ▁▁with ...)     = [2gram] 0.05536767 [ -1.256744 ]
p( ▁▁way | ▁▁the ...)     = [3gram] 0.003487763 [ -2.457453 ]
p( ▁▁we | ▁▁way ...)     = [3gram] 0.1344272 [ -0.8715127 ]
p( ▁▁handled | ▁▁we ...)     = [1gram] 1.902798e-06 [ -5.720607 ]
p( ▁▁it | ▁▁handled ...)     = [1gram] 0.002173233 [ -2.662894 ]
p( ▁. | ▁▁it ...)     = [2gram] 0.05907027 [ -1.228631 ]
p( </s> | ▁. ...)     = [3gram] 0.8548805 [ -0.06809461 ]
1 sentences, 10 words, 0 OOVs
0 zeroprobs, logprob= -26.71738 ppl= 268.4436 ppl1= 469.6111

앞의 결과에서는 10개의 단어가 주어졌고, 5번 백오프되어 3-gram은 3개만 일치되었고, 4개의 2-gram과 4개의 1-gram이 일치되었습니다. 그리하여 -26.71의 로그 확률이 계산되어 268의 PPL로 환산되었음을 볼 수 있습니다.

인터폴레이션

SRILM을 통해서 단순한 스무딩(또는 디스카운팅)뿐만이 아니라 인터폴레이션을 수행할 수도 있습니다. 이 경우에는 완성된 두 개의 별도의 언어 모델이 필요하고, 이를 섞어주기 위한 하이퍼파라미터 $\lambda$ (람다)가 필요합니다. 다음과 같이 명령어를 입력하여 인터폴레이션을 수행할 수 있습니다.

$ ngram -lm <input_lm_fn> -mix-lm <mix_lm_fn> -lambda <mix_ratio_between_0_and_1> -write-lm <output_lm_fn> -debug 2

인터폴레이션 이후 성능 평가를 수행하면, 경우에 따라 성능이 향상하는 것을 볼 수 있을 것입 니다. 람다를 튜닝하여 성능 향상의 폭을 더 높일 수 있습니다.

http://www.speech.sri.com/projects/srilm/download.html)에서