Lesson11: Text Learning まとめ Intro to Machine learning@Udacity

#Lessonに入る前に
Udacityの[Intro to Machine learning](https://mena.udacity.com/course/intro-to-machine-learning--ud120)を受けはじめてしばらく経つが、学習しては忘れている気がするので、Lesson11からだけど、備忘録として記録に残していこうと思う。

少しでも、皆さんの参考になれば。

PCはWindows 10 64bit　最近SSDに換装した10年選手のノートパソコンです。
Anaconda5.2.0(Python3)入れました。

ただ、UdacityのIntro to Machine learningはPython2とのこと。
[ここ](http://tug-uca.hatenablog.com/entry/2016/11/22/131656)と[ここ](https://qiita.com/yunambu/items/fb6cb96a824c02a9f3d0)を参照させてもらって、Python3とPython2を共存させました。

#Lesson11:Text Learningのまとめ

##このレッスンの概要
課題：文章へ機械学習(Naive BayesやSVM)を適用する場合、入力の次元を統一できないため、学習が大変。
→入力したい各文章を集めて、次元の統一をしよう！が今回のレッスン。[Lesson2:Naive Bayes](https://qiita.com/Allovertom/items/11115145d4a3ff53d1e4)やLesson3:SVMで使っていたデータをどのように作っていたのか学ぶ。

前処理の流れは
Tokenize(文章を単語に分割)→Stemming(単語をrootに丸める)→TfIdf処理(情報量で重みづけ)


##処理の手順
###STEP1, Tokenize([NLTKのword_tokenize](https://www.nltk.org/api/nltk.tokenize.html)参照)
入力：文章
出力：各単語

文章をそれぞれの単語に分けること。ここではNLTK(Natural Language Took Kit)を使用。

```python

from nltk.tokenize import word_tokenize
s = '''Good muffins cost $3.88\nin New York.  Please buy me two of them.\n\nThanks.'''
word_tokenize(s)
['Good', 'muffins', 'cost', '$', '3.88', 'in', 'New', 'York', '.',
'Please', 'buy', 'me', 'two', 'of', 'them', '.', 'Thanks', '.']
```

###STEP2, Stemming(レッスンは[NLTKのSnowballstemmer使用](http://www.nltk.org/howto/stem.html))
入力：単語
出力：単語の根(root)
単語の根(root)例えばrespond, response, responsivelyはすべてresponの根(root)に変換される。　

###STEP3, TfIdf処理 = TfidfVectorizer
入力：単語(なるべく根を入力する。でないと同じ根の単語を別物としてカウントするので、出てくるMatrixが膨大になる＝後の機械学習で処理に時間かかる)
出力：単語の頻度の重みづけ

- Tf:Term Frequency：ほぼBag of Wordsと同じだが、内部表現が違う。Bag of Wordsは出現回数だが、Term Frequencyは出現**回数**ではなく**重みづけ(weight)**で表現されている。

- Idf **Inverse** Document Frequency：各単語の重みづけ。出現頻度が**低い**単語が情報量の**多い**単語として重みづけするため、**Inverse**となっていることには納得した。
言葉覚えやすくなるかも。

上記TfとIdfを整合性を取った形で、出力Matrixを作ってくれるのかなたぶん。

例)

```python

from sklearn.feature_extraction.text import TfidfVectorizer
corpus = [
...     'This is the first document.',
...     'This document is the second document.',
...     'And this is the third one.',
...     'Is this the first document?',
... ]
vectorizer = TfidfVectorizer()
X = vectorizer.fit_transform(corpus)
print(vectorizer.get_feature_names())
['and', 'document', 'first', 'is', 'one', 'second', 'the', 'third', 'this']
print(X.shape)
(4, 9)
print(X)
(0, 8)        0.38408524091481483
(0, 3)        0.38408524091481483
(0, 6)        0.38408524091481483
(0, 2)        0.5802858236844359
(0, 1)        0.46979138557992045
(1, 8)        0.281088674033753
(1, 3)        0.281088674033753
(1, 6)        0.281088674033753
(1, 1)        0.6876235979836938
(1, 5)        0.5386476208856763
(2, 8)        0.267103787642168
(2, 3)        0.267103787642168
(2, 6)        0.267103787642168
(2, 0)        0.511848512707169
(2, 7)        0.511848512707169
(2, 4)        0.511848512707169
(3, 8)        0.38408524091481483
(3, 3)        0.38408524091481483
(3, 6)        0.38408524091481483
(3, 2)        0.5802858236844359
(3, 1)        0.46979138557992045
```

[出展](https://scikit-learn.org/stable/modules/feature_extraction.html#text-feature-extraction)にprint(X)加えた。


###*参考1：Bag of Words = CountVectorizer*
入力：複数の文章
出力：複数文章内に出てくる単語が、それぞれ何回出てきたかをカウント(Matrix形式で)
→レッスンではBag of Wordsが先に解説される。おそらくTfIdfをわかりやすくするためだと思われる。

###*参考2：Stop Words*
例えばand, the, I, you, have
頻繁に出てくるが、情報量はかなり低いため除外する。[Vectorizer(TfidfVectorizer)の引数で除外するかどうか指定できる。](https://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.TfidfVectorizer.html#sklearn.feature_extraction.text.TfidfVectorizer)
下記英語のStopWordsを除外する場合。

```python

from sklearn.feature_extraction.text import TfidfVectorizer
vectorizer = TfidfVectorizer(stop_words='english')
X = vectorizer.fit_transform(word_data)
```

#感想
時間をかけてレッスンをやっていると、最初のビデオで見たことを忘れてしまい、最後は何やってるんだかわかんなくなってしまった。一つ一つ身になるようにするには、時間がかかるけど、こうやってまとめるのが一番の近道のような気がする。

個人的には上記のような処理は人間が言葉を使うときのプロセスとは大分違うかなと感じた。
例えば、Stemmerで微妙なニュアンスをまとめてしまうのは違和感がある。
そのような必要が本当にないのなら、Stemmerでまとめた単語の根だけで人間が会話してもいい気がするが。これからの言語の進化はその方向に行くのだろうか。もしくは、計算機の性能が上がって、Stemしなくてもよくなれば、コンピューターがもっと自然な感じで会話できるようになるのかな。
機械に人間が近づくのか、人間に機械が近づくのか。。。

英語、フランス語、スペイン語とかのラテン語系は根でまとめられるかもだけど、
ヒンディー語、タイ語とかのサンスクリット語系はまた全然違うんだろうね。
日本語は根がありそうだ。