PyTorchを使ってジャパリパークの歌詞みたいなやつを生成させたい

# はじめに
先日，Preferred Networks(PFN)社が提供している深層学習ライブラリ「Chainer」の開発が終了しましたね．
私の研究室ではTensorflow派とChainer派に分かれており，互いにマウントを取り合っていたのですが，開発終了と同時にChainer派が淘汰されてしまいました(キレそう)．

私自身はChainerを愛用しておりましたのでとても残念に思うのと同時に，今まで使いやすいフレームワークを提供して頂いたことによる感謝の気持ちでいっぱいでございます(信者)．

さてそのPFN社なのですが，PyTorchの開発へ移行するらしいです．
しかもPyTorch自体がChainerの記述に似ている面が多いと聞きます．
また私の研究では主に使用したのがCNNやらGANなのですが，RNN関連に手を付けていませんでした．．．．

**「これはPyTrochの使い方とRNNの仕組みを勉強する良い機会では？？？」**

ということで「[ゼロから始めるDeep Learning②](https://www.oreilly.co.jp/books/9784873118369/)」の本を研究室の同期から~~奪い~~借り，RNNの内容を一通り読んでPyTorchで実装しました．
この記事はその備忘録となっております．

まぁ正直なところ，
**「RNNよくわからん」**
**「PyTorchの使い方よくわからん」**
**「賢い人たちからご教授ほしぃ」**
って感じなので記事にしました．

ソースコードは[Github](https://github.com/kibounoasa/generate_sentence)に載せました．
~~ちなみに「けものフレンズ」はみたことないです．~~1話だけ観ました．

# この記事の内容
- PyTorchのLSTMを使ってジャパリパークの歌詞を学習させる
- 自動でジャパリパークっぽい歌詞を生成するようにする
- PyTorchでTruncated BPTTを実装する

# RNNとかLSTM って何ぞや
RNNはRecurrent Neural Networkの略で主に時系列データを対象としたニューラルネットワークです．
通常のニューラルネットワークのレイヤとは異なり，RNNのレイヤは自身の出力を入力としてループする経路を持っています．
これにより時系列ごとの隠れ情報が保持ができるという特徴を持ちます．
LSTMはRNNの派生であり，ループ構造に加えゲートという概念を加えたものです．

詳しい説明はチンパンな私が説明するよりも[ここ](https://qiita.com/kazukiii/items/df809d6cd5d7d1f57be3)とか[ここ](https://qiita.com/KojiOhki/items/89cd7b69a8a6239d67ca)を見たほうがよっぽど分かりやすいです．

# データセットの作成
テキストデータ内の単語情報を被らないように書き出していったデータリストを「コーパス」と言うそうです．
このコーパス内の単語にIDを割り振り，IDリストにして扱いやすくするそうです．
ただ今回は単語を分けるのが面倒だったため(~~MeCabを使え~~)，歌詞に出てくる文字の一文字ずつにIDを割り当てていき，歌詞の始まりと終わりを表すために'^'と'_'を足しました．

以下がIDリストとそれに対応する単語です．

```
{'^': 0, 'W': 1, 'e': 2, 'l': 3, 'c': 4, 'o': 5, 'm': 6, ' ': 7, 't': 8, 'よ': 9, 'う': 10, 'こ': 11, 'そ': 12, 'ジ': 13, 'ャ': 14, 'パ': 15, 'リ': 16, 'ー': 17, 'ク': 18, '!': 19, '今': 20, '日': 21, 'も': 22, 'ド': 23, 'ッ': 24, 'タ': 25, 'ン': 26, 'バ': 27, '大': 28, '騒': 29, 'ぎ': 30, 'が': 31, 'ぉ': 32, '高': 33, 'ら': 34, 'か': 35, 'に': 36, '笑': 37, 'い': 38, 'え': 39, 'ば': 40, 'フ': 41, 'レ': 42, 'ズ': 43, '喧': 44, '嘩': 45, 'し': 46, 'て': 47, 'す': 48, 'っ': 49, 'ち': 50, 'ゃ': 51, 'め': 52, '仲': 53, '良': 54, 'け': 55, 'の': 56, 'は': 57, '居': 58, 'な': 59, '本': 60, '当': 61, '愛': 62, 'あ': 63, 'る': 64, 'ほ': 65, '君': 66, '手': 67, 'を': 68, 'つ': 69, 'で': 70, '冒': 71, '険': 72, '(': 73, 'ワ': 74, '・': 75, 'ツ': 76, 'ス': 77, ')': 78, '姿': 79, 'た': 80, '十': 81, '人': 82, '色': 83, 'だ': 84, '魅': 85, 'れ': 86, '合': 87, '夕': 88, '暮': 89, '空': 90, '指': 91, 'と': 92, '重': 93, 'ね': 94, 'じ': 95, 'ま': 96, '知': 97, 'り': 98, '振': 99, '向': 100, '\u3000': 101, 'ト': 102, 'ラ': 103, 'ブ': 104, 'ル': 105, 'ん': 106, 'ぷ': 107, '目': 108, '見': 109, 'み': 110, '自': 111, '由': 112, '生': 113, 'き': 114, '飾': 115, 'く': 116, '丈': 117, '夫': 118, 'ど': 119, 'ぞ': 120, '♡': 121, 'N': 122, 'i': 123, 'y': 124, 'u': 125, 'ろ': 126, '優': 127, '顔': 128, '待': 129, '開': 130, '扉': 131, 'ゲ': 132, '夢': 133, 'ぱ': 134, '語': 135, '続': 136, 'グ': 137, 'イ': 138, 'ニ': 139, '私': 140, 'サ': 141, 'キ': 142, '頑': 143, '張': 144, 'ア': 145, 'さ': 146, 'お': 147, 'せ': 148, '行': 149, 'わ': 150, '上': 151, '一': 152, '懸': 153, '命': 154, 'ロ': 155, 'ぜ': 156, 'ぇ': 157, '、': 158, '番': 159, '?': 160, 'O': 161, 'h': 162, '東': 163, 'へ': 164, '吠': 165, '西': 166, '世': 167, '界': 168, '中': 169, '響': 170, 'ァ': 171, 'メ': 172, 'デ': 173, 'ィ': 174, ',': 175, '集': 176, '友': 177, '達': 178, '素': 179, '敵': 180, '旅': 181, '立': 182, '_': 183}
```

なんか全角スペースが'\u3000'として登録されてますが，とりあえず無視します．


#ネットワーク構成
PyTorchで実装したネットワーククラスのソースコードです．

```python
import torth.nn as nn
class LSTM_net(nn.Module):
    def __init__(self, corpus_max):
        super(LSTM_net, self).__init__()
        self.embed = nn.Embedding(corpus_max, int(corpus_max/3))
        self.lstm = nn.LSTM(input_size=int(corpus_max/3), hidden_size=int(corpus_max/6), batch_first=True)
        self.out = nn.Linear(int(corpus_max/6), corpus_max)
        self.hidden_cell = None

    def init_hidden_cell(self):
        self.hidden_cell = None

    def repackage_hidden(self, hidden_cell):
        self.hidden_cell = (hidden_cell[0].detach(), hidden_cell[1].detach())

    def forward(self, x, t_bptt=False):
        h = self.embed(x)
        all_time_hidden, hidden_cell = self.lstm(h, self.hidden_cell)
        if t_bptt:
            self.repackage_hidden(hidden_cell)
        out = self.out(all_time_hidden[:, -1, :])
       
        return out
```
こうしてみると書き方がChainerっぽいですよね．
すこ．

## Embeddingレイヤ
私の理解が正しければ，EmbeddingレイヤはIDに対応する重みパラメータ行を抜き出す操作らしいです．
ですのでIDをone-hot表現に直して全結合層に入力する際の重み乗算をしなくてよいので，計算量が莫大に減るんだとかなんとか．．．

PyTorchでのEmbeddingレイヤは，

```python
import torth.nn as nn
nn.Embedding(IDの総数，取り出したときの重みの次元数)
```
で実装できます．(たぶん)


## PyTorchのLSTMについて
[ここ](http://hilinker.hatenablog.com/entry/2018/06/23/204910)によるとPyTorchのLSTMでは，入力されるテンソルは3次元であり，
`(入力する時系列の長さ, バッチサイズ, ベクトルサイズ)`だそうです．
ここでインスタンス生成時に`batch_first=True`とすることにより
`(バッチサイズ，入力する時系列の長さ, ベクトルサイズ)`となります．
そして戻り値としては，入力した時系列の長さから得られるすべての出力値と，最後の時間に関する出力値のタプルで返ってきます．

言葉ではうまく言えないんですけど下図のような感じです．

<img width="700" alt="foward_rnn.png" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/568688/55a682ee-9001-713b-12fc-e2916466bf7b.png>

したがってプログラム内の`all_time_hidden[:, -1, :]`と`hidden_cell`は実質同じです．


## Truncated BPTT
RNNの誤差逆伝搬では，時間軸で横方向に展開した時の計算グラフを追う事で，通常のニューラルネットワークのような逆伝搬を行います．

これをBack Propagation Through Time (BPTT)と呼びます．(下図)
<img width="800" alt="rnn.png" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/568688/39e99f12-05ac-8811-f6c3-da89b1e89ee6.png>

しかしここで問題があります．それは時系列の長さに比例してレイヤが深くなってしまう事です．
一般に深層学習はレイヤが深いほど勾配消失や勾配爆発を起こし，計算リソースも増加することになります．

そこで時系列の長いデータを扱う場合，逆伝搬の繋がりを適当な長さでを切り捨てる(truncate)
という考え方がTruncated BPTTです．(下図)
![truncate.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/568688/aace0b89-3603-bfcd-5cbe-307f55fc0049.png)
ここで注意しなければならないことが，順伝搬の繋がりは保持したままということです．
すなわち時刻tとt+1の間で繋がりを切る場合，順伝搬の際に時刻tで得られた出力を
時刻t+1での入力の値として保持しなければなりません．

ソースコードとしては，以下の部分と対応します．

```python
    def repackage_hidden(self, hidden_cell):
        self.hidden_cell = (hidden_cell[0].detach(), hidden_cell[1].detach())
```

得られた出力値を新しいテンソルとして作り直しており，この関数が呼ばれた時点で計算グラフを一旦切っています．
`.detatch()`というのが，Chainerで言うところの`.data`みたいに値だけを参照する役割に相当します(たぶん)．

また，LSTMは出力がhiddenとcellで二つあるので，それぞれを要素としたタプルで作成しています．



#学習
とりあえず学習の部分となるソースコードの部分を載せます．

```python
class Util():
    def make_batch(self, corpus, seq_len, batchsize=5):
        train_data = []
        label_data = []
        for i in range(batchsize):
            start = random.randint(0, len(corpus)-seq_len-1)
            train_batch = corpus[start:start+seq_len]
            label_batch = corpus[start+1:start+seq_len+1]

            train_data.append(train_batch)
            label_data.append(label_batch)

        train_data = np.array(train_data)
        label_data = np.array(label_data)
        return train_data, label_data

class Loss_function(nn.Module):
    def __init__(self):
        super(Loss_function, self).__init__()
        self.softmax_cross_entropy = nn.CrossEntropyLoss()
        self.mean_squared_error = nn.MSELoss()
        self.softmax = nn.Softmax()

def main():
    model = LSTM_net(corpus_max=corpus.max()+1)
    opt = optim.Adam(model.parameters())
    loss_function = Loss_function()
    util = Util()
    
    epoch = 0
    max_seq_len = 16 #逆伝搬で切り取る文字の長さ指定
    batch_size = 32

    while True:
        seq_len = 256 #学習で切り取る長さ
        train_data, label_data = util.make_batch(corpus, seq_len, batch_size)
        train_data = torch.tensor(train_data, dtype=torch.int64)
        label_data = torch.tensor(label_data, dtype=torch.int64)
        
        loss_epoch = 0    
        count = 0
        for t in range(0, seq_len, max_seq_len):
            train_seq_batch = train_data[:, t:t+max_seq_len]
            label_seq_batch = label_data[:, t:t+max_seq_len]
            out = model(x=train_seq_batch, t_bptt=True)
            loss = loss_function.softmax_cross_entropy(out, label_seq_batch[:, -1])
            opt.zero_grad()
            loss.backward()
            opt.step()    
            loss_epoch += loss.data.numpy()
            count += 1
        loss_epoch /= count
        epoch += 1
        sys.stdout.write( "\r|| epoch : " + str(epoch) + " || loss : " + str(loss_epoch) + " ||")
        
        model.init_hidden_cell()
```


## 方針
任意長の文字列の入力から，次の文字を予測させるように学習させたいと思います．
今回は歌詞データの中から適当な位置を決め，そこから256文字分を取り出し，長さ16でTruncated BPTTをしていこうとおもいます．

ソースコード内の`model.init_hidden_cell()`が呼び出されるまで順伝搬は保持されており，
長さ16のブロック内で逐次逆伝搬を行っています．

Lossの取り方は最後の入力に対する出力が，次の文字(におけるIDのone-hot表現)
となるようにソフトマックスクロスエントロピーをとっています．

ちなみにLoss_functionがクラスになってることの意味はないです(謝罪)．


#結果
とりあえず歌詞を生成するためのソースコードはこんな感じになります．

```python
            index = random.randint(0, corpus.max()-1)
            gen_sentence = [index]
            print(convert.id2char[index], end="")
            for c in range(700):
                now_input = np.array(gen_sentence)
                now_input = torch.tensor(now_input[np.newaxis], dtype=torch.int64)
                out = F.softmax(model(now_input, t_bptt=True), dim=1).data.numpy()[0]
                next_index = int(np.random.choice(len(out), size=1, p=out)[0]) #ランダムにサンプリング
                #next_index = int(out.argmax()) #最大確率をサンプリング
                print(convert.id2char[next_index], end="")
                if((c+2)%100==0):
                    print("")
                gen_sentence = [next_index]
```

まず初めに，学習済み`model()`に適当な文字リストのIDをに与えます．
その一文字から次に来る文字を予想した出力をまた入力し，またその次の文字を予想し．．．
を繰り返すこと700回くらいすることで歌詞を生成していきます．
このとき`model()`の出力はID毎の確率として表せるので，一番確率の高いIDを次の文字としても良いのですが，ランダム性を持たせたほうが楽しそうと思い，確率分布からサンプリングという形で文字IDを決定します．

##Lossグラフ
![loss.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/568688/1af35c01-f755-5ad2-f707-b9ee41319f9a.png)
気持ちいくらいの下がりよう．これは嫌な予感．


##生成した歌詞
以下生成した歌詞です

- epoch 0
>
由険え西優わ?iブリイhをうよよろャ!のパーこきてよ番けリ か命けeイこo クジ響てct 指e om 君大トー本はにせパパド騒まーいい上指ッ一のはtか本続oないワ懸うトバ十ていでんりる ま♡にーかラ大らじでたえぷちぜ私みけんもでァそをバかこタ界なリ語y高あしロゃえル空らフて夫eャてパラhに ブ は居うかー!リつ ♡とも君笑イっぷそううキそい空いはまーしャl待ーがかよ!cラeぉクジイグル日ーい!eいもく いーまeーよういこらけいャくもレパば本日よlcラバは空ター丈(ルぉ行ちかもいいい)いースあどけたス暮ッバへtリ tイ 立うっいっば こル ぷャつーhイィうッタすぇパて行Wおcーmeのらでcそかャへろ手はいe tらサO ト番良行か達日を騒っ語友イ(け君冒吠eo日っ一cてこいャ えん西いぷッのでまて夢れくいに、でくたでういも十)もてにthc ラ張クるラ ブ達飾向ロoパh夕ーけんララララ ,パぷhのぷサ!タt 東ちいuそし冒の良ドを素待W頑m見 愛すすパまん重か飾まイか日バこャい)へリ命生うtoういい私mよはす!e まかかーり) ・んつをに嘩るかーワたいも行 なて手にそい指ロは世愛なこパはワク色でバ君がしすな私!ちか(てだのみるバoち　W飾合t響でッも t oにe 良うャ世ス生らキ世ど!ーバこ高かだしっては番よ!ラいグ!よは十のててだがララく 行もジも目　なもっにま顔Nで日ぞ見 くhャくリい・吠吠ャし私ー私 よに!し笑っ、ア)んんそさサもはてぷ十でoだりャつ うトまツうーと目い向もーロク続しも魅でらまも手よロhuれ ねけジか当合もイ張リ夕 十君ロたのラ君グイブに(なれん!うんジ顔でもラろで番

- epoch 320
>
え、た 君ももの 敵なったちゃら魅かれた扉(ゲート) 素ト) 君も飾ってブさんて はい笑ていで大丈夫(いどーぞ♡)Nice to ようこそ ジャパリパーク!今日もドッタンバッタン大騒ぎ姿かたちも十人十色 だから魅かれ合うの夕暮れ空に 指をそっと重ねたらはじめまして君をもっと知りたいなうー!がぉー!ラララララ ラララ Oh, Welcomet yo ようこそジャパリパーク!今日もドッタンバ しんてく大目見てねみんな自由に生にきていきかてるそう 君も飾らなものった てんでんバラバラバラちんぷんかんぷんまとまんないけものですもの 大目に見ててねみんな自由に生きている でんてラ んけも 西私ここはどーバルキャットのサーバルだよ!はーいよー頑張っていきますよーよーしアライさんにおまかせなのだー!みんな行くわよものっと上を目指さないと一生と一生懸命頑張りますロックに行くぜぇーえ、もう険(のいの集たらはじめまして君をもっと知りたいなうー!がぉー!グこで続ここっちelcome to to よジャパリパーク!今日からはどうぞよろしくねいつもいつでも居も優しい笑顔 君を待っていたの開かれた扉(ゲート) 夢をいっぱい語ったらどこまででも続いててくグレイトジャーニーこ向!はじ自指そジャ吠うーニーここはそジクはジャパリパーク私はサ ーバルキャットのサーバルだよ!はいつなものだ!ラララ 集まれとルなパー!今日から魅かンらはどうぞよろしくねいでももいつでも優しい笑顔 君を待っていたの開かれた扉(ゲート夢こをいっぱい語ったらはどーここe そ こで大冒険(私ちんらま君ものよーしもイさはサーバルだよアライだれたはの夕暮れ`

- epoch 500
>
わえ!みとろきますロックに行くぜぇーえ、もう本番ですか?Oh 東へ吠えろら melcome to the ジャパリパーク!ララララ 素色lc Weelcome to Ohe ジャパリパーク私はサーバルキャットのサーバルだ!がはぉー!振り向けなイさだよー頑張っていきますよーよーしアライさんにおまかせなのだー!みんな行くわよ もっと上を目指さないと一生懸命頑張りますロックに行くぜぇーえ、もう本番ですか?Oh 東へ吠えろ 西へ吠えろ世界中に響け サファリメロディWelcome to ようこそジャパリパーク!Welcome to ようこそジャパリパーク!Welcome to ようこそジャパリパーク!今日からはどうぞよろしくねいつもいつでも優しい笑顔 君を待っていたの開かれん扉(ゲートのここそうこにそジャパリパーク!今日もド ッタンバッタン大騒ぎ重ねたまれた開ら君ものゲート)ラ 西へ吠えろ世世界中に響け サファリメロディWelcome to ようこそジャパリパーク!Welcome to ようこそジャパリパーク!今日からはどうぞよろしくねいつもい つでも優しい笑顔 君を待っていたの開かれた扉(ゲート)夢をいっぱい語ったらどこまででも続いてくグレイトジャーニーこここはどジャパリパーク私はサーバルキャットのサーバルだよ!は ーいよー頑張っていきますよーよーしアライさんにおまかせなのだー!みんな行くわよもっと上を目指さないと一生懸命頑張りますロックに行くぜぇーえ、もう本番ですか?Oh 東へ吠えろ 西へ吠えろ世界中に響け サファリメロディWelcome to ようこそジャパリパーク!今日からはどうぞよろし

- epoch 1810
>
そー!振り向けば　あちらこちらでトラブルなんてこった てんでんバラバラちんぷんかんぷんまとまんないけものですもの 大目に見 ててねみんな自由に生きているそう 君も飾らなくて大丈夫(はいどーぞ♡)Nice to meet you ジャパリパーク!今日からはどうぞよろしくねいつもいつでも優しい笑顔 君を待っていたの開かれた扉(ゲート) 夢をいっぱい語ったらどこまででも続いてくグレイトジャーニーここはジャパリパーク私はサーバルキャットのサーバルだよ!はーいよー頑張っていきますよーよーしアライさんにおまかせなのだー!みんな行くわよもっと上を目指さないと一生懸命頑張りますロックに行くぜぇーえ、もう本番ですか?Oh 東へ吠えろ 西へ吠えろ世界中に響け サファリメロディWelcome to ようこそジャパリパーク!今日もドッタンバッタン大騒ぎ姿かたちも十人十色 だから魅かれ合うの夕暮れ空に 指をそっと重ねたらはじめまして君をもっと知りたいなうー!がぉー!振り向けば　あちらこちらでトラブルなんてこった てんでんバラバラちんぷん かんぷんまとまんないけものですもの 大目に見ててねみんな自由に生きているそう君も飾らなくて大丈夫(はいどーぞ♡)Nice to meet you ジャパリパーク!今日からはどうぞよろしくねいつもいつでも優しい笑顔 君を待っていたの開かれた扉(ゲート) 夢をいっぱい語ったらどこまででも続いてくグレイトジャーニーここはジャパリパーク私はサーバルキャットのサーバルだよ!はーいよー頑張っていきますよー よーしアライさんにおまかせなのだー!みんな行くわよもっと上を目指さないと一生懸命頑

わーい，過学習だー，たのしー(真顔)


# 最後に
今回記事を投稿するのが初めてでしたので，拙い部分や分かりにくい部分が多かったですね．
だからといって書き直す気力もないのでこのまま投稿して
有志の人たちからボコボコにされようと思います．

アドバイスや間違っているところの指摘などをお待ちしております．

kibounoasa


#おまけ
いろんな曲の歌詞をデータセットにいれて自動生成した結果です．
なんの曲が入っているんでしょうね．
>
ちゃだから魅かれ合うの夕暮れ空に　指をそっと重ねたらはじめまして君をもっと知りたいなうー!がぉー!振り向けば　あちらこちらでトラブルなんてこった　てんでんバラバラちんぷんかんぷんまとまんない けものですもの　大目に見ててねみんな自由に生きているそう　君も飾らなくて大丈夫(はいどーぞ?)Nice to meet you　ジャパリパーク!ララララ　Oh, Welcome to the　ジャパリパーク!ララララ　ラララララ　素敵な旅立ちようこそジャパリパーク!せ～の でも 大目に見ててねみんな自由に生きているそう　君も飾らなくて大丈夫(はいどーぞ?)Nice to meet you　ジャパリパーク!今日からはどうぞよろしくねいつもいつでも優しい笑顔　君を待っていたの開かれた扉(ゲート)　夢をいっぱい語ったらどこまででも続いてくグレイトジャーニーOh　東へ吠えろ　西へ吠えろ世界中に響け　サフ ァリメロデディ―Welcome to　ようこそジャパリパーク!Welcome to　ようこそジャパリパーク!Welcome to　ようこそジャパリパーク!Welcome to　ようこそジャパリパーク!Welcome to　ようこそジャパリパーク!Welcome to　ようこそジャパリパーク!今日もドッタン・大騒ぎうー!がぉー!高ばぁえんｷはひy?Let's goｷﾗｷﾗ　ﾋﾟｶも　ﾋﾟｺｰﾝ　もふもふ　なでなで　にこにこ　グルグル　ﾃﾞｰﾝ　ゴロゴロ　ﾃﾞﾃﾞｰﾝ　わくわく　うずうずバタバタ　ノロノロ　あ～？　ウロウロ　あっ　てくてく　コソコソ　ガサガサ　すんすん　お？　ペロペロ　おっ　いただきますもぐもぐｷﾗｷﾗ?ｷﾞｭｲｰﾝ　ﾋﾟｶﾋﾟｶ　ﾋﾟｺｰﾝ　もふもふ　なでなで　にこ！　ふわふわり　ふわふわり　ふわふわるあなたが　名前を呼ぶそれだけで宙へ浮かぶふわふわる　ふわふわりあなたが笑っている　それだけで笑顔になる神様 ありがとう　運命のいたずらでもめぐり逢えたことが　しあわせなのでも　そんなんじゃ　だめもう　そんなんじゃ　ほら心は進化するよ　もっと　もっとそう　そんなんじゃ　やだねぇ　そんなんじゃ　まだ私のこと　見ててね　ずっと　ずっと私の中のあなたほどあなたの中の私の存在はまだまだ 大きくないことも　わかっているけれど今この同じ 瞬間　共有している 実感ちりもつもればやまとなでしこ！略して？ちりつもやまとなでこ！くらくらり くらくらるあなたを見上げたらそれだけでまぶしすぎてくらくらる くらくらりあなたを思っているそれだけで　とけてしまう神様 ありがとう　運命のいたずらでもめぐり逢えたことがと　見ててね　ずっと　ずっとドゥンぱーぱーぱーぱーぱーぱーぱーぱーぱーぱーぱーﾄﾞﾝ　おっ　ﾀﾝ　ﾄﾞﾝ　ﾄﾞｯおっ？　ﾄﾞｯ　ﾃﾞｨﾝ　ﾄﾞﾝ　ﾄﾞｯお?！　ﾄﾞｯ　ﾊﾟｯﾊﾟｰ　ﾄﾞﾝ　ぬっ！ﾄﾞﾝ　おっ　ﾀﾝ　ﾄﾞﾝ　ﾄﾞｯおっ？　ﾄﾞｯ　ﾃﾞｨﾝ　ﾄﾞﾝ　ﾄﾞｯお?！　ﾄﾞｯ　ﾊﾟｯ　ﾄﾞﾝ　ﾄﾞｯうん　ｼｬｷｰﾝ　ﾃﾞｰﾝﾀﾝ　んsｺﾞﾛｺﾞﾛ　ﾀﾝ　ﾄﾞｯ　じゃーん！　あははひとつの光が（Yeah）　輝いて　言葉選んで　紡いだの辛いときも　寂しいときも私が　いるから続く物語　星の絆で繋ぐからずって神出鬼没チャンスを待ったら一日千秋追いかければ東奔西走時代は常に千 変万化人の心は複雑怪奇でも本気でそんなこと言ってんの?もうどうにも満身創痍嗚呼、巡り巡って夜の町キミは合図出し踊りだすはぁ～回レ回レ回レ回レ回レ回レ回レ回レ!華麗に花弁散らすように回レ回レ回レ回レ回 レ回レ回レ
回レ!華麗に花弁散らすように回レ回レ回レ回レ回レ回レ回レ回レ回レ!髪も振り乱して一昨日、昨日、今日と、明日と、明後日とこの宴は続く踊レ、歌エ、一心不乱に回レ!今宵は雪月花ほい! いよーーーーっ  ぽん!ハッハッハッハッハイヤハッハッハッハッハッハッいよーーーーっ ぽん!どこからともなく現れてすぐどこか行っちゃって神出鬼没チャンスを待ったら一日千秋追いかければて東奔西走時代は常に千変万化人の 心は複雑怪奇でも本気でそんなこと言ってんの?もうどうにも満身創痍嗚呼、巡り巡って夜の町キミは合図出し踊りだすはぁ～回レ回レ回レ回レ回レ回レ!華麗に花弁散らすように回レ回レ回レ回レ回レ回レ回レ回レ!華麗に花弁散らすように回レ回レ回レ回レ回レ回レ回レ回レ!華麗に花弁散らすように回レ回レ回レ回レ回レ回レ回レ回レ回レ!髪も振り乱して一昨日、昨日、今日と、明日と、明後日とこの宴は続く踊レ、歌エ、一心不乱に回 レ!今宵は何曜日か?水木金?土日月火?ハッハッハッハッハッハッハッハイヤハッハッハッハッハイヤハッハッハッハッいよーーーーっ ぽん!でも そんなんじゃ だめもう そんなんじゃ ほら心は進化するよ　もっと もっ と言葉にすれば　消えちゃう関係なら言葉を消せばいいやって思ってた　 恐れてただけど あれ？ なんかちがうかもせんりのみちもいっぽから石のようにかたい　そんな意志でちりもつもれば やまとなでしこ？ 「し」抜きで いや　死ぬ気で！ふわふわり　ふわふわるあなたが　名前を呼ぶそれだけで宙へ浮かぶふわふわる　ふわふわりあなたが笑っているそれだけで笑顔になる神様 ありがとう　運命のいたずらでもめぐり逢 えたことが　しあわせなのコイスルキセツハ ヨクバリ circullationふわふわり ふわふわるあなたが名前を呼ぶそれだけで　宙へ浮かぶふわふわる ふわりあなたが笑っている　それだけで　笑顔になる神様 ありがとう　運命のいたずらでもめぐり逢えたことが　しあわせなのでも　そんなんじゃ　だめもう　そんなんじゃ　ほら心は進化するよ　もっと　もっとそっとそう　そんなんじゃ　やだねぇ　そんなんじゃ　ま だこと　見ててね　ずっと　ずっとドゥンぱーぱーぱーぱーぱーぱーぱーぱーぱーぱードゥンぱーぱーぱーぱーぱーぱーぱーぱーﾄﾞﾝ　おっ　ﾀﾝ　ﾄﾞﾝ　ﾄﾞｯおっ？　ﾄﾞｯ　ﾃﾞｨﾝ　ﾄﾞﾝ　ﾄﾞｯお?！ﾄﾞｯ　ﾊ