Friday, March 11, 2016

음성/음악신호+머신러닝 초심자를 위한 가이드 [2편]

음성/음악신호+머신러닝 초심자를 위한 가이드 전체 게시물은 여기를 클릭하세요.

개요

지난번 포스팅 (음성/음악신호+머신러닝 초심자를 위한 가이드 [1편])에서는 아주 간단한 MFCC 추출 - 로지스틱 회귀 분류기를 사용한 예제를 설명드렸습니다. 놀랍게도 제가 2편을 쓰는군요. [1편]은 잘 이해하셨나요? 디지털 신호와 공학 수학에 대한 간단한 배경 지식이 있었다면 잘 이해하셨을겁니다. 이번 [2편]은 [1편]의 확장판입니다.

1편의 구조를 간략히 정리하면 아래와 같습니다.

<구조>
음악,음성신호 입력 --> [전처리] --> [특징값 추출] --> [분류기] --> 결과

<예>
애기가 우는 소리 녹음파일 -->[전처리:애기가 응애응애 하는 구간만 잘라냄] --> [특징값: MFCC] --> [분류기:로지스틱 분류기] --> 배고프다 vs 졸리다 판별

이번엔 각 단계를 좀 더 고도화 할 수 있는지 알아보겠습니다.

전처리

전처리란 말 그대로 데이터를 머신러닝 알고리즘에 넣기 전에 사용에 용이하도록 처리를 해주는 것 입니다. 자동으로 전처리를 해줄 수도 있고, 수동으로 하는 방법도 있겠죠. 전처리는 굉장히 중요합니다. 입력 데이터가 엉망이면 아무리 훌륭한 알고리즘을 짜도 좋은 성능을 장담하지 못합니다. 아니 나쁜 성능을 장담합니다; 오디오 신호의 경우에 전처리 방법은...애기가 응애응애 하는 구간만 쏙 잘라준다.
    • VAD (voice activity detection:음성 탐지)를 쓴다든지, 신호의 크기가 다들 비슷비슷하다면 단순히 프레임의 평균/최대 진폭을 비교한다. 후자의 경우 오디오 편집 툴에서 [노이즈 게이트]를 활용하면 된다.
  • SNR확보: 신호의 잡음을 줄여준다.
    • EQ, 필터: 신호가 존재할 수 있는 주파수 대역을 증폭시키거나 반대로 없는 부분을 자름.
  • 볼륨 정규화: 오디오 신호의 진폭(amplitude)를 최대값 ([-1, 1])로 키워줘서 디지털 신호에 할당된 비트수를 최대한 활용하도록 한다.
등이 있습니다. 그리고 오디오랑 관계 없이 일반적으로 활용되는 전처리 방법은
  • Normalization
  • Whitening (데이터의 분포를 평균을 0, 표준편차를 1로 맞춰준다)
  • PCA - Principle Component Analysis (자세한 설명은 여기!) 를 써서 고차원 데이터를 압축한다
등이 있습니다.
다시 한 번 말씀드리면, 전처리는 정말 중요합니다. 신호가 가지고 있는 정보를 최대한 보존하면서 전체 데이터의 크기를 최소화 해야 효율적으로 연산을 할 수 있습니다. 그리고 정규화 등 데이터의 분포가 일정하지 않으면 성능에 영향을 줄 수 있습니다. 물론 좋지 않은 영향입니다. 만일 전처리 단계에서 처리가 안된다면 특징값 추출을 더욱 훌륭하게 짜야하겠죠.

특징값 추출 (feature extraction)

무지, 무지, 무지 중요합니다. 딥러닝이 대세가 되기 이전의 오디오+머신러닝 연구는 어떻게 하면 특징값 추출하는 방법을 잘 고안해내서 원하는 작업을 할 수 있을까 였습니다.
가이드 1편에서는 고민없이 MFCC를 사용했었죠? MFCC는 활용 범위가 아주 넓습니다. 그러나 언제 써먹을 수 있는지를 구체적으로 알아둬야 하겠죠. 아래 설명드리겠습니다.

  • MFCC
수식은 여기저기 다 나옵니다. 저는 핵심적인 개념과 의미만 설명하겠습니다.
    • 음색(timbre)은 악기 소리나 사람 목소리를 구별할 수 있게 해주는 그야말로 음색의 차이입니다. 흔히 '톤'이라고 표현하기도 하죠.
    • 공학적으로 보면 음색을 좌우하는 하는 아주 중요한 요소는 바로 악기 혹은 목소리의 배음 구조입니다. 같은 '라 - 440Hz'를 쳐도 피아노와 기타의 음색이 다른건 '라' 음은 440Hz뿐만 아니라 880Hz, 1,320Hz, 1,760Hz..등 440*[1,2,3,4,5,6..] Hz 의 주파수로 이루어져있고, 이 주파수의 에너지 비율이 다르기 때문입니다. 이걸 한마디로배음 구조가 다르다고 표현합니다.
    • 얼만큼 다르냐면요, 같은 관악기에서도 이만큼 다릅니다. 
    • 그리고 이 배음구조의 차이는 악기의 구조에 따라 좌우되며,
    • MFCC는 이 배음 구조의 차이를 표현하는 숫자입니다.
MFCC의 특징은,
    • 음정 (음고, pitch)이 변해도 MFCC가 (나름대로) 일정하게 유지된다는 점 입니다. 따라서,
음성 인식, 음악의 장르 분석, 감정 인식 등 다양한 분야에서 MFCC를 활용합니다. 예를 들어 음성을 인식해야 하는데 목소리가 높은 사람이 높은 음으로 '가나다라~' 하는거랑 낮은 목소리로 '가나다라~' 하는거랑 같게 인식이 되어야 하겠죠? 그러니 MFCC는 적합한 특징값이죠.
반대로 음악에서 악기를 연주하면 그 악기의 음표를 그려주는 목적이라고 하면 MFCC는 절대 사용해선 안되겠죠. 음정의 차이를 무시하도록 디자인되었으니까요.

  • 그 외에
    • spectral centroid
    • spectral rolloff
    • zero-crossing
    • spectral flux
    • energy
여기에서 다 열거하기 어려울 만큼 많은 특징값이 있습니다. 우선 각자가 어떤 특징값을 갖는지 잘 알아보시고, 필요하면 구현해서 쓰시기 바랍니다. 그리고 구현이 귀찮은 분들 (==바로 당신..)을 위해 YAAFE, Sonic Annotator 등 좋은 툴이 많이 있습니다.

Bag of Feature: 특징값 가방;모음;덩어리;..

문제가 있습니다. 특징값의 종류가 너무 많아요. 어떤걸 써야 할지, 어떤 것이 효과적인지, 상대적으로 뭐가 더 중요한지 일일이 고민하기가 까다롭습니다. 특징값 추출을 고안한 사람이 주장하는 효과가 실제로 나온다는 보장도 없구요. 으! 열받는다! 그래서... 그래서 좋은 방법이 있습니다.

다 갖다 써!

시간이 지날수록 컴퓨터의 연산량과 메모리는 늘어납니다. 그러니, 그냥, 수많은 특징값을 다 추출해서 전부 때려넣고 알아서 자동으로 중요한 걸 골라서 쓰게 한다면 참 좋겠죠? 아래처럼요.

<새로운 구조>
음악,음성신호 입력 --> [전처리] --> [특징값 왕창 추출] -->[중요한거 골라주셈] --> [분류기] --> 결과

그래서 어느 순간부터 사람들은 이렇게 하기 시작했습니다. 막, 오디오 프레임 하나에 특징값을 수십, 수백개 쓰는거죠. 전 대충 1x1000 벡터로 (즉 프레임당 특징값이 1000개) 쓰는 것 까지 봤습니다. 그러니까, MFCC 20개, dMFCC 20개, ddMFCC 20개, spectral centroid 1개, zero-crossing 1개, ... 이렇게 잔뜩 구해서 얘네들을 쭉- 붙여서 하나의 벡터로 만들어주는 거죠. 이렇게 해서 프레임마다 1x200짜리 벡터가 나왔다고 치죠. 그런데 문제는 우리는 프레임 마다 특징값을 뽑는 것이 아니라 오디오 신호 전체를 표현할 특징값이 필요하거든요. 이것도 방법이 많지만 제일 간단한 방법은 그냥 각자 평균과 분산을 구해주는 겁니다. 그러면 최종적으로는 1x200 평균과 1x200 분산 --> 1x400 벡터가 되겠죠. 그래도 연산량이 남으면 max()를 추가하면 또 200차원 추가요~ (사실 더 좋은 방법이 있습니다만 여기선 생략합니다. 이 논문에서 어떻게 했나 참고하세요.)

그럼 어떻게 중요한걸 골라주냐면, 전처리 섹션에서 언급한
을 쓰는 겁니다! 자세한 설명은 자세한 설명은 여기!를 참고해주세요.

분류기

분류기는 자세히 다루지 않겠습니다. 그러나 분류기를 고르는 법을 알려드릴게요.

"제일 간단한것부터 해보고 성능이 맘에 안들면 더 복잡한 분류기를 써봐라. 그러나 성능이 비슷하다면 반드시 제일 간단한 것을 사용해라. "
네, 오컴의 면도날이죠. 

절대 쓰다가 귀찮아져서가 아닙니다. 

용어


  • 특징값 == feature
  • 분류기 == classifier
  • 추출 == extraction
  • 전처리 == preprocessing


10 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. 혼자서 공부하고 있는 대학생입니다...!

    학과 관련 공부에 큰 도움이 되고 있습니다. 감사합니다...!

    읽다가 특징값에 대해서 궁금한게 생겼는데

    제가 7음계를 구분하는 MLP모델을 만드려 하는데

    위의 MFCC의 특징 값으로는 특정 음정에 대해서 특징을 잡아내지 못하고

    여러가지 소리들의 같은 음 (예를들어 그랜드피아노의 C4와 어쿠스틱기타의 C4)이 주파수 대역이 다르다면

    같은 음역대의 특징으로 인식하는 방법의 다른 해법이 있는지 궁금합니다...!

    ReplyDelete
    Replies
    1. 안녕하세요. 말씀하신것은 pitch detection입니다. 악기에 따른 주파수 응답 차이는 무시하면서 fundamental frequency에만 반응하는 분류기를 설계하시는거구요. 방법은 너무 많이 있는데 일단 pitch class profile (=chromagram)을 찾아보시죠.

      Delete
  3. 안녕하세요, 공부하다가 발견하게 되어 포스팅 글들을 잘 읽고 있습니다. 저는 시트콤 오디오 파일을 읽어들여 특정부분에서 발생하는 게스트 웃음소리들을 detect/remove하고 싶은데요. 이럴 경우 글쓴이님께서 제시하는 방법으로도 가능한것인지 궁금합니다.

    한가지 더 궁금한점이 있는데 오디오 파일에서 주인공이 특정 단어를 강조할때 피치톤이 달라질 것같은데 여기서 그 단어들을 뽑아낼 수 있는 방법도 있나요?

    감사합니다.!

    ReplyDelete
    Replies
    1. 안녕하세요, 웃음소리 탐지는 포스팅과 관련이 있는 내용이고 그렇게 어려울것같지 않으나 제거하는일은 매우 어려울것같습니다. 두번째 질문은 정확히 어떤 문제를 말씀하시는건지 이해하지 못했습니다.

      Delete
  4. This comment has been removed by the author.

    ReplyDelete
  5. This comment has been removed by the author.

    ReplyDelete
  6. 안녕하세요,포스팅 항상 잘 보고있습니다! 위험소리 분류(아기울음소리,소방벨,경적 등등)를 하고싶은데 가이드를 참고하면서 mfcc로 특징값을 추출하고 svm으로 분류를 해보았습니다. 일단 아기울음소리와 소방벨을 분류해봤는데 소방벨은 99%로 예측되지만 아기울음소리는 3%밖에 안되더라구요..원인이 뭘까요..?추출기가 적절하지 않아서라면 어떤 추출기를 사용하는게 좋을까요?그리고 mfcc 돌렸을 때,한 파일에 길이가 13인 행벡터가 50개 들어있다고 치면 50개 각각을 svm에 train시켰는데 찜찜했었거든요..혹시 포스팅에서 언급하신게 한 파일이라면 그 50개의 프레임(?)을 평균,분산시켜서 사용하라는 뜻인가요??그리고 혹시 자바 기반인 특징값 추출 라이브러리 괜찮은 것이 있을까요??

    ReplyDelete
    Replies
    1. 안녕하세요.
      1. 특정 클래스가 분류하기 더 어려운건 지극히 당연히 일어날 수 있는 일입니다.
      2. 다양한 분류기가 어떤 분포에서 어떻게 작동하는지 알아보시고 주어진 문제(소방벨과 아기울음소리)의 분포를 파악해보셔요.
      3. 네, 50개 프레임의 평균 분산이 맞습니다. 그러나 길이가 다를수있고, 백그라운드가 다를 수 있어서 쉬운 문제는 아니죠.
      4. 노파심에, 같은 파일에서 뽑은 프레임은 train/test에 섞여서 들어가면 안됩니다.
      5. https://github.com/JorenSix/TarsosDSP 보시죠. 부족하지만 그나마 괜찮아보이네요.

      Delete
  7. 안녕하십니까! 가이드를 보고 상당히 도움이 많이 됐습니다!! 그런데 궁금한게 있어서 몇가지 여쭤보고싶습니다!
    저희가 아기울음소리만 감지해서 진동으로 알려주는걸 개
    발 할 예정입니다. 저희는 따로 분류 안하고 울음소리만 나도 감지할 수 있게끔 만들고자 합니다 그러면 여기서 분류기를 안 거치고 특정값만 추출해서 나온 아웃풋을 이용하여 안드로이드 스튜디오에 접목하면 되는건가요?

    ReplyDelete