Natural Language Processing

Natural Language Processing with Classification and Vector Spaces

Week1: Sentiment Analysis with Logistic Regression

  • Logistic Regression 적용해보기
    • tweet의 postiive, negative 판단하기
    • supervised model
  • Bag of word, Document-Term Matrix
    • Sparse representation이 문제
    • 중요 단어, 순서, 관계 표현 못함
  • 빈도수 합으로 표현
    • corpus내 모든 단어의 PosFreq, NegFreq 구함
    • sumPosFreq: 문장 내 단어들의 PosFreq 합
    • $X_m = [1, \sum_w PosFreq(w), \sum_w NegFreq(w)]$
  • preprocessing
    • stopword: and, is, a, at 등 지우기
    • punctuation: 쉼표, 마침표 등 지우기
    • stemming: tune, tuned, tuning
    • lowercasing: 소문자로 바꾸기
  • logistic regression
    • classify/predict: $h = sigmoid(\theta \cdot x)$
    • cost function: $J = \frac{-1}{m}(y^T \cdot \log{h} + (1-y)^T \cdot \log(1-h))$
    • update grad: $\theta = \theta - \frac{\alpha}{m} x^T \cdot (h-y)$
    • until cost is low enough
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import nltk                                # Python library for NLP
from nltk.corpus import twitter_samples    # sample Twitter dataset from NLTK
from nltk.corpus import stopwords          # module for stop words that come with NLTK
from nltk.stem import PorterStemmer        # module for stemming
from nltk.tokenize import TweetTokenizer   # module for tokenizing strings

tokenizer = TweetTokenizer(preserve_case=False, strip_handles=True, reduce_len=True)
stemmer = PorterStemmer() 

def process_tweet(tweet):
  tweet = re.sub(r'^RT[\s]+', '', tweet)
  tweet = re.sub(r'https?://[^\s\n\r]+', '', tweet)
  tweet = re.sub(r'#', '', tweet)
  tokens = tokenizer.tokenize(tweet)
  tokens = [t for t in tokens if not t in stopwords.words('english')]
  tokens = [t for t in tokens if not t in string.punctuation]
  tokens = [stemmer.stem(t) for t in tokens]
  return tokens

def gradientDescent(x, y, theta, alpha, num_iters):
    m = x.shape[0]
    for i in range(0, num_iters):
        z = np.dot(x, theta)
        h = sigmoid(z)
        J = (-1/m) *  (np.dot(y.T, np.log(h)) + np.dot((1-y).T, np.log(1-h)))
        theta -= (alpha / m) * np.dot(x.T, h - y)
    return float(J), theta

Week2: Sentiment Analysis with Naïve Bayes

  • 나이브 베이즈 분류기
    • 긍정일때 단어의 분포, 부정일때 단어의 분포 알고있음 = $P(w_i \vert pos)$
    • 문장이 등장했을때, 긍정인지 부정인지 알고싶음
    • 문장 = 단어 여러개
    • 즉 단어 여러개에 대해 긍정인지 부정인지 알고 싶음 = $P(neg \vert w_1 w_2 .. w_m)$
    • 단어 각각의 등장이 독립적이라고 가정함
    • $NaiveBayes = \prod_i \cfrac {P({w_i}\vert pos)}{P({w_i}\vert neg)}$
  • 유도과정
    • 단어들의 곱사건 을 $W$라 할때 $W = \prod_i{w_i}$
    • $P(pos\vert W) = P(W\vert pos) \cfrac{P(pos)}{P(W)}$
    • $P(neg\vert W) = P(W\vert neg) \cfrac{P(neg)}{P(W)}$
    • $NaiveBayes = \cfrac{P(pos\vert W)}{P(neg\vert W)}$
    • 독립이면 $P(W\vert pos) = \prod_i P(w_i\vert pos)$
    • $NaiveBayes = \cfrac {P(pos)}{P(neg)} \prod_i \cfrac {P({w_i}\vert pos)}{P({w_i}\vert neg)}$
    • positive, negative 비율이 같다면
    • $NaiveBayes = \prod_i \cfrac {P({w_i}\vert pos)}{P({w_i}\vert neg)}$
  • laplacian smoothing
    • $P({w_i}\vert neg)$이 0이라면 0으로 나누게되어서 위 식 못씀
    • 때문에 공통적으로 분자 분모에 특정 값을 더해서 보정해줌
    • $P({w_i}\vert neg) = \cfrac{freq(w_i, neg) + 1}{N_{neg} + m}$
    • $m$은 $w_i$에서 가능한 $i$의 수이고, 때문에 $\sum_{i=1}^m P(w_i \vert neg) = 1$
  • log likelihood
    • 여러번 나누는 floating point연산은 underbound가 날 가능성이 높음
    • 그러므로 log를 취해서 계산
    • $\lambda(w) = \log {\cfrac {P(w \vert pos)}{P(w \vert neg)}}$
    • 미리 람다를 계산해두고 나중에는 더하기만 하면 됨
  • 나이브 베이즈 문제점들
    • 독립조건 맞추기 어려움
    • 비율이 비슷한 데이터셋은 많지 않음
    • 단어 순서를 무시함
  • 그 밖에 고려할 점
    • punctuation 지우면서, 지워지는 이모티콘이 감정을 나타내기도 함
    • not등 stopword를 지우면서 의미가 바뀌기도 함
    • 반어, 모순 등을 고려할것

Week3: Vector Space Models

  • distance, cosine similarity
  • word analogy test
    • Seoul -> Korea == Paris -> France
  • PCA
    • 벡터를 더 낮은 차원으로 근사해 visualize하는데 사용
    • 자세한 내용에 대해서는 추가 학습이 필요
  • 기계번역
    • 두 언어에 대한 임베딩 X, Y가 주어지고
    • 두 언어의 단어들에 대한 매핑이 주어질 때
    • $XR = Y$를 만족하는 $R$을 찾기
  • 행렬에 대한 회귀분석 하기
    • evaluate: $| F G |_F^2$
    • loss: $| XR - Y |_F^2$
    • gardient: $\frac{2}{m}(X^T(XR-Y))$
    • test: Locality Sensitive Hashing (LSH) + K-mean
  • Locality Sensitive Hashing (LSH)
    • 랜덤한 여러개의 hyper-plane, 해당 평면들의 normal vector
    • norm-vec에 대한 내적값으로 bit-hash
    • 같은 hash를 가지는 점에 대해서만 K-mean 적용
    • planes need to be considered: $N$ -> $N/(2^{plane count})$

Natural Language Processing with Probabilistic Models

Week1: Autocorrect

  • edit distance 계산에 관한 내용
  • 기본적인 DP만 알면 됨

Week2: Part of Speech Tagging and Hidden Markov Models

  • part of speech tagging: 품사, Named entitiy 추정
  • Markov Assumption
    • 미래 상태는 현재 상태에만 영향을 받는다.
    • $P(S_{t+1} \vert S_1, …, S_{t}) = P(S_{t+1} \vert S_t)$
  • Markov Chain
    • 시스템을 상태의 전이로 표현
    • state transition prob matrix $A(a_{ij}) = P(S_j \vert S_i)$
    • state로 sequence 데이터를 표현할 수 있다.
  • Hidden Markov Model $\lambda = (A, B, \pi)$
    • 두 sequence가 주어짐 (observable, hidden)
    • observable($O_k$)은 hidden($S_i$)에 종속적이라고 간주
    • state transition prob matrix $A(a_{ij} = P(S_{t+1} = s_j \vert S_{t} = s_i))$
    • emisstion prob matrix $B(b_{jk} = P(O_t = o_k \vert S_t = s_j))$
    • initial state prob matrix $\pi(\pi_{i} = P(S_1 = {s_i}))$
  • HMM 문제(1) - Evaluation: O가 관측될 확률
    • Question: $P(O_1 = o_a, O_2 = o_b, O_3 = o_a)$ ?
    • 베이즈 공식을 쓰면, 계산량이 폭발함
    • $\sum_{i,j,k} P(o_a, o_b, o_a \vert s_i, s_j, s_k)$
    • forward algorithm (dynamic programming) 사용
    • $\alpha_1(i)=P(O_1=o_a, S_1=s_i) = \pi_i * b_{ia}$
    • $\alpha_2(i)=P(O_1=o_a, O_2=o_b, S_2=s_i) = (\sum_j \alpha_1(j)*a_{ji})*b_{ib}$
    • 마지막 상태 은닉상태를 기준으로 종합하므로, 이후 상태 전이에 활용 가능해짐
  • HMM 문제(2) - Decoding: O가 주어질때 가장 가능성있는 H를 찾기
    • viterbi algorithm 사용
    • forward algorithm의 sum 대신 argmax를 사용
    • 이전 상태의 최대값 기준으로 전이시켜 다시 최대값을 찾는 방법
    • $v_1(i) = \pi_i * b_{ia}$
    • $v_2(i) = [argmax_j v_1(j) * a_{ji}] * b_{ib}$
    • optimal pass를 찾기 위해 최대값을 찾았던 인덱스를 저장해둬야함
    • 이후 마지막 최대값으로 부터 인덱스 보면서 따라가면 됨
    • viterbi, forward 모두 로그를 취한 확률을 더하는게 좋음(underflow 방지)
  • HMM 문제(2) - Learning: 파라미터 학습하기
    • Baum-Welch Algorithm 사용
    • 나중에 학습하기 링크

Week3: Autocomplete and Language Models

  • N-gram: n개의 이전 단어를 가정하고, 현재 단어의 확률찾기
    • word sequence 문자($w_a^b$) = a에서서 b까지의 문자가 연속으로 등장할 확률
    • N-gram: $P(w_n \vert w_{n-1}^{n-N+1})$
    • word seq확률: $P(w_1^n) = P(w_1) \prod_{i=1}^n P(w_i \vert w_{i-1})$
  • N-gram과 시작 문자, 종료 문자
    • 시작 문자 N-1개가 있으면 $P(w_1)$항을 없앨 수 있다.
    • $P(w_0^n) = \prod_{i=0}^n P(w_i \vert w_{i-1})$
    • 종료 문자가 있으면 길이가 다른 문장의 생성확률이 하나의 확률공간으로 묶인다.
  • N-gram LM
    • N-gram은 카운트로 계산 가능
    • $b-a = n-1$일때 $P(w_b \vert w_a^{b-1}) = C(w_a^b)/C(w_a^{b-1})$
    • underflow 방지를 위해 로그 확률의 합으로 계산
    • 평가 지표는 Perplexity(lower is better) 사용
    • $logPP(W)= \displaystyle-\frac{1}{m}\sum_{i=1}^m \log_2 P(w_i \vert w_{i-1})$
  • out-of-vocab word
    • vocab에 없는 단어는 기본적으로 확률계산 불가
    • <UND>로 변경해서 진행
    • 이 경우 Perplexity는 낮아지지만, 실제로 좋아지는건 아니다.
  • Smoothing
    • vocab에 있는 문자도 분모나 분자가 0이 될수 있음
    • 이 경우 동일한 비율만큼 분모 분자에 더해서 0을 방지

Week4: Word embeddings with neural networks

  • word vector
    • Integer: (+)simple, (-)순서가 의미 없음
    • One-hot: (+)simple, (+)순서 내포 안함, (-)임베딩 함의 없음, (-)Sparse함
  • basic word embedding
    • word2vec (Google, 2013) CBOW / Skip-gram
    • Global Vector, GloVe (Stanford, 2014)
    • fastText (Facebook, 2016), out-of-vocab word 지원
  • advanced word embedding with DL
    • BERT(Google, 2018)
    • ELMo(Allen Institute for AI, 2018)
    • GPT-2(OpenAI, 2018)
  • CBOW: Continuous bag-of-words
    • 중심어 주변으로 window size만큼 단어를 문맥으로 취급
    • context word vector -> center word vector
    • 기본적으로 one-hot으로 단어 벡터를 만든다.
    • context word vector = window내 단어들의 one-hot의 평균
    • V는 사전의 크기, N은 임베딩의 크기, B는 배치 크기
    • ctx(V) -> Dense1(N) -> ReLU -> Dense2(V) -> Softmax
    • (V,B) -> Dense1(N) -> (N,B) -> Dense2(V) -> (V,B)
    • 임베딩은 Dense1의 W1과 Dense2의 W2.T의 합으로 구함

Natural Language Processing with Sequence Models

Week1. Neural Networks for Sentiment Analysis

  • 기초적인 DL로 Embedding을 수행해보는 챕터
  • trax에서 지도학습은 크게 4가지 과정을 거침
    • data generator: (input tensor, label tensor)을 생성
    • model: 여러 레이어를 쌓거나, 기 존재하는 모델을 사용
    • task: loss, optimizer, metrics를 정해서 TrainTask, EvalTask 생성
    • loop: 위에 3가지를 모두 넣고 생성한 뒤에 run으로 돌리면 됨.
  • trax의 layer 특징들
    • 기본적으로 출력 차원만을 설정함
    • 파라미터의 크기는 input tensor의 signature를 통해서 알아서 설정함
    • 손실함수를 줄이기 위한 grad-decent를 알아서 해줌
    • Keras layer에서 거의 아이디어를 가져온듯함, 매우 유사함
  • 여러 레이어들
    • Dense: $z = Wa + b$,
    • Embedding: int32(word) -> vector, vocab/embedding의 크기 필요
    • LSTM, GRU: rnn의 LSTM, GRU레이어
    • Mean: 평균 내주는 레이어
    • LogSoftmax: log softmax 함수
    • Select: 입력의 index를 재배열한 새 배열을 기반으로 출력을 만듬
  • 합성 레이어들
    • Serial: 스택 기반의 순차처리, sublayer는 top에서 하나씩 꺼내쓰고 다시 push한다.
    • Branch: 여러 레이어 실행, Serial내 stack에서 쭉 꺼내씀
    • Parallel: 여러 레이어 실행 후, 결과를 이어붙여 만들어줌
  • (추가) Embedding vs Word2Vec
    • Word2Vec은 두 Dense 레이어를 통해서 의미론적 동치를 파악 가능
    • Embedding은 그냥 정수에서 임의 vector를 매핑하는 형태
    • Embedding만 단독으로 쓰일 경우, 단어자체의 의미론적 동일을 못찾음
  • Semantic analysis 모델
    • 모델 Embedding(단어) -> Mean(문장) -> Dense(2) -> LogSoftmax
    • loss = tl.CrossEntropyLoss()
    • optimizer = trax.optimizers.Adam(training_rate)

Week2. Recurrent Neural Networks for Language Modeling

  • Vanilla RNN (Recurrent Neural Network)
    • 여러 단어를 배치로 집어넣되
    • 이전 배치에서 쓴 상태값을 이용하여 현재 상태를 정함
    • 긴 sequence에 대해서 정확도가 떨어짐
    • gradient vanishing 발생
    • $h_t = g(W_{h}[h_{t-1},x_t] + b_h)$
    • $\hat{y}t = g(W{yh}h_t + b_y)$
  • GRU (Gated Recurrent Unit)
    • 사실 LSTM의 복잡성을 감소시킨 모델로 LSTM보다 뒤에 나옴
    • 하지만 간단하기 때문에 강의에서는 먼저 다룸
    • reset으로 이전 state에서 필요 없는 것들을 지움
    • reset과 곱해주어서 candidate state를 생성
    • update gate로 이전 state와 candidate간의 반영 비율 결정
    • 이전 state가 activation 없이 통과 가능 -> gradient vanishing 문제 없음
    • reset gate: $\Gamma_r = \sigma(W_r[h_{t-1},x_t]+b_r)$
    • update gate: $\Gamma_u = \sigma(W_u[h_{t-1},x_t]+b_u)$
    • candidate: $h’t = \tanh(W_h[\Gamma_r*h{t-1},x_t]+b_u)$
    • hidden state: $h_t =(1-\Gamma_u)*h_{t-1}+\Gamma_r*h’_t$
    • output: $\hat{y}t = g(W{y}h_t + b_y)$
  • RNN 활용
    • one to one: 경기 결과 시퀀스로 순위 예측
    • one to many: 이미지로 문장 생성, 첫번째 그림 입력 이후
    • many to one: 문장으로 감정 예측
    • many to many: 기계번역, 요약
    • bi-directional RNN: 두 RNN 모델을 양쪽 방향으로 따로 훈련시킨 뒤 합치거나 평균
    • deep RNNs: 여러 층의 RNN을 겹쳐서 추가

Week3. LSTMs and Named Entity Recognition

  • vanishing gradient
    • activation과 weight를 거치면서 gradient가 급속도로 감소함
    • 긴 문장의 첫 단어가 거의 시스템에 영향을 주지 못함
  • LSTM
    • GRU랑 거의 똑같음
    • cell/hidden state 두가지 상태를 유지함
    • cell state는 activation을 거치지 않음
    • hidden state는 cell state를 output gate에 넣어서 생성
    • 이전 state에서 필요 없는것을 지우기 위한 forget gate
    • 어떤 상태를 써야하는지 고르기 위한 input gate
    • forget: $f_t = \sigma(W_f[h_{t-1}, x_t]+ b_f)$
    • input: $i_t = \sigma(W_i[h_{t-1}, x_t]+ b_i)$
    • candidate: $\tilde{C_t} = \tanh(W_C[h_{t-1}, x_t]+ b_C)$
    • cell state: $C_t = f_t* C_{t-1} + i_t * \tilde{C_t}$
    • output: $f_o = \sigma(W_o[h_{t-1}, x_t]+ b_o)$
    • hidden state: $h_t = o_t * tanh(C_t)$
  • Named Entity Recognition
    • 각 단어의 속성 추정, 이름/장소/시간
    • Embedding(n_vocab, d_model) -> LSTM(d_model) -> Dense(n_tag) -> LogSoftmax

Week4. Siamese Networks

  • 분류는 어렵지만, 동일성 판단은 쉬운것을 이용
  • Siamese network
    • 두 문장을 LSTM으로 통과시킨 후, cos-sim을 구함
    • 2개 쌍의 sim을 구한뒤 뺌 (Anchor, Positive) (Anchor, Negative)
    • $Loss = max(0, s(A,N) - s(A,P) + \alpha)$
    • 데이터 생성시 v1과 v2에 각각 duplicated인 질문을 쌍으로 넣는다.
    • v1(Batch, X1), v2(Batch, X2) 결과를 벡터로 뽑은뒤 내적하면
      • (Batch, Batch) 크기의 내적 배열이 된다.
      • 이때 대각선은 duplicated
      • 나머지는 not-duplicated가 된다.
    • 개별 모델: Embedding -> LSTM -> Mean -> divide-by-sum-sqrt
    • Siamese: Parallel(Model, Model)
    • Loss = triplet loss

Natural Language Processing with Attention Models

Week1. Neural Machine Translation

  • seq2seq (초기)
    • encoder: Embed + LSTM -> last state
    • decoder: Embed + LSTM -> cascading input
    • 문제점: 문장이 길 경우, grad-vanishing
  • seq2seq + attention
    • input: encoder outputs + decoder last state
    • attention 계산 = input -> FFN -> Softmax
    • 여전히 문자이 길 경우, grad-vanishing. RNN을 쓰면 안됨
    • 그러나 attention 없는것 보다는 훨씬 좋음
  • Scaled dot-prodcut attention
    • RNN, LSTM 없이 NLP를 하고자 고안된 Self-attention 레이어
    • $softmax(\cfrac{QK}{\sqrt{d_k}})V$
    • 문자을 벡터로 임베딩 한뒤, 가중치를 곱해서 같은 크기의 Q,K,V를 구함 Q.shape = (n, m)
    • QK가 단어와 단어 사이의 연관성을 나타내게 됨 Q.dot(K).shape ==(n,n)
    • 이걸 scaled-softmax를 적용하면, 확률로 변경됨
    • V를 적용해서 연관성을 다시 행렬곱 Z.dot(V) == (n,m)
    • 단어간 연관성 확률을 임베딩 벡터에 곱하게 됨
    • 즉 관련 높은 단어의 벡터쪽으로 위치가 이동하는 효과
  • Teacher Forcing
    • 디코딩 레이어 훈련시, 훈련 가속화 방법
    • 디코딩 레이어는 보통 이전 step의 결과를 입력으로 활용함
    • teacher forcing은 대신에 올바른 결과를 입력으로 넣어줌
    • 훨씬 더 빠르게 수렴하는 효과
  • BLEU, ROUGE-N, F1 score
    • 발생 빈도를 근거로 하는 스코어 판별법들
    • 사람의 판단과 양의 상관관계를 보이기 때문에 자주 사용됨
    • BLEU는 번역된 문자의 단어가 Reference내에 존재했는지 여부로 판단
    • ROUGE-N은 Reference내 단어가 번역된 분장 내에 얼마나 존재하는지 여부로 판단
    • 둘을 섞어서 조화평균을 돌리면 F1 스코어를 얻을 수 있음

Week2. Text Summarization

  • RNN과 LSTM의 문제
    • Loss of information
    • Vanishing gradient
  • Transformer는 RNN과 LSTM을 사용하지 않음
    • Encoder와 Decoder만을 사용
    • GPT, BERT, T5로 이어지면서 발전함
    • Pretrain후 fine-tuning이 가능
    • t5는 한번의 훈련으로 다목적으로 사용 할 수 있음
  • Masked Self-Attention
    • Scaled dot-product attention에서 QK의 결과를 마스킹
    • 우상단 삼각형(현재 단어보다 뒤쪽)을 $-\inf$ 로 마스킹
    • 디코더에서만 사용
    • 디코더 특성상, 다음 단어를 예측하는데에 미래의 단어가 사용되면 안됨
  • Multi-head Attention
    • 어탠션 여러개를 훈련시킨후 concat함
    • 이후 fully-connected를 거쳐서 입력과 동일한 차원의 벡터로 바꿔줌
  • Decoder
    • Embedding
    • Positional encoder
    • Residual(Masked Multi-head attention) x N
    • Add & Norm x N
    • Residual(Feed Forward) x N
    • Add & Norm x N
    • Linear
    • Softmax

Week3. Question Answering

  • Pretrained models
    • ELMo: Bidirectional RNNs
    • GPT: only decoder
    • BERT: only encoder
    • T5: decoder & encoder
  • BERT
    • encoder 블럭을 여러겹 쌓음
    • 한 레이어에서 다음 레이어로 할때 각 encoder/decoder가 fully-connected
    • 즉 양쪽 방향으로 다 봄
    • 토큰을 비워놓고 들어갈 단어를 맞추는 형태
  • Encoder
    • Embedding
    • Positional encoder
    • Residual(Maksed Multi-head attention) x N
    • Add & Norm x N
    • Residual(Feed Forward) x N
    • Add & Norm x N

Week4. Chatbot

  • Attention의 문제점
    • 아주 긴 문장에서 $L^2$ 만큼 시간, 공간을 잡아먹음
    • 특별히 $QK^T$ 계산 결과를 각 레이어만큼 보관해야함
    • 이 경우 매우 큰 메모리를 사용하게됨
  • LSH Attention
    • 어텐션 계산을 $L^2$로 하지 말고, 쪼개서 함
    • 쪼개는 기준은 Locality Sensitive Hashing
    • 각 bucket 기준으로만 곱하면 저장량이 확 줄어듬
  • Reversible Residual Layers(RevNet)
    • 모델을 두 채널로 나눠서 함께 훈련시킴킴
    • 이러면 중간 결과들만 가지고 activation들을 구할 수 있음
    • 즉 저장할 필요가 없어져서 메모리가 세이브됨