4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

日向坂46の歌詞をベクトル化してみた!

Last updated at Posted at 2020-10-17

0:やりたいこと

日向坂46の全曲の歌詞データを元にword2vecを用いて、
自然言語⇒数値
に変換して遊んでみたいと思います。

Word2vecとは?

単語をベクトルに変換する魔法

image.png

単語がどのようにベクトルに変化するか?
image.png

入力単語の周辺の単語(今回は距離1とする)を教師データとすることで、重みW,W"を計算する。
計算された重みWがそれぞれの単語のベクトルを表す。

自然言語処理の流れ

自然言語処理の流れ

1:データの収集

解決したいタスクに応じてデータを収集する

2:クリーニング処理

HTMLのタグなど意味を持たないノイズを削除する
Beautiful Soup
標準ライブラリ re モジュール

1,2:データの収集&クリーニング処理

#1.スクレイピング
import requests
from bs4 import BeautifulSoup
import warnings
warnings.filterwarnings('ignore')
target_url = "https://www.uta-net.com/search/?Aselect=1&Keyword=%E6%97%A5%E5%90%91%E5%9D%82&Bselect=3&x=0&y=0"
r = requests.get(target_url)
soup = BeautifulSoup(r.text,"html.parser")
music_list = soup.find_all('td', class_='side td1')
url_list = [] #曲一覧から各曲名のURLを取り出してリストに入れる
for elem in music_list:
    a = elem.find("a")
    b = a.attrs['href']
    url_list.append(b)

#<td class="side td1">
#    <a href="/song/291307/">アザトカワイイ</a>
#</td>  
#<td class="side td1">
#    <a href="/song/250797/">居心地悪く、大人になった</a>
#</td>  
自然言語処理の流れ
hinataza_kashi = "" #曲ごとにRequrestを送り歌詞を抽出する
base_url = "https://www.uta-net.com"
for i in range(len(url_list)):
    target_url = base_url + url_list[i]
    r = requests.get(target_url)
    soup = BeautifulSoup(r.text,"html.parser")
    div_list = soup.find_all("div", id = "kashi_area")

    for i in div_list:
        tmp = i.text
        hinatazaka_kashi += tmp

#<div id="kashi_area" itemprop="text">
#釣られてしまいました (一目でYeah, Yeah, Yeah)
#<br>
#僕が勝手に恋をしてしまったんです
#<br>
#君のせいじゃない
自然言語処理の流れ
#前処理(英語や記号を正規表現で削除)
import re
kashi=re.sub("[a-xA-Z0-9_]","",hinatazaka_kashi)#英数字の削除
kashi=re.sub("[!-/:-@[-`{-~]","",kashi)#記号の削除
kashi=re.sub(u"\n\n","\n",kashi)#改行の削除
kashi=re.sub(u"\r","",kashi)#空白の削除
kashi=re.sub(u"\u3000","",kashi)#全角の空白を削除
kashi=kashi.replace(' ','')
kashi=kashi.replace(' ','')
kashi=kashi.replace('','')
kashi=kashi.replace('','')
kashi=kashi.replace('','')
kashi=kashi.replace('','')
kashi=kashi.replace('','')
kashi=kashi.replace('','')
kashi=kashi.replace('','')
kashi=kashi.replace('y','')
kashi=kashi.replace('','')
kashi=kashi.replace('','')
kashi=kashi.replace('','')
kashi=kashi.replace('','')
kashi=kashi.replace('\u3000','')
自然言語処理の流れ
with open("hinatazaka_kashi_1.txt",mode="w",encoding="utf-8") as fw:
    fw.write(kashi)

3:単語の正規化

半角や全角、小文字大文字などを統一する
送り仮名によるもの
「行う」と「行なう」
「受付」と「受け付け」

文字の種類
「りんご」と「リンゴ」
「犬」と「いぬ」と「イヌ」

大文字と小文字
Apple と apple

※今回は無視する

4:形態素解析(単語分割)

文章を単語ごと分割する
MeCab
Janome
JUMAN++

5:基本形への変換

語幹(活用しない部分)への統一を行う
例:学ん(だ)→学ぶ
昨今の実装では基本形へ変換しない場合もある

4,5:形態素解析(単語分割)&基本形への変換

path="hinatazaka_kashi_1.txt"
f = open(path,encoding="utf-8")
data = f.read()  # ファイル終端まで全て読んだデータを返す
f.close()
#3.形態素解析
import MeCab

text = data
m = MeCab.Tagger("-Ochasen")#テキストをパースするためのTaggerインスタンス生成

nouns = [line for line in m.parse(text).splitlines()#Taggerクラスのparseメソッドを使うと、テキストを形態素解析した結果が返る
               if "名詞" or "形容動詞" or "形容詞" or"形容動詞" or "動詞" or "固有名詞" in line.split()[-1]]
自然言語処理の流れ
nouns = [line.split()[0] for line in m.parse(text).splitlines()
               if "名詞" or "形容動詞" or "形容詞" or "形容動詞" or "動詞" or "固有名詞" in line.split()[-1]]
自然言語処理の流れ

6:ストップワード除去

出現回数の多すぎる単語など、役に立たない単語を除去する
昨今の実装では除去しない場合もある


my_stop_word=["する","てる","なる","いる","こと","","","y","","","そう","れる","いい","ある","よう","もの","ない","しまう",
                 "られる","くれる","から","だろ","その","けど","だけ","","","まで","つて","じゃ","たい","なら","たら","なく","られ","まま","たく"]

nouns_new=[]
for i in nouns:
    if i in my_stop_word:
        continue
    else:
        nouns_new.append(i)
自然言語処理の流れ
import codecs
with codecs.open("hinatazaka_kashi_2.txt", "w", "utf-8") as f:
    f.write("\n".join(nouns_new))

7:単語の数値化

機械学習で扱えるよう文字列から数値へ変換を行う

8:モデルの学習

タスクに合わせ、古典的な機械学習~ニューラルネットワーク選択する
それでは、この流れのうち前処理にあたるものを把握する。

#7,8:単語の数値化&モデルの学習

from gensim.models import word2vec

corpus = word2vec.LineSentence("hinatazaka_kashi_2.txt")
model = word2vec.Word2Vec(corpus, size=100 ,min_count=3,window=5,iter=30)
model.save("hinatazaka.model")
model = word2vec.Word2Vec.load("hinatazaka.model")

# ドライバーと類似している単語を見る
print('好きと関連する単語ベスト10')
similar_words = model.wv.most_similar(positive=[u"好き"], topn=10)
for key,value in similar_words:
    print('{}\t\t{:.2f}'.format(key, value))

print('-----')
# # 2つの単語の類似度を計算
similarity = model.wv.similarity(w1=u"笑顔", w2=u"")
print('「笑顔」と「夏」の類似度=>' + str(similarity))

similarity = model.wv.similarity(w1=u"友達", w2=u"")
print("「友達」と「夏」の類似度=>" + str(similarity))

similarity = model.wv.similarity(w1=u"女の子", w2=u"")
print('「女の子」と「男」の類似度=>' + str(similarity))
自然言語処理の流れ

類似度

この中で出てくる類似度というのは、cos類似度のことを言っています。
cos類似度とは簡単にいうと、2つのベクトルがどれだけ同じ方向を向いているか(類似しているか)を数値化したものです。cos類似度が0のときには、類似度が低く、1のときには類似度が低いことを示しています。
cos類似度は以下のような計算式で表されます。

自然言語処理の流れ

#【総評】
***「パパデュワデュワデュワデュワデュワデュワパパパパ」***ってなんやねん。
歌詞じゃなくてメンバーのブログからデータを取得するとメンバーの仲良し度も分かるんじゃないかな。(次回やってみようかな…)

参考文献

1:自然言語処理の基礎(TensorFlow)

2:[uepon日々の備忘録]
(https://uepon.hatenadiary.com/entry/2019/02/10/150804)

3:[Np-Urのデータ分析教室]
(https://www.randpy.tokyo/entry/word2vec_skip_gram_model)

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?