あいみょんに「恋」とは何か聞いてみた

# あいみょんに「恋」とは何か聞いてみた

こんにちは。
みんな大好きあいみょん様に質問してみたいことはたくさんあると思います。

あいみょんは全て歌詞を自分で書いているので歌詞の中からあいみょんが考えていること分析できるのでは、、
ということで歌詞を分析して考えていることを聞いてみましょう！！

# はじめに
現在はwebの開発をメインに行なっているのですが、大学時代は機械学習を触る機会が多かったので久々に触ってみたいと思いこちらの記事を作成しました。音楽が好きなので歌詞分析をしてみようと思いこちらのブログにしました。

# 開発環境
Google Colaboratory

# スクレイピング
歌詞のデータを持ってくるためUta-Netから歌詞データを持ってきます。
BeautifulSoupというライブラリを使用することで容易にスクレイピングをすることができます。
データフレームを作成し、スクレイピングするWEBページを指定します。

`requests.get`を使って歌詞一覧ページのHTMLを取得し、`BeautifulSoup`で解析しています。
下記のコードで歌詞のデータをcsvファイルに書き込むことができます。

```python
#ライブラリインポート
import requests
from bs4 import BeautifulSoup
import pandas as pd
from datetime import datetime
import datetime
import time
import re

#取得したデータを格納するデータフレームを作成
Aimyon_songs_df = pd.DataFrame(columns=['song_name','lyrics','release_date','impression'])

#Uta-Net先頭URL
base_url = 'https://www.uta-net.com'
#あいみょんの歌詞一覧ページURL
url = 'https://www.uta-net.com/artist/17598/'

#歌詞一覧ページのHTML取得
response = requests.get(url)
soup = BeautifulSoup(response.text, 'lxml')
links = soup.find_all('td', class_='sp-w-100 pt-0 pt-lg-2')
#歌詞ページより、情報を取得
for link in linkｓ:
  a = base_url + (link.a.get('href'))

  #歌詞ページよりHTMLを取得
  response_a = requests.get(a)
  soup_a = BeautifulSoup(response_a.text, 'lxml')
  #曲名取得
  song_name = soup_a.find('h2').text
  #歌詞取得
  song_lyric = soup_a.find('div', itemprop='lyrics').text.replace('\n','')
  #発売日取得
  detail = soup_a.find('p', class_='detail').text
  match = re.search(r'\d{4}/\d{2}/\d{2}', detail)
  release_date = datetime.datetime.strptime(match.group(), '%Y/%m/%d').date()
  #表示回数を取得
  p = r'この曲の表示回数：(.*)回'
  impression = re.search(p, detail).group(1)

  #取得したデータフレームに追加
  temp_df = pd.DataFrame([[song_name],[song_lyric],[release_date],[impression]], index=Aimyon_songs_df.columns).T
  Aimyon_songs_df = Aimyon_songs_df.append(temp_df, ignore_index=True)
  #2秒待機
  time.sleep(2)

#csv出力
Aimyon_songs_df.to_csv('aimyon_songs_df.csv', mode='w')
```

# データの前処理
次にデータを整えます。
発売日などのデータも取ってきましたが、今回使用するのは歌詞のデータだけで大丈夫なのでtxtファイルに結合して格納します。
歌詞だけ持ってこなかったのは、こんなこともできるよーみたいな意味です。

```python
import pandas as pd

# CSVファイルのパス
csv_file_path = 'aimyon_songs_df.csv'  # ファイルパスを適切に変更してください

# CSVファイルを読み込む
df = pd.read_csv(csv_file_path)

# "lyrics"列のデータをリストとして抽出
lyrics_list = df['lyrics'].tolist()

# リスト内の文字列を結合して1つの文字列にする
combined_lyrics = '\n'.join(lyrics_list)

# 書き出すTXTファイルのパス
txt_file_path = 'aimyon.txt'  # ファイルパスを適切に変更してください

# TXTファイルに結合した文字列を書き出す
with open(txt_file_path, 'w', encoding='utf-8') as txt_file:
    txt_file.write(combined_lyrics)

print(f'結合されたテキストが {txt_file_path} に書き出されました。')
```

### 形態素解析
次に歌詞データから余分なデータを削除します。
今回は`janome`を使用して形態素解析を行います。
形態素解析とは日本語を最小単位に分割し、品詞ごとに分けることができるものです。
今回の分析では名詞、動詞、形容詞、形容動詞を抽出します。

```python
# 品詞を取り出し「名詞、動詞、形容詞、形容動詞」のリスト作成
def tokenize(text):
    t = Tokenizer()
    tokens = t.tokenize(text)
    word = []
    stop_word = create_stop_word()
    for token in tokens:
        part_of_speech = token.part_of_speech.split(",")[0]
        if part_of_speech == "名詞":
            if not token.surface in stop_word:
                word.append(token.surface)
        if part_of_speech == "動詞":
            if not token.base_form in stop_word:
                word.append(token.base_form)
        if part_of_speech == "形容詞":
            if not token.base_form in stop_word:
                word.append(token.base_form)
        if part_of_speech == "形容動詞":
            if not token.base_form in stop_word:
                word.append(token.base_form)
```

### ストップワード
他に関連しないワードを省くためにストップワードを設定します。
いくつか自分で追加しましたが、ストップワードがまとまっているものを使用して多くは除きました。

```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()
    #自分で追加
    my_stop_word=['いる','する','させる','の', 'られる']
    stop_word.extend(my_stop_word)
    return stop_word
```

# word2vec
word2vecは、大量のテキストデータを解析して各単語の意味をベクトル表現かする手法です。
代表的な例では「王様」 – 「男」+ 「女」 = 「女王」のような単語同士の類似度を計算することができます。
今回は歌詞データを学習させます。

```python
model = word2vec.Word2Vec(sentence, vector_size=200, min_count=4, window=4, epochs=50)
```

|sentence|歌詞データ|
|:-:|:-:|
|vector_size|ベクトルの次元数|
|min_count|n回未満の単語を除く|
|window|学習に使う前後の単語数|
|epochs|学習回数|

学習したモデルに対して関連するワードを以下のようにして調べることができます。
```python
model.wv.most_similar(positive=[u"恋"], topn=20)
```

それでは実際に聞いてみた結果です！

1. 裸: 0.93286
2. 馬鹿: 0.91306
3. 思う: 0.91275
4. 早い: 0.90879 
5. 階: 0.90682
6. 不幸: 0.90582
7. 隣: 0.90560
8. 魅力: 0.90357
9. 離す: 0.90065
10. 開く: 0.90036


あいみょんらしい結果ではありますが、少しネガティブなワードが多めでしたね！
また結果に大きく差がなかったのは学習量かなと思います。
より多くの歌詞データがあればより高い精度で分析することができそうです。

# 最後に
ぜひ皆さんも好きなアーティストに聞きたいことを分析してみましょ〜！

# おまけ
「愛」についても聞いてみました。「恋」よりポジティブな結果で嬉しいです！

1. おしい: 0.98239
2. 夢: 0.94402
3. お母さん: 0.92433
4. ゆく: 0.92347
5. 想像: 0.91597
6. ナンマイダナンマイダ: 0.91236
7. つく: 0.91022
8. 眠る: 0.90695
9. 眠れる: 0.90656
10. 唱える: 0.88986