音声合成メモ(tacotron2その4)
トレーニング時におけるmodelの内部処理を見てみる。
Embedding/Encoderレイヤ
Embeddingレイヤに渡す前に、テキスト文字はidに置き換えられる。
idはゼロ始まりの148個。
ARPAbetの発音記号も含まれる。
{'_': 0, '-': 1, '!': 2, "'": 3, '(': 4, ')': 5, ',': 6, '.': 7, ':': 8, ';': 9, '?': 10, ' ': 11, 'A': 12, 'B': 13, 'C': 14, 'D': 15, 'E': 16, 'F': 17, 'G': 18, 'H': 19, 'I': 20, 'J': 21, 'K': 22, 'L': 23, 'M': 24, 'N': 25, 'O': 26, 'P': 27, 'Q': 28, 'R': 29, 'S': 30, 'T': 31, 'U': 32, 'V': 33, 'W': 34, 'X': 35, 'Y': 36, 'Z': 37, 'a': 38, 'b': 39, 'c': 40, 'd': 41, 'e': 42, 'f': 43, 'g': 44, 'h': 45, 'i': 46, 'j': 47, 'k': 48, 'l': 49, 'm': 50, 'n': 51, 'o': 52, 'p': 53, 'q': 54, 'r': 55, 's': 56, 't': 57, 'u': 58, 'v': 59, 'w': 60, 'x': 61, 'y': 62, 'z': 63, '@AA': 64, '@AA0': 65, '@AA1': 66, '@AA2': 67, '@AE': 68, '@AE0': 69, '@AE1': 70, '@AE2': 71, '@AH': 72, '@AH0': 73, '@AH1': 74, '@AH2': 75, '@AO': 76, '@AO0': 77, '@AO1': 78, '@AO2': 79, '@AW': 80, '@AW0': 81, '@AW1': 82, '@AW2': 83, '@AY': 84, '@AY0': 85, '@AY1': 86, '@AY2': 87, '@B': 88, '@CH': 89, '@D': 90, '@DH': 91, '@EH': 92, '@EH0': 93, '@EH1': 94, '@EH2': 95, '@ER': 96, '@ER0': 97, '@ER1': 98, '@ER2': 99, '@EY': 100, '@EY0': 101, '@EY1': 102, '@EY2': 103, '@F': 104, '@G': 105, '@HH': 106, '@IH': 107, '@IH0': 108, '@IH1': 109, '@IH2': 110, '@IY': 111, '@IY0': 112, '@IY1': 113, '@IY2': 114, '@JH': 115, '@K': 116, '@L': 117, '@M': 118, '@N': 119, '@NG': 120, '@OW': 121, '@OW0': 122, '@OW1': 123, '@OW2': 124, '@OY': 125, '@OY0': 126, '@OY1': 127, '@OY2': 128, '@P': 129, '@R': 130, '@S': 131, '@SH': 132, '@T': 133, '@TH': 134, '@UH': 135, '@UH0': 136, '@UH1': 137, '@UH2': 138, '@UW': 139, '@UW0': 140, '@UW1': 141, '@UW2': 142, '@V': 143, '@W': 144, '@Y': 145, '@Z': 146, '@ZH': 147}
短めの音声(LJ030-0109.wav、テキスト「The Vice-Presidential car」)を例に見てみる。
テキスト「The Vice-Presidential car」はスペースも含めてidに置き換えられる(アルファベットは小文字へ変換してからidに置き換え)
[57, 45, 42, 11, 59, 46, 40, 42, 1, 53, 55, 42, 56, 46, 41, 42, 51, 57, 46, 38, 49, 11, 40, 38, 55]
Embeddingレイヤ
トークン数は「148」、ベクトルサイズは「512」次元。
(embedding): Embedding(148, 512) # (n_symbols, symbols_embedding_dim)
アウトプットの形状は下記となる。
[batch_size, seq_len, 512] # --> Transpose(1, 2) [batch_size, 512, seq_len]
encoderレイヤ
5文字ずつ畳み込みを3回繰り返して、Bi-LSTM。
(encoder): Encoder( (convolutions): ModuleList( (0): Sequential( (0): ConvNorm( (conv): Conv1d(in_channels=512, out_channels=512, kernel_size=(5,), stride=(1,), padding=(2,)) ) (1): BatchNorm1d(num_features=512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) (1): Sequential( 省略 ) (2): Sequential( 省略 ) ) (lstm): LSTM(input_size=512, hidden_size=256, batch_first=True, bidirectional=True) )
アウトプットの形状は下記となる。
[batch_size, 512, seq_len]
Decoderレイヤ
Decoderの最初の入力として、値がALLゼロのをTensorを使う。
(1, batch_size, 80)
これをlog-mel spectrogramのTensorと結合する。
# decoder_inputs.shape (1 + frame_len, batch_size, 80)
Prenet(Linear変換2回)を通した後のTensor。
# decoder_inputs.shape (1 + frame_len, batch_size, 256)
上記の「decoder_inputs」に対して、frame分、ループを回す。
1回のループにおける処理を図示すると下記のとおり(丸枠がTensor、角枠が演算)
"B"は「batch_size」を表す
「attention_weights」と「attention_context」は次ループでのインプットとして使用する。
Attentionに関しては、queryが「log-mel spectrum」(*)、memoryが「テキスト文字列」(Encode結果)に該当する。
(*)1frame分なので、「spectrogram」ではなく、「spectrum」としている