音声ファイル特徴量変換(その4)STFT(TensorFlow)
TensorFlowで短時間フーリエ変換(Short-time Fourier Transform)を求めるには、「tf.signal.stft」関数が提供されている。
https://www.tensorflow.org/versions/r1.15/api_docs/python/tf/signal/stft
音声データは「yes」という一秒間の発話データ。
「libROSA」パッケージで計算する方法は以下をご参照。
work-in-progress.hatenablog.com
TensorFlow 1.X系のAPIを使ったコード
import tensorflow as tf from tensorflow.python.ops import io_ops tf.compat.v1.disable_eager_execution() # Audio Data audio_path = 'speech_dataset/yes/0a7c2a8d_nohash_0.wav' with tf.compat.v1.Session(graph=tf.Graph()) as sess: wav_filename_placeholder = tf.compat.v1.placeholder(tf.string, []) wav_loader = io_ops.read_file(wav_filename_placeholder) # Load data, sr = tf.audio.decode_wav(wav_loader, desired_channels=1) # channelの次元を削除 data_ = tf.squeeze(data) # batch_sizeの次元を追加 data__ = tf.expand_dims(data_, axis=0) # Input: A Tensor of [batch_size, num_samples] # mono PCM samples in the range [-1, 1]. stfts = tf.signal.stft(data__, frame_length=480, frame_step=160, fft_length=512) # 振幅を求める spectrograms = tf.abs(stfts) feature = sess.run( spectrograms, feed_dict={wav_filename_placeholder: audio_path} )
今回、試した環境のバージョンは「1.14」
% python -c 'import tensorflow as tf; print(tf.__version__)' 1.14.0
結果を表示させてみる。
print('feature shape: ', feature.shape) print('feature type: ', type(feature))
feature shape: (1, 98, 257) feature type: <class 'numpy.ndarray'>
Tensorの形状は以下のとおり。
# tf.signal.stft # Output shape (batch_size, frame_size, fft_size // 2 + 1)
「libROSA」パッケージを使った場合の形状とは次元の並びが異なる。
# librosa.stft # Output shape (fft_size // 2 + 1, frame_size)
また、パディングの設定により、frame数が変わってくる。
「libROSA」パッケージは「パディングあり」(101 frame)、「TensorFlow API」は「パディングなし」(98frame)
プロットしてみる。
import numpy as np import librosa # 「batch_size」の次元を減らす feature_ = np.squeeze(feature, 0) # 次元を入れ替える (frame, DFT_index) --> (DFT_index, frame) amp = tensor_.transpose(1, 0) # 振幅をデシベルに変換(基準値は「振幅の最大値」) amp_db = librosa.amplitude_to_db(amp, ref=np.max) # plot import matplotlib.pyplot as plt import librosa.display librosa.display.specshow(amp_db, sr=16000, hop_length=160, y_axis='linear', x_axis='time') plt.title('yes/0a7c2a8d_nohash_0.wav') plt.colorbar(format='%+2.0f').set_label('[dB]') plt.ylim(0, 8000) plt.tight_layout() plt.show()
比較してみる。
右側が「libROSA」パッケージを使った結果。
TensorFlow 2.X系のAPIを使ったコード
「TensorFlow 1.X」系は「1.15」で最後になるようなので、「TensorFlow 2.X」系に上げてみる。
pip install --upgrade tensorflow
python -c 'import tensorflow as tf; print(tf.__version__)' 2.1.0
「TensorFlow 2.X」環境下でも先ほどのソードコードは動作するが、「2.X系」に書き直してみる。
import tensorflow as tf from tensorflow.python.ops import io_ops # Audio Data audio_path = 'speech_dataset/yes/0a7c2a8d_nohash_0.wav' # Load Audio File def load_data(filename): wav_loader = io_ops.read_file(filename) data, sr = tf.audio.decode_wav(wav_loader, desired_channels=1) # channelの次元を削除 data_ = tf.squeeze(data) # batch_sizeの次元を追加 data__ = tf.expand_dims(data_, axis=0) return data__, sr # compute STFT def get_stft_spectrogram(data): # Input: A Tensor of [batch_size, num_samples] # mono PCM samples in the range [-1, 1]. stfts = tf.signal.stft(data, frame_length=480, frame_step=160, fft_length=512) # 振幅を求める spectrograms = tf.abs(stfts) return spectrograms # 音声データ読み込み audio_data, sr = load_data(audio_path) # 特徴量を求める feature = get_stft_spectrogram(audio_data)
「TensorFlow 2.X」系では、 「Eager Execution」がデフォルトで有効になる。
# 「Eager Execution」が有効か確認する print(tf.executing_eagerly())
True