1
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 5 years have passed since last update.

韻を扱いたいpart2

Posted at

内容

前回入力データの分割方法に改良が必要なのでは?と感じたため、様々な分割方法を試してみる。入力データは前回同様某ラッパーの歌詞を使用。一応検証用として自分が温めていた韻をテーマにしたものも用意している。

分かち書きの場合

import MeCab

mecab = MeCab.Tagger("-Owakati")
mecab_text = mecab.parse(data).split()

歌詞通りの「韻」を抽出できている部分もあるが、「数万円」で踏んでいるところが分かち書きによって「数、万、円」と分割されているため認識できていない。余談だが、kakashiconv.doに一度に多くのデータは渡せないようだ。text_data = [conv.do(text) for text in mecab_text]とした。ちなみに分かち書き後、母音に変換したwordの長さは最大8文字、平均2.16文字であった。細かく分け過ぎているので、分かち書きでの分割は適していないと言える。
このMeCabを使えるようにするまでに何回も挫けた。色んな記事を見過ぎたのかもしれない。こちらに感謝

N-gramの場合

では、単にN文字ごとに分割していくとどうなるだろう。Nは4から試してみる。

def make_ngram(words, N):
    ngram = []
    for i in range(len(words)-N+1):
        #全角スペースと改行を取り除く
        row = "".join(words[i:i+N]).replace("\u3000","").replace("\n","")
        ngram.append(row)
    return ngram

体感だが、Nは5かそれ以上が良さそうである。(4以下だとスコアの差が付かない)そこそこ歌詞通りに韻を検出できている。試しに検証用データを入れてみると、一見気づかない韻が検出できた。wordが様々な切り取られ方をするのだから、スコアの付け方を変えてみる。

def make_score_ngram(word_a, word_b):
    score = 0
    for i in range(len(word_a)):
        if word_a[-i:] == word_b[-i:]:
            score += i
     return score

母音の一致を語尾から見ることによって、出力が見やすい。Nの値についてはlen(target_word_vo)(韻を探す元の言葉の母音の長さ)が良いだろう。自分がやりたいことが表現できてしまったような気がしている。
折角苦労してMeCabを使用できるようにして、「韻の数値化」も自分なりに考えたので、使いたい。この2つを組み合わせてみる。

target_wordが絞れるのでは?!

「韻の数値化」では母音が合致する部分を探索し、合致している長さlen(word[i:j)をスコアにしていた。このword[i:j]は「eoi」等の形をしており、この出現回数をカウントすれば、入力データ中で一番登場する母音が分かるはずだ。それを含む言葉をtarget_wordに指定すれば、多くのレコメンドが見込めるという考えである。申し訳程度に分かち書きと検証用に用意したテキストを使う。

from pykakasi import kakasi
import re
from collections import defaultdict
import MeCab

with open("./test.txt","r",encoding="utf-8") as f:
    data = f.read()

mecab = MeCab.Tagger("-Owakati")
mecab_text = mecab.parse(data).split()

kakasi = kakasi()

kakasi.setMode('H', 'a')
kakasi.setMode('K', 'a')
kakasi.setMode('J', 'a')

conv = kakasi.getConverter()
text_data = [conv.do(text) for text in mecab_text]
vowel_data = [re.sub(r"[^aeiou]+","",text) for text in text_data]
dic_vo = {k:v for k,v in enumerate(vowel_data)}
# voel_dataのインデックスで母音変換前のdataが分かるように辞書作成。
dic = {k:v for k,v in enumerate(mecab_text)}

# 新たなキーを追加する際に初期化を省きたいためdefaultdictを使用{母音:出現回数}
dic_rhyme = defaultdict(int)
for word_a in vowel_data:
    for word_b in vowel_data:
        if len(word_a) > len(word_b):
            word_len = len(word_b)
            for i in range(word_len):
                for j in range(word_len + 1):
                    #カウントするのは2文字以上に限定
                    if word_b[i:j] in word_a and not len(word_b[i:j])<2:
                        dic_rhyme[word_b[i:j]] += 1
        else:
            word_len = len(word_a)
            for i in range(word_len):
                for j in range(word_len + 1):
                    if word_a[i:j] in word_b and not len(word_a[i:j])<2:
                        dic_rhyme[word_a[i:j]] += 1
# カウントが多かった順にソート
dic_rhyme = sorted(dic_rhyme.items(), key=lambda x:x[1], reverse=True)
print(dic_rhyme)
# dic_rhymeの上位にきたものが含まれているものを探索。ここでは"ai"を使用
bool_index = ["ai" in text for text in vowel_data]

for i in range(len(vowel_data)):
    if bool_index[i]:
        print(dic[i])

登場頻度の高い母音の並びを取得し、どこで使われているか出力できた。しかしながら、分かち書きで細分化された言葉は分かりにくくなっていた。もしかしたら、もう少し長い韻があった可能性もある。

改良点

target_wordを絞るという用途では必要性を感じないが(自分が一番言いたいことを指定したいため)、どの母音の並びが頻出なのかは確認できても良いかもしれない。分かち書きで上手くいかなかったが、MeCabを利用して(何度もいうが、使えるようになるまで四苦八苦した)改良したい。
また、N-gramを採用したことによって「韻の数値化」も簡潔にできたので、もう少し複雑に「韻」を定義し直せないか考える。(現状「っ」など考慮していない)
しかし、回り道をした。「韻の数値化」は韻を漏らさないよう、入力データに対応できるよう、自分なりに考え抜いたつもりのものだ。まさか引数を様々にスライスすることが入力データを様々にスライス(表現が違うかもしれません)で解決できるとは…というかそれに気付かないとは。基本が大事ですね。でもN-gramって意味のない日本語が出来ると感じませんか?ただ、「韻」の部分を強調して発音する等やり方はあるんです。やはり、簡単なデータ使ってとにかくやってみることが大事ってことですわ。

1
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
1
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?