Week3
- ツール
- 自然言語の特性
- 自然言語処理へのアプローチ
- 理性主義的アプローチ
- 言語学, 論理学に基づいて、知識をルール・手続き化する演繹的手法
- 経験主義的アプローチ
- 伝統的な自然言語処理と言語学
- 単語の処理
- 前処理, 正規化
- 単語 N グラム
- 品詞付与
- ベクトルによる単語の意味表現
- 構文解析
- 応用システム
- Time flies like an arrow.
- 単語の認識 (tokenization)
- 正規化処理
- 小文字への統一
- 辞書見出し形 (原形) への変換: lemmatize
- 語尾処理による正規形への変換: stemming
- stemmer, lemmatizer in NLTK
>>> stemmer = nltk.stem.LancasterStemmer()
>>> stemmer.stem('guitars')
'guit'
>>> stemmer.stem('guitarist')
'guit'
>>> lemmatizer = nltk.stem.WordNetLemmatizer()
>>> lemmatizer.lemmatize('went')
'went'
>>> lemmatizer.lemmatize('went', pos='v')
'go'
>>> lemmatizer.lemmatize('children', pos='n')
'child'
- 単語 N グラム
- 確率の連鎖規則: $P(in,the,morning) = P(morning|in,the) P(the|in) P(in)$
- $P(a,b) = \frac{\#(a,b)}{\sum_{x,y \in V}\,\#(x,y)}$
- N グラム確率を用いた文の確率
- 仮定: 文中で、ある単語が生起することは、それより以前の単語系列の生起に依存する
- $P(s) = P(w_1,\cdots,w_m) = \prod_{i=1}^m P(w_i|w_0,w_1,\cdots,w_{i-1})$
- 考慮する以前の範囲を限定する
- この計算を N グラムによって近似する
- $P(w_i|w_0,w_1,\cdots,w_{i-1}) \approx P(w_i|w_{i-N+1,\cdots,w_{i-1}})$
- 言語モデル
- 統計的言語モデルとは文 (単語系列) の確率を計算する道具立て
- (あるいはこれと等価的に) ある単語系列を観測したときに、次に来る単語の確率を見積もる道具立て
- 但し: Noam Chomsky: It must be recognized that the notion "probability of a sentence" is an entirely useless one, under any known interpretation of this term.
>>> import nltk
>>> words = nltk.corpus.brown.words()
>>> len(words)
1161192
>>> bigrams = list(nltk.bigrams(words))
>>> len(bigrams)
1161191
>>> fd = nltk.FreqDist(bigrams)
>>> fd.most_common(n=20)
>>> def sentence_prob(s, fd):
... bigrams = nltk.bigrams(nltk.word_tolenize(s))
... s_p = 1.0
... for b in bigrams:
... s_p *= fd[b] / fd.N()
... return s_p
>>>
>>> sentense_prob('I have a dream', fd)
2.8001433373857277e-18
>>> sentense_prob('I have a big dream', fd)
0.0
- たまたま brown コーパスには "big dream" が存在していなかったが、このような現象は、どんなに大きなコーパスでも起こりうる → 確率の平滑化 (smoothing) が必要
- $P(w) = \frac{Count(w) + \alpha}{\sum Count(w) + \alpha}$
- etc.
- 品詞付与
>>> s = 'I bought a book written in English.'
>>> nltk.pos_tag(nltk.word_tokenize(s))
def vitabi(sentense):
tolens = nltk.word_tolenize(sentence)
tokens.insert(0, '<s>')
T = len(tokens)
S = len(pos_tags)
V = np.zeros((S, T), dtype=np.float32)
B = np.zeros((S, T), dtype=int) $ back-pointer table
for j in range(S):
V[j,0] = 1.0
B[j,0] = 0
for t in range(1, T):
for s in range(S):
max_prob = 0.0
max_ind = 0
for s_ in range(S):
prob = V[s_,t-1] * p_t_t(pos_tags[s_], pos_tags[s]) * p_t_w(pos_tags[s_], tolens[t])
if prob > max_prob:
max_prob = prob
max_ind = s_
V[s,t] = max_prob
B[s,t] = max_ind
max_prob = V[:,T-1].max()
last_pos_ind = V[:,T-1].argmax()
pos_seq = make_pos_seq(B, last_pos_ind, T-1)
return max_prob, list(zip(tokens[1:], pos_seq))
- 言語表現の意味
- 意味とは何か: ギリシャ哲学の昔から深い議論の歴史
- 自然言語処理で利用される基本的な考え方:
- 言語表現の意味はその構成要素の意味から決まる (構成性の原理)
- 単語の意味: どのような文脈で用いられるかによって規定できる (分布仮説)
- 分布仮説に基づく単語の意味表現
- 現在の主流: 単語にベクトルを割り当てる
- 単語ベクトル導出のアプローチ
- コーパスにおける共起関係を行列として表し、行列分解の手法を適用する (Count アプローチ)
- 文脈から単語を、単語から文脈を予測するような学習を行う (Predict アプローチ)
- ベクトル表現の利点
- ベクトル間の演算によって意味的 (非) 類似度や関連度が計量化できる
- 市街地距離 (L1)
- ユークリッド距離 (L2)
- コサイン類似度
- Word2Vec: Predict アプローチの代表例
- CBOW (Continuous bags of words): 文脈から現在の単語を予測
- Skip-gram: 現在の単語から文脈を予測
- v(Berlin) - v(Germany) + v(France) = Paris
- Word2Vec tool
- Word2Vec in gensim
>>> import gensim
>>> w2v_f= './GoogleNews-vectors-negative300.bin'
>>> w2v = gensim.models.KeyedVectors.load_word2vec_format(w2v_f, binary=True)
>>> w2v.similarity('cat', 'bike')
0.58541536
>>> w2v.similarity('car', 'train')
0.3402561
>>> w2v.most_similar('car', topn=5)
まとめ
- 単語の正規化や品詞付与などは、重要な要素技術として蓄積が図られてきた
- ベクトルによる単語の意味表現は、2013 年の Word2Vec や fastText による、通常的な手段となった (commodity 化)
- 文脈における意味を考慮するベクトル化
- 単語の系列である文や文章に対するベクトル化に関する研究が盛んに行われている (決定だはまだ)