파이썬 음성 노이즈 제거 - paisseon eumseong noijeu jegeo

음성인식을 함에 있어서 굉장히 큰 딜레마에 빠지게 되었는데요..

단순하게 생각했을 때 음성인식 결과가 좋으려면 어떻게 해야 할까요?

1. 음성인식(STT) 러닝 데이터가 많아야 한다.

2. 깨끗한 음원 파일을 이용해 음성인식(STT)을 한다.

저는 개발 중인 입장에서 이렇게 두 가지의 추론을 하고 있습니다.

하지만 현실적으로 봤을 때.

노이즈 제거는 어쨌거나 음원파일을 손실하게 되어서

음성인식에 나쁜 결과를 가져다 줄 수도 있는데요!

뭔가 가장 기능적으로 우수한 합의점을 찾는 것이 숙제인 것 같습니다.

오늘은 2에 해당하는 깨끗한 음원파일을 만들어 보려고 노력했던 결과물들을 소개할 껀데요.

바로 디노이즈(denoise) 관련 러닝 과정입니다.

몇 가지 방법들이 있었는데 음 .. 3가지 정도 추천을 해드릴 예정입니다!

먼저 오늘은 첫번째 디노이즈 러닝 툴

"RNNOISE"

입니다.

RNNOISE의 가장 큰 장점은

빠르다! 입니다.

물론 더 빠른 툴도 있습니다만. 성능 대비!

빠르다! 

RNNOISE의 원리와 세부 내용을 알고 싶으신 분은 이쪽에서

간단하게 설명을 드리자면

RNNOISE의 가장 큰 장점은 

머신러닝을 통해 얻은 노이즈 결과를 C 소스코드로 추출해 내서

빌드를 하는 것인데요!

그렇기 때문에 python 소스코드와는 비교도 안되게 빠른 장점이 있습니다.

자 그럼 설치해서 사용해 보도록 하겠습니다!

먼저 소스코드는 이쪽에 있습니다.

https://github.com/xiph/rnnoise

github에서 소스코드를 다운로드하시면 간략한 설명이 있는데요!

RNNoise is a noise suppression library based on a recurrent neural network.

To compile, just type:
% ./autogen.sh
% ./configure
% make

Optionally:
% make install

While it is meant to be used as a library, a simple command-line tool is
provided as an example. It operates on RAW 16-bit (machine endian) mono
PCM files sampled at 48 kHz. It can be used as:

./examples/rnnoise_demo <number of channels> <maximum attenuation> < input.raw > output.raw

The output is also a 16-bit raw PCM file.

이렇게 지금 다운받을 수 있는 소스코드를 가지고 빌드를 해서 사용하는 방법이 나와있습니다.

만약 노이즈 데이터를 따로 구할 여력이 안 되는 분이나,

간단하게 테스트만 해보실 분들은 저렇게 빌드해서 사용을 하시면 되는데요!

키 포인트는 기존에 있는 코드는 48000 Hz sample에서 동작하도록 되어있으니 참고해주시고요

저는 노이즈 데이터를 수집해서 러닝 후 러닝 한 데이터를 이용해 KALDI의 STT 데이터 스펙

16bit 16000Hz의 오디오의 노이즈 제거하는 과정을 설명해드릴 겁니다.

자 먼저 git clone을 이용해 소스코드를 다운로드 받습니다.

파이썬 음성 노이즈 제거 - paisseon eumseong noijeu jegeo
파이썬 음성 노이즈 제거 - paisseon eumseong noijeu jegeo

자 이렇게 다운로드 받은 후에 

아래와 같이 작업하시면 되는데 몇 가지 주의사항이 있습니다!!

 https://github.com/xiph/rnnoise/blob/master/TRAINING  내용
(1) cd src ; ./compile.sh

(2) ./denoise_training signal.raw noise.raw count > training.f32

    (note the matrix size and replace 500000 87 below)

(3) cd training ; ./bin2hdf5.py ../src/training.f32 500000 87 training.h5

(4) ./rnn_train.py

(5) ./dump_rnn.py weights.hdf5 ../src/rnn_data.c ../src/rnn_data.h

src 디렉터리에서 compile.sh 실행하면 아래와 같이 denoise_training 바이너리가 빌드됩니다!

파이썬 음성 노이즈 제거 - paisseon eumseong noijeu jegeo

그러고 나서 순수하게 사람 목소리만 녹음된 음원파일의 pcm 파일과

노이즈만 있는 파일의 pcm 파일이 필요한데요 !

노이즈 데이터의 경우는 

https://people.xiph.org/~jm/demo/rnnoise/rnnoise_contributions.tar.gz

위 링크에서 6.4G의 파일을 다운로드 받으실 수 있습니다.

이 노이즈 데이터를 모두 16bit의 16000hz mono 스펙의 오디오 파일로 변환합니다.

간단하게 설명드리면 저는 sox를 이용했는데요

스펙에 맞게 변환하는 과정
sox input.wav -b 16 -r 16000 -c 1 output.wav

오디오 파일 합치는 과정

sox *.wav output.wav

이렇게 파이썬으로 스크립트를 작성해서 작업했습니다.

그리고 클린한 음성 녹음 파일은 zeroth에서 제공한 음성파일을 이용했습니다.

파이썬 음성 노이즈 제거 - paisseon eumseong noijeu jegeo

위의 그림에서 보시면 1.4G의 noise 데이터, speech 데이터를 보실 수 있습니다.

 duration은 44739.029313 초로 12시간 반 정도 되는 데이터입니다.

이 데이터를 이제 pcm으로 바꿔줄 건데요!

여기서 잠깐. 느리긴 하지만 간단하게 사용할 수 있는 pcm2wav, wav2pcm, wavinfo 파일을 설치해봅시다

git clone https://github.com/smallmuou/wavutils
파이썬 음성 노이즈 제거 - paisseon eumseong noijeu jegeo

git clone으로 다운르도 받으신 후에 

bin 디렉터리에 보면 세 개의 바이너리가 있는 것을 확인하실 수 있는데요!

이 툴들을 이용해서 wav 파일을 pcm으로 만들어줍니다!

사용법은 아래와 같구요!

저 같은 경우는 바이너리를 /usr/bin 밑에 두고 사용했습니다.

파이썬 음성 노이즈 제거 - paisseon eumseong noijeu jegeo
pcm2wav 사용법
파이썬 음성 노이즈 제거 - paisseon eumseong noijeu jegeo
wav2pcm 사용법

그리고 나서 

./denoise_training signal.raw noise.raw count > training.f32

이걸 실행해주시면 되는데요 

count는 임의로 값을 넣어주셔야 합니다.

보통 데이터의 양에 따라 값이 상이하게 값이 들어가는데요

500000 ~ 50000000 의 값을 넣어줍니다.

저는 50000000을 넣어주어서 결과적으로 

./denoise_training signal.raw noise.raw 50000000 > training.f32

이렇게 진행을 했구요

파이썬 음성 노이즈 제거 - paisseon eumseong noijeu jegeo

 트레이닝을 시작하면 저렇게 아래 숫자가 계속 증가되면서 목표치가 되면 종료하게 됩니다

(시간이 상당히 걸립니다 하루까진 아니구요

기억이 가물가물하지만 4시간 정도?)

그리고 만들어진 파일을 이용해 다음 러닝 과정을 진행합니다.

cd training ; ./bin2hdf5.py ../src/training.f32 50000000 87 training.h5

이 부분은 굉장히 금방 끝나게 됩니다.

이어서 실질적인 러닝 부분

./rnn_train.py

이 부분의 경우 GPU 러닝을 하고 싶으신 분들은 rnn_train.py의 주석 부분을 수정해주셔야 하는데요

해당 부분은 아래와 같습니다.

파이썬 음성 노이즈 제거 - paisseon eumseong noijeu jegeo
rnn_train.py 수정 전
파이썬 음성 노이즈 제거 - paisseon eumseong noijeu jegeo
rnn_train.py 수정 후

그리고 또 한가지

batch 사이즈를 수정해주어야 하는데요!

batch size가 뭐냐!?

sample 데이터 중 한 번에 네트워크에 넘겨주는  데이터의 개수인데요!

보통 2의 n 승으로 적습니다.

2, 4, 16, ....512, 1024 이렇게요!

batch 사이즈를 수정하는 이유는요

수정하지 않으면 너무너무!!!! 너무 느려요

이론적으로 보면

batch 사이즈가 작으면 정확도가 늘어나는데요

제가 테스트해본 결과 RNNOISE에서는 크게 해당이 안 되는 것 같았습니다.

저는 기존 32에서 512로 러닝을 했습니다.

파이썬 음성 노이즈 제거 - paisseon eumseong noijeu jegeo
파이썬 음성 노이즈 제거 - paisseon eumseong noijeu jegeo

이렇게요!

파이썬 음성 노이즈 제거 - paisseon eumseong noijeu jegeo
저는 anaconda를 사용했습니다.

아나콘다 사용법

그리고 나서 rnn_train.py 시작하면

파이썬 음성 노이즈 제거 - paisseon eumseong noijeu jegeo

이렇게 러닝이 진행됩니다 

epoch가 120/120 이 되면 완료된 것입니다!

완료되면 

./dump_rnn.py weights.hdf5 ../src/rnn_data.c ../src/rnn_data orig

이렇게 입력해줍니다.

원래는 아래와 같이 명령어를 치라고 나오는데요 소스코드가 변경되었고 .h에 쓰이는 값이 버그가 있기 때문에

.h에 쓰레기 값이 쓰이는 것을 방지하고자 위와 같이 입력을 해줍니다!(상당히 중요합니다 안 하면 에러남)

(5) ./dump_rnn.py weights.hdf5 ../src/rnn_data.c ../src/rnn_data.h

그러면 

파이썬 음성 노이즈 제거 - paisseon eumseong noijeu jegeo
rnn_data.c 의 소스코드

rnn_data.c에 러닝 결과가 쓰이는데요

이제 아래와 같이 빌드하면 됩니다!

cd /rnnoise
To compile, just type:
% ./autogen.sh
% ./configure
% make

Optionally:
% make install

그러면 examples 디렉터리 하위에 rnnoise_demo 바이너리가 생성됩니다.

파이썬 음성 노이즈 제거 - paisseon eumseong noijeu jegeo

이 바이너리를 이용해서 pcm데이터의 노이즈를 제거해 줄 수 있는데요!

위에서 설명해드린 wavutils을 이용해

16bit 16000hz mono 스펙의 웨이브 파일을 pcm데이터로 변환해 아래와 같이 사용하고 

다시 노이즈가 제거된 pcm 데이터를 wav로 변경해줍니다

wav2pcm input.wav output.pcm

./rnnoise_demo output.pcm output_denoise.pcm

pcm2wav 1 16000 16 output_denoise.pcm output_denoise.wav

이렇게 명령어를 날려주면 노이즈가 싹!

하지만 STT 개선에는 큰 도움은 주지 못했습니다.

다음에는 간단한 디노이즈 오픈소스 두 가지를 소개해드리겠습니다!