ichou1のブログ

主に音声認識、時々、データ分析のことを書く

日銀のEFT買い入れを可視化してみる(2021年3月5日までのデータ)

3月4日、5日と、2日連続で日銀によるETFの買入れ(500億円超)があった。

指数連動型上場投資信託受益権(ETF)および不動産投資法人投資口(J-REIT)の買入結果


日銀のETF買入れと日経平均株価の関係をプロットしてみる。

株価の下降局面で買い支えているのが確認できる。
(点のプロットが株価(終値)、紫のバーが買入額を示す)

2021年3月5日まで(過去6ヶ月)

f:id:ichou1:20210307102723p:plain


2021年3月5日まで(過去3ヶ月)

f:id:ichou1:20210307102814p:plain


下記URLで公開中。
https://analytics.katakanadojo.tokyo/d/WtlmSAaWz/nikkei?orgId=1&viewPanel=2



また、「2021年3月5日」までの買入れの累計額を出してみる。
対象は、以下2つ。

  • 設備投資および人材投資に積極的に取り組んでいる企業を支援するためのETF
  • 上記以外のETF
> select sum(amount_bil) from etf_kai
name: etf_kai
time                 sum
----                 ---
1970-01-01T00:00:00Z 358414

35兆8414億円。

音声合成メモ(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、角枠が演算)
f:id:ichou1:20201012082538p:plain
"B"は「batch_size」を表す

「attention_weights」と「attention_context」は次ループでのインプットとして使用する。

Attentionに関しては、queryが「log-mel spectrum」(*)、memoryが「テキスト文字列」(Encode結果)に該当する。

(*)1frame分なので、「spectrogram」ではなく、「spectrum」としている

音声合成メモ(tacotron2その3)

内部処理を見てみる。

今回は、音声ファイルから特徴量(log-mel spectrogram)を求めるところまで。

ソースでは、「mel_spectrogram」関数が該当する。
https://github.com/NVIDIA/tacotron2/blob/master/layers.py#L63

    def mel_spectrogram(self, y):
        """Computes mel-spectrograms from a batch of waves
        PARAMS
        ------
        y: Variable(torch.FloatTensor) with shape (B, T) in range [-1, 1]

        RETURNS
        -------
        mel_output: torch.FloatTensor of shape (B, n_mel_channels, T)

「y」にあたる音声ファイル読み込みは「scipy.io.wavfile.read」を使っている。

処理は3つのステップ。

        # 短時間フーリエ変換
        #   filter_length(n_fft) = 1024
        #   hop_length = 256
        #   win_length = 1024
        magnitudes, phases = self.stft_fn.transform(y)
        # 振幅を使う
        magnitudes = magnitudes.data
        # --> (fft_bin , frame)

        # メル周波数変換
        #   n_mel_channels = 80
        mel_output = torch.matmul(self.mel_basis, magnitudes)
        # --> (mel_bin , frame)

        # 対数を取る
        mel_output = self.spectral_normalize(mel_output)

STFTの結果は「振幅」の方を使っている。
(「librosa.feature.melspectrogram」では、STFTの「パワー」を使うので、単純な置き換えはできない)

Tensorを使わない処理に書き換えると下記のとおり。

# Load
data, sr = librosa.load(
    audio_path,
    sr=22050)

# STFT
S_F = librosa.stft(data,
                   n_fft=1024,
                   win_length=1024,
                   hop_length=256)

# 複素数平面におけるユークリッド距離(振幅)
amp = np.abs(S_F)
# --> (513, frame)

# Filterbank matrix
mel_basis = librosa.filters.mel(sr=sr,
                                n_fft=1024,
                                n_mels=80,
                                fmin=0.0,
                                fmax=8000.0)
# --> (80, 513)

# FFT bins into Mel-frequency bins
mel = np.matmul(mel_basis, amp)
# --> (80, flame)

# log-mel
log_mel = np.log(np.clip(mel, 1e-5, None))

音声認識や音声合成に出てくる用語のまとめ

(随時、更新します)

スペクトラム」と「スペクトログラム」の違い

時間領域で標本化されたデータはチャンクに分けられ(チャンクは一般にオーバーラップさせる)、チャンク毎にフーリエ変換を施す。
各チャンクの変換結果が、ある時間における全周波数成分のグラフ(スペクトラム)となるので、これを時系列に並べるとスペクトログラムが完成する。

wikiより引用(一部、加工)

単語 言語 次元(x, y, z)
spectrum 英語 2次元(周波数、信号成分の強さ)
spectrogram 英語 3次元(時間、周波数、信号成分の強さ)



スペクトラム」と「スペクトル」の違い

同じ意味。

言語 単語 品詞
英語 spectrum 名詞
spectral 形容詞
フランス語 spectre 名詞



「振幅」、「パワー」、「magnitude」、「Energy」の違い

フーリエ変換で求まった「実数」と「虚数」に対して、「実数の二乗」と「虚数の二乗」を足す。
平方根をとる前の状態を「power spectrum」、平方根をとった後の状態を「amplitude spectrum」として区別する。

用語 類似表現 意味 備考
amplitude spectrum magnitude 振幅
power spectrum Energy パワー 振幅の二乗

音声合成メモ(tacotron2その2)

内部でどのような処理を行っているのか見てみる。

論文より(Encoder/Decoderの枠線を加筆)
f:id:ichou1:20200920112952p:plain


「torchsummaryX」を使って、モデルのサマリを出力してみる。

各レイヤ構成

Embedding
(embedding): Embedding(148, 512)
Encoder

「BatchNorm1d」レイヤに関しては、1行におさまらないので"affine=True, track_running_stats=True"を省略。

(encoder): Encoder(
  (convolutions): ModuleList(
    (0): Sequential(
      (0): ConvNorm(
        (conv): Conv1d(512, 512, kernel_size=(5,), stride=(1,), padding=(2,))
      )
      (1): BatchNorm1d(512, eps=1e-05, momentum=0.1, ...)
    )
    (1): Sequential(
      (0): ConvNorm(
        (conv): Conv1d(512, 512, kernel_size=(5,), stride=(1,), padding=(2,))
      )
      (1): BatchNorm1d(512, eps=1e-05, momentum=0.1, ...)
    )
    (2): Sequential(
      (0): ConvNorm(
        (conv): Conv1d(512, 512, kernel_size=(5,), stride=(1,), padding=(2,))
      )
      (1): BatchNorm1d(512, eps=1e-05, momentum=0.1, ...)
    )
  )
  (lstm): LSTM(512, 256, batch_first=True, bidirectional=True)
)
Decoder
(decoder): Decoder(
  (prenet): Prenet(
    (layers): ModuleList(
      (0): LinearNorm(
        (linear_layer): Linear(in_features=80, out_features=256, bias=False)
      )
      (1): LinearNorm(
        (linear_layer): Linear(in_features=256, out_features=256, bias=False)
      )
    )
  )
  (attention_rnn): LSTMCell(768, 1024)
  (attention_layer): Attention(
    (query_layer): LinearNorm(
      (linear_layer): Linear(in_features=1024, out_features=128, bias=False)
    )
    (memory_layer): LinearNorm(
      (linear_layer): Linear(in_features=512, out_features=128, bias=False)
    )
    (v): LinearNorm(
      (linear_layer): Linear(in_features=128, out_features=1, bias=False)
    )
    (location_layer): LocationLayer(
      (location_conv): ConvNorm(
        (conv): Conv1d(2, 32, kernel_size=(31,), stride=(1,), padding=(15,), bias=False)
      )
      (location_dense): LinearNorm(
        (linear_layer): Linear(in_features=32, out_features=128, bias=False)
      )
    )
  )
  (decoder_rnn): LSTMCell(1536, 1024, bias=1)
  (linear_projection): LinearNorm(
    (linear_layer): Linear(in_features=1536, out_features=80, bias=True)
  )
  (gate_layer): LinearNorm(
    (linear_layer): Linear(in_features=1536, out_features=1, bias=True)
  )
)
Postnet
(postnet): Postnet(
  (convolutions): ModuleList(
    (0): Sequential(
      (0): ConvNorm(
        (conv): Conv1d(80, 512, kernel_size=(5,), stride=(1,), padding=(2,))
      )
      (1): BatchNorm1d(512, eps=1e-05, momentum=0.1, ...)
    )
    (1): Sequential(
      (0): ConvNorm(
        (conv): Conv1d(512, 512, kernel_size=(5,), stride=(1,), padding=(2,))
      )
      (1): BatchNorm1d(512, eps=1e-05, momentum=0.1, ...)
    )
    (2): Sequential(
      (0): ConvNorm(
        (conv): Conv1d(512, 512, kernel_size=(5,), stride=(1,), padding=(2,))
      )
      (1): BatchNorm1d(512, eps=1e-05, momentum=0.1, ...)
    )
    (3): Sequential(
      (0): ConvNorm(
        (conv): Conv1d(512, 512, kernel_size=(5,), stride=(1,), padding=(2,))
      )
      (1): BatchNorm1d(512, eps=1e-05, momentum=0.1, ...)
    )
    (4): Sequential(
      (0): ConvNorm(
        (conv): Conv1d(512, 80, kernel_size=(5,), stride=(1,), padding=(2,))
      )
      (1): BatchNorm1d(80, eps=1e-05, momentum=0.1, ...)
    )
  )
)

各レイヤのOutput Shape

Embedding
Layer                                    Output Shape              
--------------------------------------   --------------------------
0_embedding                              [batch_size, max_len, 512]
Encoder
Layer                                    Output Shape              
--------------------------------------   --------------------------
1_encoder.convolutions.0.0.Conv1d_conv   [batch_size, 512, max_len]
2_encoder.convolutions.0.BatchNorm1d_1   [batch_size, 512, max_len]
3_encoder.convolutions.1.0.Conv1d_conv   [batch_size, 512, max_len]
4_encoder.convolutions.1.BatchNorm1d_1   [batch_size, 512, max_len]
5_encoder.convolutions.2.0.Conv1d_conv   [batch_size, 512, max_len]
6_encoder.convolutions.2.BatchNorm1d_1   [batch_size, 512, max_len]
7_encoder.LSTM_lstm                               [batch_size, 512]
Decoder

「batch_size」 が 「64」、「max_len」が「164」であったとする。

Layer                                                                      Output Shape              
-------------------------------------------------------------------------  --------------
8_decoder.prenet.layers.0.Linear_linear_layer                              [870, 64, 256]
9_decoder.prenet.layers.1.Linear_linear_layer                              [870, 64, 256]
10_decoder.attention_layer.memory_layer.Linear_linear_layer                  [64, 1, 128]
Layer                                                                      Output Shape              
-------------------------------------------------------------------------  --------------
11_decoder.LSTMCell_attention_rnn                                              [64, 1024]  
12_decoder.attention_layer.query_layer.Linear_linear_layer                   [64, 1, 128]  
13_decoder.attention_layer.location_layer.location_conv.Conv1d_conv           [64, 32, 1]  
14_decoder.attention_layer.location_layer.location_dense.Linear_linear_layer [64, 1, 128]  
15_decoder.attention_layer.v.Linear_linear_layer                               [64, 1, 1]  
16_decoder.LSTMCell_decoder_rnn                                                [64, 1024]  
17_decoder.linear_projection.Linear_linear_layer                                 [64, 80]  
18_decoder.gate_layer.Linear_linear_layer                                         [64, 1]

上記を1ブロックとして、「869」ブロック、続く。

Layer                                                                      Output Shape              
-------------------------------------------------------------------------  --------------
6955_decoder.LSTMCell_attention_rnn                                            [64, 1024]
6956_decoder.attention_layer.query_layer.Linear_linear_layer                 [64, 1, 128]
6957_decoder.attention_layer.location_layer.location_conv.Conv1d_conv         [64, 32, 1]
6958_decoder.attention_layer.location_layer.location_dense.Linear_linear_... [64, 1, 128]
6959_decoder.attention_layer.v.Linear_linear_layer                             [64, 1, 1]
6960_decoder.LSTMCell_decoder_rnn                                              [64, 1024]
6961_decoder.linear_projection.Linear_linear_layer                               [64, 80]
6962_decoder.gate_layer.Linear_linear_layer                                       [64, 1]
Postnet
Layer                                               Output Shape              
-----------------------------------------           ----------------------
6963_postnet.convolutions.0.0.Conv1d_conv           [batch_size, 512, 869]   
6964_postnet.convolutions.0.BatchNorm1d_1           [batch_size, 512, 869]   
6965_postnet.convolutions.1.0.Conv1d_conv           [batch_size, 512, 869]   
6966_postnet.convolutions.1.BatchNorm1d_1           [batch_size, 512, 869]   
6967_postnet.convolutions.2.0.Conv1d_conv           [batch_size, 512, 869]   
6968_postnet.convolutions.2.BatchNorm1d_1           [batch_size, 512, 869]   
6969_postnet.convolutions.3.0.Conv1d_conv           [batch_size, 512, 869]   
6970_postnet.convolutions.3.BatchNorm1d_1           [batch_size, 512, 869]   
6971_postnet.convolutions.4.0.Conv1d_conv            [batch_size, 80, 869]   
6972_postnet.convolutions.4.BatchNorm1d_1            [batch_size, 80, 869]   

音声合成メモ(tacotron2その1)

NVIDIAのtacotron2を試してみる。

GitHub - NVIDIA/tacotron2: Tacotron 2 - PyTorch implementation with faster-than-realtime inference

まずは、Pre-trainedモデルを使ってinference(推論)

「ちいさなうなぎやに」という音声を生成してみる。

text = 'chee sanah UNAGI ya knee'

sequence = np.array(text_to_sequence(text, ['english_cleaners']))[None, :]
# --> [[40 45 42 42 11 56 38 51 38 45 11 58 51 38 44 46 11 62 38 11 48 51 42 42]]

sequence = torch.autograd.Variable(
    torch.from_numpy(sequence)).cuda().long()

_, mel_outputs_postnet, _, _ = model.inference(sequence)

with torch.no_grad():
    audio = waveglow.infer(mel_outputs_postnet, sigma=0.666)


駅のアナウンス音声(英語)

text = 'Please stand behind the yellow line'

音声合成メモ(World)その1

音声合成「World」を試してみる。

下記で公開されているATR音素バランス503文の発話データと、
https://ja.osdn.net/projects/galateatalk/releases/22207

パラレルデータとして下記の"綾波音声"データを使用させていただいた。
Scyclone Demo Page

データ1

ちいさなうなぎやに、ねっきのようなものがみなぎる。

左側がGalateaTalk音声データ、右側が綾波音声データ。

f:id:ichou1:20200830082508p:plainf:id:ichou1:20200830082517p:plain

「World」を使った基本周波数の抽出。

f:id:ichou1:20200830083047p:plainf:id:ichou1:20200830083055p:plain

データ2

ひょうげんするのうりょくをみにつけることである。

f:id:ichou1:20200830085825p:plainf:id:ichou1:20200830085812p:plain

f:id:ichou1:20200830090130p:plainf:id:ichou1:20200830090138p:plain


まずは、基本周波数の変換だけで試してみる。

GalateaTalkデータの対数基本周波数に関する平均と分散を計算。

平均: 4.759163479676581 ( 116.64830639534101 [Hz] )
分散: 0.1984692325760092


綾波音声データの対数基本周波数に関する平均と分散を計算。
(2つの音声データだけで計算)

平均: 5.492186212498033 ( 242.78741195064816 [Hz] )
分散: 0.13437581378553115

基本周波数の変換については、下記サイトを参考にさせていただいた。
美少女声への変換と合成. Introduction | by Lento | Medium

変換結果(右側は目標となる綾波音声)

f:id:ichou1:20200830093639p:plainf:id:ichou1:20200830083055p:plain

元データ

基本周波数のみ変換して音声合成

基本周波数の変換+フォルマントSHIFT(1.2)