Introduction
augmentation 기법은 데이터에 약간의 변화(원래 데이터의 특성을 잃지 않을 정도로)를 주는 기법이다. augmentation을 사용하므로써 한정적인 데이터를 늘려주는 효과를 볼 수도 있고 딥러닝 모델이 학습 데이터에 대해 overfitting되는 것도 막아주는 효과를 볼 수 있다. 그래서 대부분의 Task (필자가 알고있는 Speech, NLP, vision)에서 data augmentation 기법을 사용하고 있다.
augmentation 기법은 self-supervised learning에서 필수로 필요한 기법 중 하나이다. 기본적으로 self-supervised learning은 supervised learning과 다르게 '정답'이라는 label이 없는 상태에서 학습을 진행한다. 즉 data로만 학습을 하는 방식이라는 것이다. self-supervised learning은 unsupervised learning은 아니기 때문에 스스로 data에 대한 representation을 추출해내야하는데, 이때 data와 유사한 data'를 만들어낼 수 있는 augmentation 기법을 사용한다. 좀더 자세한 내용은 self-supervised learning에 대해 설명할때 설명하도록 하겠다.
일반적으로 음성인식, 화자분류 등의 여러가지 Speech task는 음원을 입력으로 받으면 무조건 'spectrogram' 으로 변환하여 사용한다. 즉 handcraft 방식으로 음원에 있는 representation을 추출해서 모델에 입력으로 사용하는 방식을 많이 사용한다. (이유는 waveform은 1차원의 데이터라서 CNN으로 처리하기도 애매하고 대부분의 Speech task는 vision의 기술을 차용해서 사용하는 경우가 많은데 1차원이면 대입하기도 까다롭기 때문이라고 생각한다. 그리고 1차원에서 representation을 추출하기는 좀 어렵다랄까 라는 필자의 생각) 그렇다고 해서 waveform에서 representation을 직접적으로 추출하려는 시도가 없는 것은 아니다. wav2vec, vq-wav2vec, wav2vec2.0에서 성공적으로 representation을 추출할 수 있다는 가능성을 보여줬다고 생각한다 (필자는 바로 이 부분에서 self-supervised learning의 매력에 완전 푹 빠져서 헤어나오지 못하고 이쪽부분을 개미핥기처럼 파고 있다).
그래서 waveform으로부터 직접 augmentation을 할 수 있는 방식을 소개/정리하려고 한다. 참고한 논문은 Data Augmenting Contrastive Learning of Speech Representations in the Time Domain, E. Kharitonov, M. Rivière, G. Synnaeve, L. Wolf, P.-E. Mazaré, M. Douze, E. Dupoux. [arxiv] 이다. Time domain 관점에서 waveform을 augmentation하는 방식이다 (아무래도 waveform 상태에서 frequency를 augment하는것은 여럽지 않을까하는 필자의 생각)
Quick Start
git clone https://github.com/facebookresearch/WavAugment.git && cd WavAugment && python setup.py develop
이것만 하면 된다. git clone으로 프로젝트 땡겨오고 setup.py로 라이브러리화 시키면 끝이다.
x, sr = torchaudio.load('./dataset/00001.wav')
ipd.Audio(x, rate=sr)
먼저 음원을 불러오고, 음원을 한번 들어본다. augmentation이 어떻게 되는지 한번에 확인하는 방법은 듣고, 보고는 것이 명확하다고 생각한다.
import augment
effect_chain = augment.EffectChain().pitch(100).rate(16_000)
import augment를 하면 위에서 라이브러리화시킨 프로젝트를 사용할 수 있다. augment라이브러리는 EffectChain이라는 object를 기반으로 만들어져있어서 여기서 여러가지 augment기법들을 사용할 수 있다. 그리고 chaining 기법도 사용할 수 있다고 한다.
Pitch Randomization
음원에서 음정의 높이를 조절하는 방식이다. 음정을 낮게 ~~~~ 높게 조절할 수 있으며 랜덤으로 pitch값을 조절해서 사용할 수 있다.
# input signal properties
src_info = {'rate': sr}
# output signal properties
target_info = {'channels': 1,
'length': 0, # not known beforehand
'rate': 16_000}
random_pitch = lambda: np.random.randint(-400, 400)
y = augment.EffectChain().pitch(random_pitch).rate(16_000).apply(x, src_info=src_info, target_info=target_info)
ipd.Audio(y, rate=sr)
코드는 램덤으로 -400 ~ 400 사이의 random_pitch를 추출해 적용하는 코드이다. 사용방법은 간단하다. 원하는 augmentation 방법을 메서드로 호출하면 되고 apply()를 통해 실행하면 된다. 코드와 같이 random하게 정해진 범위에서 추출해서 사용해도되고 상수로 때려박아도된다. 취향에 따라서 사용하면 된다.
Time Dropout
음원에서 임의의 한 부분을 blackbox로 지워버리는 방법이다.
y = augment.EffectChain().time_dropout(max_seconds=0.5).apply(x, src_info={'rate': sr})
ipd.Audio(y, rate=sr)
max_seconds 이하의 값으로 time dropout이 발생하게 되며 음원이 재생되다 임의의 한 구간에서 아무소리도 안나왔다 다시 소리가 나오는 형태로 처리된다. max_seconds는 sec단위라는 것을 명심할 필요가 있다. time dropout은 spec augmentation에서 time domain을 제거하는 것과 동일한 효과를 얻는데, 음원 길이에 비해 너무 많이 지워버리면 역효과가 날 수 있다.
Additive Noise
음원에 noise를 추가하는 기법이다. noise를 추가하기 위해서는 MUSAN과 같은 노이즈 데이터베이스가 필요하다고 한다.
noise_generator = lambda: torch.zeros_like(x).uniform_()
y = augment.EffectChain().additive_noise(noise_generator, snr=15).apply(x, src_info={'rate': sr})
ipd.Audio(y, rate=sr)
원래는 MUSAN과 같은 데이터베이스에서 음원을 추출해서 noise를 추가해주어야 하지만, 샘플 프로젝트에서는 가볍게 x의 길이와 똑같은 noise를 임의로 생성해서 사용하였다. additive_noize에 파라미터값으로 noise와 snr 값을 입력하면 된다. snr은 signal-to-noise ratio라고 해서 신호 대 잡음비를 의미한다.즉 잡음의 비율을 의미하는 것이다.
Reverberation
음원에 reverberation 효과를 적용하는 것이다. reverberation 쉽게 말해서 울림? 이라고 생각하면 될 것 같다.
y = augment.EffectChain().reverb(50, 50, 50).channels(1).apply(x, src_info={'rate': sr})
ipd.Audio(y, rate=sr)
reverberation은 벽에 반사되는 신호에 대한 정보를 음원에 포함하는 것으로 room의 크기가 필요하다. 즉 코드에서는 50 * 50 * 50 크기의 room에서 발생되는 잔향(reverberation)을 의미하는 것이다.
Clipping
음원에서 주파수영역을 클리핑하는 방식이다. 쉽게 말해서 일정 주파수 이상은 잘라내는 것이다.
clip_chain = augment.EffectChain().clip(0.25)
y = clip_chain.apply(x, src_info={'rate': sr})
ipd.Audio(y, rate=sr)
사용방법은 위에 설명한 구조와 완전 동일하며 clip 메서드에 파라미터로 ratio를 적어주면 된다.
이외에 64가지의 Effect를 지원한다고 하는데, 사용할것들만 한번씩 다뤄보았다. 그리고 해당 라이브러리는 torch와 sox기반이며 non-batch only CPU 방식이다. 그래서 사용할때 병렬로 사용하는 것이 좋다고 한다. 어차피 Torch의 DataLoader가 multi cpu사용이 가능하기 때문에 그냥 써도 되지 않나 싶다.
Reference
https://github.com/facebookresearch/WavAugment