19
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

データサイエンスAdvent Calendar 2020

Day 6

機械学習における音声データの水増し

Last updated at Posted at 2020-12-05

データの水増し画像ばっかり

音声データの水増し方法について考えよう

出来そうなこと

  • 音量上げ/下げ
  • 音声の引き延ばし/縮め
  • ノイズの付加
  • 時間シフト
  • 音の高さ(ピッチ)の変更
  • 残響付加

Kaggleのこれとか見てると前半の4つくらいはやってるけど、むしろ音声認識みたいな室内で使うような音声モデルを扱いたいなら後半二つこそやるべきだと思う。前半のやつについてはそのままコードを借ります。

データ読み込み

wav.py
import librosa
filename = "unko.wav"
data, _ = librosa.load(filename,sr=16000)

1.音量を変える

もうこれでいいと思う。音量が1.2倍になる

sample.py
data_vol = data * 1.2

ランダムに音量を変えたければこんな感じで良さそう

sample.py
import random
data_vol = data * random.uniform(0.8, 1.2) 

2.音声を伸縮する

つまり早口にしたりゆっくりにしたりする。
これは上のkaggleのリンク先のコードを拝借してます。
rateで何倍速で話すか設定してます。

sample.py
def stretch(data, rate=1):
    input_length = len(data)
    data = librosa.effects.time_stretch(data, rate)
    if len(data)>input_length:
        data = data[:input_length]
    else:
        data = np.pad(data, (0, max(0, input_length - len(data))), "constant")
    return data

data_stretch = stretch(data, rate=random.uniform(0.5, 1.5)) #ランダムデータ伸縮

3.音声をずらす

話しはじめの時間をずらします。
shiftタップ分の音声のスタート地点を後ろにずらして、ずらしてはみ出たぶんの音声は最初にまわります。

sample.py
def time_shift(data,shift):
    data_roll = np.roll(data, shift)
    return data_roll

data_timeshift = time_shift(data,2**10)

4.音の高さを変える

ピッチを変えます。
bins_per_octave=12というのは1オクターブを12に分けてるよってやつです。
12音階はピアノの鍵盤と一緒です。
ここではあんまり関係ないですけど、bins_per_octave=12のときshift

+12:1オクターブ上
-12:1オクターブ下
+7:完全5度
+5:完全4度

に対応します。

sample.py
def pitch_shift(data,sample_rate,shift):
    ret = librosa.effects.pitch_shift(data, sample_rate, shift, bins_per_octave=12, res_type='kaiser_best')
    return ret

data_pitch = pitch_shift(data,16000,random.uniform(-12, 12))

5.ノイズの付加

音声強調ではできるだけ綺麗な音声が望ましいですが、音声認識や識別の場合何かしらのノイズを付与することでデータを増やすことがあります。ここで付与される音声はホワイトノイズが使われることが多いですが、音声の場合画像と違って何もホワイトノイズに囚われる必要はなくて、環境音だったり音楽だったりもノイズとして付与できます。

下ではノイズデータの大きさをnoise_rateで調整して、音声データに比べて長さが足りない場合はリピート再生させることで長さを伸ばしています。

sample.py

noise_data,_ = librosa.load("noise.wav",sr=16000)
def addnoise(data,noise_data,noise_rate):
    if len(data) < len(noise_data):
        ret = data + (noise_data[:len(data)]*noise_rate)
    else:
        while len(noise_data) < len(data):
            noise_data = torch.cat((noise_data,noise_data),0)[:audio_len]
        ret = data + (noise_data[:len(data)]*noise_rate)
    return ret

data_addnoise = addnoise(data,noise_data,1.0)

ホワイトノイズを付与したい場合は次の通り

sample.py
wn = np.random.randn(len(data))
data_wn = data + 0.005*wn

6.響きをつける

音声認識とかの場合、その辺で配布されているような響きのないドライな音声というのはあんまり現実的ではなくて、実際には室内の反響の影響を大きく受けています。学習させるならこの辺こそやった方がいい。

こんな感じにリバーブをシミュレーションしてつけてみるのもいいんですけど、いちいちこんなことしてたらきりないので、「室内 インパルス応答 データ」とかで検索してインパルス応答のwavファイルをいくつか拾ってきて

sample.py
from scipy.signal import fftconvolve

ir_data ,_ = librosa.load("inpulse_responce.wav",sr=16000)
data_riv = fftconvolve(data,ir_data)

こんな感じでやれば響きを付与できます。

実際そんないくつもインパルス応答を用意する必要はないと思うので、ここから4種類くらい壁の吸音率や部屋の大きさの条件を変えてインパルス応答を用意しといて、ランダムに選択する感じでいいと思います。

追記 ラボメンが擬似的にインパルス応答を生成する方法を書いてくれました。神です。
[Qiita]残響曲線から残響フィルタを算出する

終わりに

こんな感じで音響工学的視点でもいろいろ水増しできると思うのでぜひ試してみては。
実際精度は上がります。
それでは〜

19
15
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
19
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?