自然言語処理入門 まとめ【Python + Janome + gensim】

## 対象
初学者を対象に書いてます。自然言語処理の理解の手助けになれば幸いです
何か間違いあったらご指摘お願いします

---
勉強会に行ってその内容を自分なりにまとめたのでおかしい部分あるかもです

自然言語処理の基本となる`形態素解析`から、実務で用いやすい`tf-idf`や`Word2Vec`までの仕組みの説明と実際にサンプルコードを用いたハンズオンを行いました。

少々高校数学の知識が必要ですが、全体的に理解しやすく簡単にハンズオンまで行けたので非常に実用性が高いと思いました。

# **自然言語概論**

機械がどういう風に処理をすれば人間の言葉を理解できるか？的な内容です。
（知っている人も多いと思いますが）

以下キーワード

- 形態素解析
- ベクトル空間法
- tf-idf
- Word2Vec


## **形態素解析**

検索エンジンにも用いられている自然言語処理の手法の一つ
ある文章を「意味を持つ最小限の単位（＝単語）」に分解し、文章の内容を判断するために使います

例） 「東京都に住む 」 を分解

![Keitasokaiseki.png](https://qiita-image-store.s3.amazonaws.com/0/118385/202c2acf-cae5-9040-2f22-b558ff9d0880.png)

出典
http://techlife.cookpad.com/entry/2016/05/11/170000

単語同士の多くの組み合わせの中から、文章として最も確からしいと思われる単語の並びを探し出します

### **なんで分解するの...?**
「日本語は文節を判断するのが難しい」ので`正しい意味の文`にするのが一筋縄ではいかないから

英語の文は単語の間にスペースが有るので文節の判断がしやすい。
もともと英語文の解析に使っていたものを応用したらしいです。

### **分解してどうするの...?**

分解して解析すると数値が算出されます。
そのうちの小さいパスを繋いでいくと正しい意味に近くなるのだそう。

![0b86533e-19d7-4edb-8116-ac11d2623f16-1920x651r.png](https://qiita-image-store.s3.amazonaws.com/0/118385/e9b32ddd-fe97-c862-3758-f6c08db20a45.png)



赤枠の`連接コスト`を繋いでいく
数値の解析は「最小コスト法」を用いている

### **形態素解析のツール**
日本語の形態素解析では「`mecab`」が有名（実務でもよく使われる）

今回使う「`janome`」は「`mecab`」の辞書を使っているので基本的な部分は同じとのこと。

`janome`の方が比較的扱いやすいので
`janome`で検証、`mecab`つかって実用化が一般的。（janome → mecabの移行も簡単）

## **ベクトル空間法   BoW ( Bag of Words )**

単語 →　行列化

単語のままだと扱いづらいので、数値化するために使う
（詳しくは、文章などをベクトル化して類似度などを算出するために使う）

![20090213aikawa3.jpg](https://qiita-image-store.s3.amazonaws.com/0/118385/47f43ad7-c97a-81c9-3648-eb2a66ee0b0a.jpeg)

出典
http://www.teu.ac.jp/interesting/013496.html

```math

さわやか・・・
\begin{pmatrix}
2  \\
4  \\
0
\end{pmatrix}
蒸し暑い・・・
\begin{pmatrix}
0  \\
4  \\
3
\end{pmatrix}
 今日の天気・・・
\begin{pmatrix}
1  \\
4  \\
2
\end{pmatrix}


```

※一応数学の行列です
ベクトルに直したら向きや角度などを計算してカテゴライズできる
これを一行の文章丸々単語ごとに解析する

実は疎行列（0ばっかの行列）になるので効率悪い...
後で出てくるWord2Vecで解決する

## **tf-idf  ( Term Frequency - Inverse Document Frequency)**

文書中に含まれる単語の重要度を評価する手法の1つ

簡単にポイント
- 1文の中の単語の出現回数を数える
- ある単語の出現回数と１文の総単語数で割合出す

を計算すると、文章の中で特徴的な単語を見つけることができる。
文章全体で登場回数が少ない単語は、よりその文書を特徴付けるものだとして取り扱われる

TF:  単語が文で何回出てきたか
IDF: log{ (全体の文書数 + 1) / (ある単語の含まれる数 + 1) }

今回の勉強会では、tf-idf と ベクトル空間法に関しては「scikit-learn」のツールをそれぞれ使用した

## **Word2Vec**

ベクトル空間法の欠点を解決する考え方

ある単語に意味を持たせて足し算引き算できるようにして、似ている単語をだしやすくしたりする考え方。

### **わかりづらいと思うので例**

イチロー、プログラマー、パリ、道頓堀、打つ」という５単語をワードセット

![one-hot_vector.jpg](https://qiita-image-store.s3.amazonaws.com/0/118385/ffb29b61-2044-4f3e-b3b7-d46d5e4ef8bd.jpeg)


これだけではよくわからないので
単語に意味をもたせる

![distributed_representation.jpg](https://qiita-image-store.s3.amazonaws.com/0/118385/2d06e19c-6995-2ec2-f63b-e0067b09d075.jpeg)


怠惰さ・スポーツ・土地などの属性を 100 ~ 300 つけることでかなり高い精度を出せるようになる

#### 「分散表現」と言われる

### **精度上げてどうすんの...?**

**単語が意味を持っているので演算処理できるようになります**

- `王様` - `男` + `女` = `女王`
- `パリ` - `フランス` + `日本` = `東京`

的な事ができちゃいます。
ベクトルになってるので
### ベクトルで表現すると

![vector_semantics.jpg](https://qiita-image-store.s3.amazonaws.com/0/118385/8fd18300-e2b9-60de-8166-6b371bfa840e.jpeg)


違う単語を同じ方向に変換しても意味がすれ違うことがなくなる
機械が人間と同じような理解をすることが可能になる

#### tf-idf と合わせればある単語の次に来る単語の確率がわかる

今回の勉強会では`gensim`を使用した

> 引用
> https://deepage.net/bigdata/machine_learning/2016/09/02/word2vec_power_of_word_vector.html

## **自然言語処理の流れまとめ**

### 1. **ある文章を意味を崩さないように単語に分解する** `形態素解析`
使用ツール: `mecab` or `janome`
### 2. **分解した単語をベクトルへ変換** `ベクトル空間法`
使用ツール: `scikit-learn [ CountVectorizer ]`
### 3. **文章の特徴をつかむ** `tf-idf`
使用ツール: `scikit-learn [ TfidfTransformer ]`
### 4. **Word2Vecをつかって単語と単語を関係づける** `Word2Vec`
使用ツール: `gensim [ word2vec ]`

## **【考察】チャットボット（仮）で考えてみる**
上記の流れからチャットボット（音声インターフェースかもしれない）にこんな感じで使えるのではと考えた

#### **会話データを形態素解析**
↓
#### **ベクトル空間法・tf-idfを使って会話の特徴からパーソナル解析**
会話をもとにどんな人で、どんなことを必要としてるかなどなど
↓
#### **Word2Vecと機械学習を使ってその人にあった会話を行う（自動会話的な）**
ちょっとずれてるかもしれません...

もう既にありますが、かなり音声会話の仕組みについて理解できたと思います！

なんか意見ありましたらコメント下さいー