秋元康に「恋」とは何かを聞いてみた


P&Dアドベントカレンダー21日目の記事です。もうすぐクリスマスですね:santa:
クリスマスプレゼントは最近iPhone6sが頻繁に強制終了をするので新しいiPhoneが欲しいです:santa:
##　はじめに
いきなりですが、**恋**していますか？
Wikipediaには、
>恋（こい）とは、特定の相手のことを好きだと感じ、大切に思ったり、一緒にいたいと思う感情。

とは書いてありますが、**「恋」とは何なのか**がよく分からなかったので、恋愛ソングを数多く書いている秋元康先生に聞いてみる事にしました。

## どうやって聞くのか

さすがに、直接秋元康先生に尋ねる事はできないので、先生が執筆された**歌詞**を使って
「恋」と類似度が高い言葉は何かを解析して求めることにしました。

## 使う技術
- Python 3.6.5
-  スクレイピング(BeautifulSoup)
-  MeCab（形態素解析）
-  Word2Vec(単語をベクトル化)

##　方法

### 1.歌詞データ収集

歌詞検索サービス[Uta-net](https://www.uta-net.com/)から歌詞を取得しテキストファイルに保存するPythonのスクリプトを作成しました。
https://github.com/KohheiAdachi/getWordofSong/blob/master/getSong.py
このスクリプトを使用し、Uta-netで各アーティストをキーワード検索した時に出てきた曲をテキストファイルに保存しました。

```python:歌詞取得
from getWordofSong import getSong as gt
import os

song = gt.GetSong()
# ディレクトリ作成
Input_dirTitle = input("dirTitle:")
make_dir = "kashi/"+Input_dirTitle
os.mkdir(make_dir)
# 歌詞サイトのURL入力(検索ページ）
Input_url = input("urlを入力:")
print(Input_url)
# 歌詞ページのURL取得
kashiList = song.getSongList(str(Input_url),match="search")
for kashi in kashiList:
    title,data = song.getWordofsong(kashi)
    print(title)
    song.save_kashi(title,data,make_dir)
```

|アーティスト  |曲数  |
|---|---|
|AKB48  |609  |
|SKE48  |230  |
|NMB48  |187
|HKT48  |78 |
|NGT48  |28 |
|STU48  |17|
|乃木坂46 |183 |
|欅坂46 | 81|

合計1413曲分の歌詞を収集しました。

### 2.データの前処理
歌詞には英語も含まれており、英数字、記号を正規表現で削除し、日本語のみの歌詞にし、解析結果に影響が出ないようにします。

```python:歌詞データの読み込む関数
def read_doc(directory):
    text = ""
    for path in directory:
        with open(path,'r',errors='ignore') as f:
            text += f.read()
    return text
```
```python:ファイルパスを取得後、歌詞を読み込み英数字、記号を正規表現で削除
from glob import glob
# ファイルパスを取得
filePathList = glob.glob("kashi/*/*")
# すべての歌詞を１つの文字列にする
kashi = read_doc(filePathList)

# 英数字の削除
kashi = re.sub("[a-xA-Z0-9_]","",kashi)
# 記号の削除
kashi = re.sub("[!-/:-@[-`{-~]","",kashi)
```

###3.形態素解析

MeCabを使用し取得した歌詞に対して形態素解析を行い、解析に使用する単語である名詞、動詞、形容詞、形容動詞を取り出し、動詞、形容詞、形容動詞に対しては基本形に直しました。
また、ストップワードを設定し、関係なさそうな単語は除きました。

```Python:形態素解析
def split_into_words(doc):
    mecab = MeCab.Tagger("-Ochasen")
    lines = mecab.parse(doc).splitlines()
    words = []
    stop_word = create_stop_word()
    for line in lines:
        chunks = line.split('\t')
        if len(chunks) > 3 and not chunks[2] in stop_word:
            if chunks[3].startswith('動詞'):
                words.append(chunks[2])
            if chunks[3].startswith('名詞') and not chunks[0] in stop_word:
                words.append(chunks[0])
            if chunks[3].startswith('形容詞'):
                words.append(chunks[2])
            if chunks[3].startswith('形容動詞'):
                words.append(chunks[2])    
    return words
```
```python:ストップワードリスト生成
def create_stop_word():
    target_url = 'http://svn.sourceforge.jp/svnroot/slothlib/CSharp/Version1/SlothLib/NLP/Filter/StopWord/word/Japanese.txt'
    r =requests.get(target_url)
    soup=BeautifulSoup(r.text, "html.parser")
    stop_word=str(soup).split()
    return stop_word
```
### 4.Word2vecで学習
Word2Vecで学習させ各単語をベクトル化させました。

```python:Word2Vecdで学習
from gensim.models import word2vec

def learnig_word2vec(kashi)
    sentence = [kashi]
    model = word2vec.Word2Vec(sentence, size=200, min_count=4, window=5, iter=40)
    # モデルを保存
    model.save("AkimotoYasushi.model")
```

### 5.類似度の計算

学習したモデルに対して、「恋」という単語に対して類似度の高い上位１０個の単語を出力します。

```python:類似度の計算
# モデルの読み込み
model = gensim.models.Word2Vec.load('AkimotoYasushi.model')
word = model.wv.most_similar(positive=[u"恋"], topn=10)
# 結果を出力
for i, lv in enumerate(word):
    print(str(i) + "    " + lv[0] + "    " + str(lv[1]))
```

### 結果
「恋」という単語に対して類似度の高かった単語を出力した結果を以下に示します。

```:結果
0    証拠    0.9997125864028931
1    浮気    0.999591588973999
2    ぃ    0.9995723962783813
3    縄    0.9995304346084595
4    キス    0.9995051622390747
5    頂戴    0.9995023012161255
6    傾向    0.9994885325431824
7    せる    0.9994684457778931
8    喧嘩    0.9994481801986694
9    起きる    0.999412477016449
```
**証拠？？
浮気？？
縄（意味深）！！？？
キス:kiss:！！？？**

**結果がいろいろと辛いので**、さらにストップワードを追加したいと思います。

```python:追加でストップワードを追加
my_stop_word = ["角","無理","予約","ボウリング","立ち読み","ファッション","雑誌","糖","缶","ただ","すぎ","縄","発","偏差","ぃ","せる","頂戴","浮気","くる","びっくり","いじめ","しまう","くん","ふう","ちょうだい","コーヒー"]
# ストップワード追加
stop_word.extend(my_stop_word)
```

```:ストップワードを追加した結果
0    キス    0.9993709325790405
1    弱い    0.9993308186531067
2    存在    0.9993278384208679
3    負け    0.9993095397949219
4    生物    0.9992963075637817
5    起きる    0.9992321133613586
6    傾向    0.9991904497146606
7    克服    0.9991508722305298
8    逆転    0.9991446137428284
9    喧嘩    0.9991180300712585
```
恋とは、**キスに弱くて、存在に負けて？、生物的で、起きる傾向があって?、克服して、逆転して、喧嘩するものなんですね！（適当）**

### グループごとで再計算してみた
学習する歌詞を各グループごとに絞って再びWord2Vecで学習させ、「恋」と類似度の高い単語を再計算させました。

#### AKB48にとって**「恋」**とは

```:AKB48にとって「恋」とは
0    美学    0.9974193572998047
1    理由    0.9970353245735168
2    閉じる    0.99690842628479
3    恋人    0.996814489364624
4    事件    0.9967169761657715
5    恥ずかしい    0.9966646432876587
6    舐める    0.9965479969978333
7    とこ    0.9963464140892029
8    わかる    0.996084451675415
9    奥    0.9960130453109741
```
#### 乃木坂46にとって**「恋」**とは

```:乃木坂46にとって「恋」とは
0    意外    0.9484642148017883
1    告白    0.948411226272583
2    ハート    0.9470661282539368
3    キス    0.9470518827438354
4    ひらく    0.9429705142974854
5    絶対    0.9425839781761169
6    秘密    0.9415342807769775
7    大人    0.9398925304412842
8    許す    0.9393779635429382
9    磨く    0.9379326701164246
```
#### 欅坂46にとっての**「恋」**とは

```:欅坂46にとって「恋」とは
0    輝く    0.9968976974487305
1    ときめき    0.9954394102096558
2    奥    0.9930803775787354
3    大切    0.9909152388572693
4    過ごす    0.9906127452850342
5    日常    0.9903433918952942
6    昨日    0.9902833700180054
7    感じる    0.9896537661552429
8    思い出    0.9886585474014282
9    教える    0.9869102239608765
```

AKB48は美学
乃木坂46は意外
欅坂46は輝く
でした。
※それぞれに対して、ストップワード変更してます。

#### 西野カナ先生にも聞いてみた


```:西野カナにとって「恋」とは
0    知る    0.9580930471420288
1    追いかける    0.9487483501434326
2    出会える    0.9459880590438843
3    失う    0.9414538145065308
4    向く    0.9401863813400269
5    言い聞かせる    0.9368431568145752
6    傷つく    0.9362004995346069
7    押す    0.9356939196586609
8    不思議    0.934490442276001
9    無理    0.9331055879592896
```


## まとめ

- ストップワードをうまく設定しないと意味深な結果となってしまう。
- 秋元康の歌詞のエキスパートくらいの知識がないと結果に対して考察が難しい。
- 西野カナ先生に聞いたほうが良い結果が得られた。

## 最後に
結局「恋」とはなんだろうか...
ソースコードは[GitHub](https://github.com/KohheiAdachi/Kashi-word2vec)にまとめてあります。

##　参考文献

西野カナに「恋」とは何か聞いてみた
https://blog.aidemy.net/entry/2018/06/15/174827