LoginSignup
4
4

More than 3 years have passed since last update.

韻を扱いたい part1

Posted at

はじめに

ラップが好きなので良さを広めたいと常々考えていた。「韻」がおもしろさであり、深い部分である。何度か作詞してみたが、どうもしっくりこない(ダジャレのようになったり、韻を意識して話が散らかる)。ならば、作詞の元となるものを入力すると、「韻」的なものを出力してくれれば良いのでは??ということでやってみる。
(皆さんも青春時代にラブソングとか作詞しませんでした?笑。)

韻の判断

韻と一口に言っても発音で聞こえが変わる(「そう」と「そお」)等、奥が深い。今回は、母音[a,i,u,e,o]が同じ並びになれば「韻」とする。ローマ字変換が必要となるが、kakashi(ここを参考にしました)がそれを可能にしてくれる。取り敢えずの入力データは某ラッパーの1曲の歌詞を記入したテキストデータを使ってみる。
(「かかし」といえば「ロボか案山子並みbyKICK THE CAN CREW」が思い浮かぶ)

from pykakasi import kakasi
import re

with open("gennama.txt","r") as f:
    data = f.read()

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

conv = kakasi.getConverter()
filename = data
data = conv.do(filename)
data_re = re.sub(r"[^aeiou]+","",data)

print(data_re)#出力 oeauiaau...

韻の数値化

kakasiでローマ字へ変換し、re.sub()で目的の[a,i,u,e,o]のみ抽出できた。次は、入力データを一定の決まりで分割し、母音が一致している部分になにかしらの処理をしていきたいのだが、ここで路頭に迷う。何がしたいか、何が「韻」なのかが分けわからなくなってしまう。入力データの形、変形のさせ方でずっと悩んでいたが、進まないので取り敢えず「韻を数値化」することを考えた。
(「みんな進化した韻がいいんだぜと 言い出した下in the 銀座線byYOSHI(餓鬼レンジャー)」[いん]の音が心地よい。今回[n]は考えてないが)

#短い方のwordをスライスし、他方にそれが含まれていた場合「韻」と見なし、その長さをスコアとして加算する
def make_score(word_a, word_b):
    score = 0
    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):
                if word_b[i:j] in word_a:
                    score += len(word_b[i:j])
    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:
                    score += len(word_a[i:j])
    return score

このscoreで「韻の数値化」は表現できたと思う。語尾の合致だけをscoreにしても良かったが、wordをスライスすることにした。
日本語の動詞は全て「u」の音で終わる。動詞ばかりで韻を踏むことは好ましくない

出力するもの

さて、未だ入力データがうやむやなままだが、ここまでのもので出力を考える。出力もうやむやで、「韻」的なものなのだが。。
「韻の数値化」はword同士の類似性とも言える。片方のwordに好きな言葉を入力すると、データの中から類似性の高いものをレコメンドしてくれる、という感じで進めてみる。入力データは某ラッパーの歌詞、分割方法は歌詞カード通りの空白、この条件でこれまでのものをまとめる。
キャッチコピーやダジャレも韻だと思っている。同音異義語が主であるが。ラップ中の韻も心地良い。韻を踏むことでいいこと言った感が強まると思う。

from pykakasi import kakasi
import re

with open("./gennama.txt","r", encoding="utf-8") as f:
    data = f.read()
#今回は「hoge hogehoge ...」のようなスペースだけで分かれているのでsplit()のみの前処理
data_sp = data.split()
target_word_origin = "げんなま"

kakasi = kakasi()

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

conv = kakasi.getConverter()
#ローマ字へ変換
target_word = conv.do(target_word_origin)
text_data = conv.do(data).split()
text_data = list(text_data)
#母音のみ残す
target_word_vo = re.sub(r"[^aeiou]+","",target_word)
vowel_data = [re.sub(r"[^aeiou]+","",text) for text in text_data]
#vowel_dataのインデックスで母音変換前のdataが分かるように辞書作成。
dic = {k:v for k,v in enumerate(data_sp)}

#短い方のwordをスライスし、他方にそれが含まれていた場合「韻」と見なし、その長さをスコアとして加算する
def make_score(word_a, word_b):
    score = 0
    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):
                if word_b[i:j] in word_a:
                    score += len(word_b[i:j])
    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:
                    score += len(word_a[i:j])
    return score
#それぞれ母音のみにしたデータと任意の言葉を渡す。後に元の言葉が分かるようインデックスとスコアをセットで取得。
def get_idx_score(vowel_data, target_word):
    ranking = []
    for i, word_b in enumerate(vowel_data):
        score = make_score(target_word, word_b)
        ranking.append([i, score])
    return sorted(ranking, key=lambda x:-x[1])

ranking = get_idx_score(vowel_data, target_word_vo)
print(target_word_origin)
for i in range(len(ranking)):
    idx = ranking[i][0]
    score = ranking[i][1]
    print("スコア:" + str(score))
    print("言葉:" + dic[idx])

入力データとして使ったのは完成された歌詞であるが、target_wordに歌詞中のワードを使っても必ずしも韻を踏んでいる部分が上位にこない。それもそのはず、入力データの分割方法が適当である。しかし、大枠が出来たことでうやむやだった部分をより具体的に考えることができた。また、問題点がはっきりした。

感想、今後の展開

方向性が見えた。入力は自分の言葉の羅列、出力は今回行ったように入力から韻を踏める言葉をレコメンドしてくれる感じ。こうすることで、自分の言葉で韻が踏めることが分かって面白いと思う。また、自分のように作詞したい場合、韻を気にせず言いたいことを適当に書き出しておけば、歌詞の中心部分ができあがるはずだと考える。今後、入力データのwordへの分割方法、韻の数値化での点数付けも改良が必要である。入力が自分の言葉という自由性を持たせておきたい(方言や、独特の言い回し等残したい)ので、色々試してみようと思う。(単純に品詞縛りで抽出しても望んだ結果にはならなそうではある。)

おわりに

*以下備忘録
自分はプログラミング初心者だ。オンライン学習を受けた後、何か作ろうとした時に、学んだことを全て使おうとして、入力データはスクレイピングして形態素解析して…出力は完成された歌詞、LSTMを用いて…などと考えて何も進まなかった。本文で述べてるように、入出力がうやむやで、何がしたいというものが具体化していなかったため、投げ出してしまっていた。取り敢えず作ったものが欲しくて、誰かのコーディングをパクろうとしたが、同じことをしている人を見つけられなかった。(オリジナルな韻を踏みたい人間がもろパクリしようとしていた…)
今回流れが変わったのは、オンライン学習の復習をしていた時に「レコメンドのコンテンツベースフィルタリング」で、類似度を「韻の数値化」にすればレコメンド出来るんじゃないか?とふと思ったことだ。実は類似度は依然にも注目していたが、どう使うか思いつかなかった。簡単そうなのでやってみたら、望んだ出力結果とならなかった。ここで、どこがポイントなのかはっきりした。さらに、入力データは今回使った歌詞のように言葉の羅列でいいじゃんと思えた。
何が言いたいかというと、まず今回のような大枠を作ることが大切、使うデータも出力を大体予想できるもので良い、出来上がったものの使い道は後から考えても良い、というようなことだ。また、必要ない関係ないと思っていることがリンクすることもある。勉強のモチベーションが下がった時に、それを思い出そうと感じた。

4
4
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
4