ゼロから作るDeep Learning 自然言語処理編を理解する Chap2

# 概要
本記事では，[ゼロから作るDeep Learning 自然言語処理編](https://www.oreilly.co.jp/books/9784873118369/)を理解することを目指し，その箇所の引用・自分なりに大事だなと思ったこと・感想などをまとめていきます．(知識不足な所も多々ありますが，温かい目で見守って頂ければと思います)

これまでとこの先の記事はこちらから
[1章：ニューラルネットワークの復習](https://qiita.com/peartrees/items/f5379e7889b3875d1627)
[3章：word2vec](https://qiita.com/peartrees/items/c75e67d19e5507005f07)


本記事では，書籍の２章(自然言語と単語の分散表現)を扱います．



# Chap2 - 自然言語と単語の分散表現(pp.57-92)
本章では以下を理解することがGoalになります．

- 自然言語処理の目指すもの
- 自然言語処理の古典的手法



## 2.1 自然言語処理とは
この節では，自然言語処理とは何か，自然言語処理を通じて得られるものは何かを扱っています．

### ・ 単語に注目する意義
> 私たちの言葉の意味は，「単語」によって構成されます．単語は，言ってみれば，意味の最小単位です． (from p59)

単語の意味を正確に捉えることができれば，言語を理解できたと考えられます．
自然言語処理では，コンピューターによる言語の意味理解を目標としているため，単語の意味に注目するのは自然な流れと言えますね．
次節以降では，単語の意味を理解する手法として代表的なものを扱っていきます．

<br>

## 2.2 シソーラス
この節では，シソーラスのアイデアを理解することがGoalになります．

### ・ シソーラス
> シソーラスとは，類語辞書であり，「同じ意味の単語」や「意味の似た単語」が同じグループに分類されています．例えば，carの同義語には，automobileやmotorcarなどが存在することがシソーラスを使えば分かります． (from p60)

シソーラスとは，単語の関連性を**人間が1語ずつ定義**して得られた辞書であり，語を定性的に扱えるようにしたものです．
人間が1語ずつ定義するという点で正確性は◎ですが，数十万とある語を一々定義していたのでは限界があり，微妙なニュアンスの違いなどを定義できないといった問題が多くあります．

そうした問題に対処する為に，次節以降の手法が登場してきます．

<br>

## 2.3 カウントベースの手法 
この節では，カウントベースの手法の動機と目的を理解することがGoalになります．

### ・ コーパスとは？
> コーパスとは，簡単に言ってしまえば，大量のテキストデータです． (from p63)

前節で扱ったシソーラスの方法では，単語1つ1つに注目して意味理解を目指しましたが，人間が1つ1つに定義づけを行うのには限界があります．

そこで，カウントベースの手法では，**コーパス**に注目して意味理解を目指します．
コーパスとは私たちが実際に書いている，または読んでいる文章(Wikipediaや，新聞，Twitterなど)で大量に存在し，今この瞬間にも膨大な量のデータが生み出されています．

こうした膨大なデータに注目し，効率的に，またシステマティックに単語の意味理解をしようという考えがカウントベースの手法になります．

### ・ 単語の分散表現
> 「色」のベクトル表現（RGBの成分表示）のようなことを「単語」でも行えないでしょうか？

ベクトルで表すことができれば，ある語を**定量的に**評価できたり，ベクトルの**加減算**で別の単語の意味を類推できたりと，メリットが沢山あります．
単語をベクトルで表すことを**単語の分散表現**と言います．

そうは言っても，どうやって単語をベクトルにするの？？
と思った方は勘が鋭く，分散表現をどのようにして獲得するのかは，今後の重要なテーマになってきます．

ちなみに，分散表現の獲得手法は大きく**カウントベース**と**推論ベース**の２種類に大別することができ，本章では前者を扱っています．

### ・ 分布仮説
> 単語をベクトルで表す研究は数多く行われて来ました．（中略）重要な手法のほとんど全てが，あるひとつのシンプルなアイデアに基づいていることが分かります．そのアイデアとは，「単語の意味はその周辺の語によって形成される」というものです．

「単語の意味は似たようなコンテクスト（文脈）においては，似たような意味になる」という考えのことを**分布仮説**と呼びます．
「ある単語の意味はAである」と定義するのではなく，単語が登場する**前後の文脈**を見て意味を考えるというのは尤もらしいと思えます．


### ・ 共起行列
> 分布仮説に基づいて，単語をベクトルで表す方法を考えましょう．そのための素直な方法は，周囲の単語を"カウント"することです．

ある単語 *w* に着目した時，*w* の前後のにどのような単語がどれだけ出現するのかをカウントしたものを**共起行列**と言います．
以下のようなSentenceを通じて考えてみましょう．

Sentence : I drink beer.

単語「I」の前後には，「drink」があります．
そのため，単語「I」に対して，共起する単語の頻度は，


| |I  |drink  |beer  |. |
|---|---|---|---|---|
|I |0  |1  |0  |0  |

となります．これは単語「I」を [0, 1, 0, 0] というベクトルで表したことになります．
ちなみに，上ベクトルのように単語の出現の有無で表したものを**One-Hotベクトル**と言います．
この作業を全ての語に対して行うと，以下のようなテーブルが得られます．

| |I  |drink  |beer  |. |
|---|---|---|---|---|
|I |0  |1  |0  |0  |
|drink |1  |0  |1  |0  |
|beer |0  |1  |0  |1  |
|. |0  |0  |1  |0  |

このテーブルのことを**共起行列**と呼び，単語を**カウントベース**でベクトル化したことになります．
「drink」の前後には，飲み物が現れそうという直感にも則しており良さそうです．


### ・ コサイン類似度
> ベクトル間の類似度を計測するには，さまざまな方法が考えられます．例えば，ベクトルの内積やユークリッド距離などが代表例として挙げられます．（中略）単語のベクトル表現の類似度に関しては，**コサイン類似度**がよく用いられます．

共起行列によって単語のベクトル表現が可能になり，ある単語同士がどれだけ似ているのか，という類似度評価を行うことが可能になりました．単語における類似度評価にはよくコサイン類似度が用いられます．以下が定義になります．
<br>

```math
similarity(x, y) = \frac{x\,y}{||x||\,||y||} = \frac{x_1y_1 + x_2y_2 + \cdots + x_ny_n}{\sqrt{x_1^2\cdots+x_n^2}\sqrt{y_1^2\cdots+y_n^2}}
```


ポイントは**正規化**されている点です．
これにより2つのベクトルの大きさを無視して，どれだけ同じ向きを向いているのかを測定することが可能になっています．


<br>
## 2.4 カウントベースの手法の改善
単語の共起行列をもとに単語をベクトルで表すことに成功しましたが，それが最善な手法とは言えません．
なぜなら，単語同士の共起した回数**「だけ」**を考えている為です．
回数をカウントしただけでは，真に単語の関係性・意味を取得できるとは限りません．

1つの例として，「an」と「apple」を考えます．
「・・・an apple・・・」というフレーズは多く見られるでしょう．
その為，先の共起行列ではanとappleの共起回数は大きなものになります．

一方で，「eat」と「apple」の間には明らかに大きな関連があると言えますが，共起の回数で言うと「eat」は「an」に負けてしまうでしょう（anは高い頻度で出現する単語の為）．

このように，頻度だけで考えるのには問題がある為，語の出現回数を考慮したベターなカウントベース手法について理解することがGoalになります．

### ・ 相互情報量
> そのような問題（※）を解決するために，**相互情報量**(Pointwise Mutual Information)と呼ばれる指標が使われます． (※高頻度単語が強い関連を持つように評価されること)

相互情報量は以下のように定義されます．

```math
PMI(x, y) = log_2{\frac{P(x,y)}{P(x)P(y)}}
```
P(x) は x が起こる確率，P(y) は y が起こる確率，P(x,y) は x, yが同時に起こる確率です．
大雑把な理解としては，x，y が単体で多く出現する場合（先の例で表すと「an」のような語）は，共起回数が多くても情報量は小さくなります．
相互情報量のお陰で，2語の持つ「関連」を定量的に評価することができるようになります．

### ・ 次元削減
> **次元削減**は文字通り，ベクトルの次元を削減する手法を指します．単に削減するのではなく，”重要な情報”をできるだけ残した上で削減するという点がポイントです．

これまで扱ってきた共起行列はコーパスに登場する語彙の分だけ次元数が大きくなるという特徴があります．
「次元の呪い」と言うだけあって，次元数は大きくなりすぎないのに越したことはありません．

そこで登場するのが，**元の行列から重要な情報・意味を残したまま**，より低次元で表現し直す次元削減の考え方になります．

### ・ 特異値分解
> 特異値分解（Singular Value Decomposition:SVD）は，任意の行列を3つの行列の積へと分解します．

SVDを数式で書くと，以下のようになります．

```math
X = USV^T
```
Xは任意の行列，U，Vは直交行列であり，Sは対角行列になります．

SVDについては[分解すると見える世界 ー特異値分解ー](https://thinkit.co.jp/article/16884)が非常に分かりやすく，参考になります．

SVDを行うと，高次元の行列を低ランク近似することができるだけでなく，重要度(特異値)を取得できるという点で，非常に重要な考えになります．

<br>

## 2.5 まとめ
本章では，自然言語処理の歩みと古典的手法，単語の分散表現について扱いました．

コンピューターに私たちの言語の意味理解をさせたいというのが，自然言語処理のモチベーションであり，次のようなアプローチが確立されてきました．

- シソーラス（類語辞書）による手法
    - 人の手によって定義する

- カウントベースの手法
    - コーパスから，統計的に意味を抽出する

- 推論ベースの手法(次回)
    - Word2Vecなど

---

# Chap2のまとめと所感
本章を通じて，自然言語処理の最も初歩的な部分を学ぶことができました．
コンピューターに自然言語を理解させることがいかに難しいのか，単語から意味を取り出す古典的な手法にどういったものがあるのか，その問題点は何か，といった話題に触れたことで，今後の推論ベースの手法の理解が深まると感じました．

それでは，次章Chapter3でお会いしましょう👋