Monday, January 4, 2016

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

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

소개

음성, 음악신호를 이용해 이러쿵저러쿵~~처리를 하고 머신러닝으로 뚝딱~ 하는 프로그램을 짜고싶다 (짜야한다..)! 그런데,

i) 오디오 신호 처리는 알지만 머신러닝을 몰라요.
OR
ii) 머신러닝은 알지만 오디오 신호 처리는 몰라요.

에 해당하시는 분들을 위해 간단한 포스팅을 씁니다. 예를 들면 아이 울음 소리를 번역하는 어플, 음악에서 자동 기타 코드 인식 등의 경우가 있겠죠.


가정:

- 문제: 아이 울음 소리를 번역하자! 이 아이가 a.배고파서 우는지 b.졸려서 우는지 이 두 가지만 고려.
- 사용 언어: 파이썬.
- 데이타: 아이 울음소리가 녹음된 파일 100개 (1.wav, 2.wav, ..., 100.wav)
- 라벨링: 되어있음. (파일명이 짝수면 배고픔, 홀수면 졸림)

가장 전통적인, 전형적인, 그리고 어지간한 성능을 보여주는 방법인 Feature extraction (특징값 추출) + classifier (분류기)의 조합을 시도해봅시다.
[방법 1] MFCC를 특징값으로 사용 + Logistic regression classifier를 써서 분류 - 가장 간단한 방법입니다.


[방법 1 - 단계a. 특징값 추출 Feature extraction]


* 준비물: 파이썬 패키지: librosa (documentation), 컴퓨터, 두뇌, 시간, 손가락, 공기, 지구 등.

- - 설치방법 생략.

* librosa.core.load

를 써서 오디오 파일을 읽어온다.
> y, sr = librosa.load('data/baby_cry.wav')

- - arguments 설명
- - - sr=22050 : input 샘플링 주파수입니다. 아마도 갖고있는 오디오 파일의 샘플링 주파수는 22050이 아닐 확률이 큽니다. 이렇게 값을 설정해주는 것은 11025 Hz 까지의 값만 써도 된다는 가정을 한 것이죠. 잘 모르시면 그냥 두세요.
- - - mono=True : 스테레오 음원일경우 모노로 바꿔준다는 말입니다. 역시 그냥 두시면 됩니다. 대부분의 경우 모노면 충분합니다. 이 글의 타겟이시면 스테레오 음원이 필요한 경우가 아닐거에요.
- - - offset, duration: 오디오 파일의 특정 구간만 쓰실경우 설정하시면 됩니다. 그러나, 초심자라면 이걸 쓰지 마시구요, 갖고있는 오디오 파일에서 의미있는 구간만 미리 잘라놓으세요. 예를들어 음원이 60초인데 아기 우는 소리가 20~35초에 있다면 그 부분만 남기고 나머지는 버려서 15초로 만들어놓고 쓰시면 됩니다.

* librosa.feature.mfcc

를 써서 오디오 신호를 mfcc로 바꾼다.
> mfcc = librosa.feature.mfcc(y=y, sr=sr)

- - arguments 설명
- - - n_mfcc=20 : mfcc 계수의 개수입니다. mfcc가 가장 활발하게 쓰이는 음성 인식에서는 대략 이 값을 수십개 (20~50)로 설정하고 씁니다. 즉 그정도면 충분하다고 알려져있습니다. 다만 주어진 상황과 목표에 따라 그 값은 다를 수 있습니다. 우선 20으로 두시면 됩니다.
- - mfcc란?
- - mfcc는 음성/음악 인식에서 가장 널리 쓰이는 특징값입니다. 자세한 설명은 위키를 참조.
mfcc 프레임 기반 특징값입니다. 즉, 각 프레임 (대체로 수 십 ms)마다 하나의 mfcc vector가 나오게 됩니다.
위의 코드를 실행하면 mfcc는 2차원 어레이가 할당됩니다. 즉

> print mfcc.shape 

를 하시면 (20, number_of_frames)이 나오게 됩니다.

이제 이 특징값을 써서 분류기를 활용해봅시다.


[방법 1 - 단계b. 분류기 Classifier]


* 분류기 Classifier

분류기란, 말그대로 분류를 해주는 기..;;입니다. 예를 들어, 20차원의 mfcc 벡터를 입력으로 하면 요 애기가 배고파서 우는지, 졸려서 우는지를 알려주는 녀석이죠. 즉 y = f(mfcc) 으로 표현해보면 f( )가 분류기에 해당하고, y는 그 결과입니다. y는 [0, 1] 중에 하나를 고르는걸로 우리가 설정해놓을 수 있죠. 즉 0=배고프다, 1=졸리다. 이렇게 설정해놓고 그에 맞춰서 트레이닝을(기계를, 혹은 알고리즘을 학습시키는 것을) 해 주는 것이죠. 좀 더 일반적으로는

판단 = f(특징값)

으로 쓸 수 있겠죠?
Logistic regression, SVM, decision tree, random forest, neural networks 등 분류기의 종류는 아주아주 많습니다.

* Logistic regression

(거의) 제일! 간단한! 분류기입니다.

*준비물: 파이썬 패키지: scikit-learn

열심히 설치하시면 됩니다.
$ pip install sklearn

* scikit-learn의 linear model의 LogisticRegression

를 쓰겠습니다.  (예제 참고)

1 > from sklearn import linear_model 
2 > logreg = linear_model.LogisticRegression()
3 > logreg.fit(X_train, y_train)
4 > y_test_estimated = logreg.predict(X_test)

요 네 줄의 코드가 핵심입니다. 그러나! 그 전에!

* X_train, y_train, x_test, y_test

머신 러닝 알고리즘의 트레이닝에선 반드시! 교차 검증 (Cross-validation)을 해야합니다.
쉽게말해, 100개의 음악 파일중 짝수는 배고픈, 홀수는 졸린 울음소리였죠? 그렇다면 2,4,6,8,..., 60 까지, 총 30개의 배고픈 울음 소리와 1,3,5,7,...,59까지, 총 30개의 졸린 울음 소리를 모아서 총 60개를 트레이닝 셋으로 두고, 나머지 40개를 테스트 셋으로 두죠. 그게 뭐냐구요? 쉽게 말하면 우리의 알고리즘 학생에게 기계학습을 열심히 시키는데, 1~60까지로 공부를 시키고 (트레이닝), 잘 이해 했는지를 61~100번으로 시험을 보는겁니다 (테스트). 왜 이렇게 하냐면, 이렇게 안하면 다들 시험에 나오는 것만 공부하고, 그래서 시험은 잘 보지만 막상 써먹을 수가 없게 되기 때문입니다.  즉, 이렇게 학습시킨 알고리즘으로 어플을 만들면 진짜로 사용자의 아기가 울었을때는 왜 우는지 전혀 맞출 수 없는거죠. (이걸 과적합/오버피팅/Overfitting이라고 합니다.)
그래서 우린 어떻게 하냐면요,

- 1~100의 wav 파일의 MFCC를 전부 구합니다.
- - 원래는 파일 하나당 여러 프레임이 존재하고, 따라서 파일 하나당 여러 개의 MFCC 벡터가 존재합니다.
- - - 귀찮으니 이걸 평균내서, 파일 하나당 하나의 MFCC 벡터를 만들었다고 합시다. 그러면 우린 총 100개의 MFCC 벡터를 갖고있지요. (n_mfcc=20, 즉 벡터는 20차원이라고 하죠.)
- 또, 아까 말했듯이 짝수는 배고픈 (=0), 홀수는 졸린(=1) 울음 소리에요.
자 이제,

- - - X_train은 60-by-20이 되도록 만드세요. 즉, 각 row는 각각의 mfcc가 되는거죠. 1번파일부터 60번 파일까지 순서대로~
- - - Y_train은 60-by-1 numpy 어레이로 하구요. 즉, 길이가 60인 [1,0,1,0,.....1,0] 이 되겠죠?
- - - X_test는 40-by-20이 됩니다. 여기엔 61번파일부터 100번 파일까지의 mfcc값을 넣습니다.
- - - Y_test는 40-by-1이구, 역시 [1,0,...1,0]인데 길이가 40이죠.
그리고 나서, 위의 코드를 돌리면! 그리고 나서,

5 > print y_test_estimated

를 통해 값을 보셔도 되고, 아무튼 열심히 y_test와 y_test_estimated를 비교하시면 됩니다.

*정리

"MFCC를 특징값으로 사용했고, 60:40으로 train set/test set을 나누었고, logistic regression을 이용해 분류(classification)를 했습니다."
- (MFCC,) training set, test set, logistic regression, classification 이 무엇인지 간략한 개념을 이해하셨으면 성공!
- 과연 방법 2를 쓰게될지는 모르겠습니다만 여튼 도움이 되었으면 좋겠습니다.





24 comments:

  1. 안녕하세요
    청각장애인들을 위한 아기울음 알림 장치를 DIY로 만들어보려 하는 중
    최근우님의 블로그를 보게 되었습니다.

    이 글의 안내에 따라
    MFCC 피쳐들을 뽑아서 평균, 분산, max값을 이용해
    간단한 Neural Network로 아기울음소리를 분류해 보았습니다.
    그러나 테스트 결과, 학습데이터에 없는 몇몇 소리들이
    아기울음으로 잘못 분류되는 경우가 발생했습니다.
    ex)여성 보컬 노래, 여자 흐느끼는 소리 등

    이러한 오작동(?)을 막기위해(혹은 줄이기위해)
    어떤 방법이 있을지 여쭙고 싶습니다.

    ReplyDelete
    Replies
    1. 분류기 선택 등 머신러닝 일반은 http://keunwoochoi.blogspot.co.uk/2016/08/blog-post.html 을 참고하시구요,
      false negative와 false positive중 어떤걸 줄일지 생각해보시구요.
      https://librosa.github.io/librosa/generated/librosa.feature.delta.html 를 참고하셔서 dMFCC, ddMFCC를 추가해보는것도 방법입니다.

      Delete
    2. 정말 감사합니다! 여러가지로 또 테스트를 해봐야겠습니다.

      Delete
  2. 친절히 설명해주셔서 감사합니다!

    ReplyDelete
  3. 1탄, 2탄, 3탄까지 읽게 되었는데요.
    깊이 공부해야할 부분은 요점요점 잘 정리해주셔서 감사합니다.
    잘 참고해서 사용하도록 하겠습니다.
    혹시 GANs를 사용한 tutorial이 있으면 알려주실 수 있을까요?
    영어가 워낙 약해서요 ㅠ.ㅠ

    ReplyDelete
    Replies
    1. 안녕하세요, GAN은 http://jaejunyoo.blogspot.com 유재준님 블로그에 많이 나와있습니다.

      Delete
  4. 안녕하세요. 1탄, 2탄, 3탄 읽으면서 공부하고 있는 학생입니다.
    우선 너무 유익한 블로그를 찾게되어 너무 감사합니다.

    1탄 내용을 보면서 공부하고 있는데요.

    위에
    데이타: 아이 울음소리가 녹음된 파일 100개 (1.wav, 2.wav, ..., 100.wav)
    이 파일을 참고하면서 따라가보려고 여기저기 찾다가 결국 글을 남기게 됬습니다..
    혹시 위 데이터파일은 어디서 찾을수 있을까요ㅠ??

    ReplyDelete
    Replies
    1. 안녕하세요, 반갑습니다. 4탄을 새로 작성했습니다. 일단 애기 우는 소리는 baby crying sound dataset이라고 구글하시면 맨 위에 나오는게 있구요, 4탄은 좀 더 일반적인 경우에 대한 이야기입니다. 참고하세요.

      Delete
  5. 안녕하세요? 음성 처리 공부를 하고 싶던 와중에 이 블로그에서 많은 정보를 얻게 되어 감사합니다다
    1탄을 공부하려고 하는데 baby crying sound dataset 을 검색하니 https://research.google.com/audioset/dataset/baby_cry_infant_cry.html 가 나오는데요.. 비디오 리스트만 나오는데 크롤링해야하나요?

    ReplyDelete
    Replies
    1. 안녕하세요. 오디오셋은 말씀하신대로 직접 비디오를 크롤링해야합니다. pytube 같은걸 쓰시면 됩니다.

      Delete
  6. 안녕하세요. 음성처리에 대한 중요한 정보들을 블로그를 통해 감사히 공부하고 있는 학생입니다.
    MFCC의 계수와 벡터의 값들이 무엇을 의미하고 있는 것인지 알수있을까요? 또 관련 정보가 있는 링크도 감사하겠습니다!

    ReplyDelete
    Replies
    1. 안녕하세요, 질문하신 내용은 다른곳에서 많이 찾아볼수 있는 내용이라 제가 따로 정리하지는 않겠습니다.

      Delete
  7. 안녕하세요 mfcc를 20차수로 뽑는다면 X_train을 60 by 20으로 만든다고 하셨는데,
    실제로 60 by 20 by (number of frames)로 3차원 배열이 되지 않는지요?
    그렇게되면 2차원만 허용하는 SVM과 같은 분류기는 사용하지 못하는 건가요?
    아니면, SVM의 차원을 확장해서 사용하는 방법을 얼핏 보았는데, 그러한 방법으로 3차원배열을 사용해야하나요??

    ReplyDelete
    Replies
    1. 안녕하세요,
      1. 머신러닝에서 적용하는 '차원'을 오해하고계신것 같네요. 20차수는 20차원 벡터가 되고, 60 by 20 행렬 (혹은 2'차원' 어레이)는 60 x 20 = (1200차원 벡터로 reshape이 가능한) 1200 차원 데이터입니다.
      2. SVM은 2차원만 허용하지 않습니다. 다차원에서 사용 가능합니다. 2차원에서만 사용 가능한 분류기가 있나요? 제가 알고있는 분류기는 전부 다차원 벡터에 적용 가능합니다.

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

    ReplyDelete
  9. 안녕하세요 글 쓰신 것에서는 이항분류를 사용하셨는데 다중분류를 하려면 Logisticregression 대신MLPclassifier로 fit하면 되는건가요? 그런데 이 때는 Y 데이터를 문자로 입력하나요? 머신러닝이 처음이라서요.. ㅜㅜ

    ReplyDelete
    Replies
    1. 1. 넵.
      2. one-hot-vector를 찾아보시면 됩니다.

      Delete
    2. 답변해주셔서 정말 감사합니다.

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

    ReplyDelete
  11. 안녕하세요 머신러닝을 공부하는 학생입니다. 머신러닝의 초보라서 아직 깊게 알지는 못하지만 파이썬을 이용하여 사람 A,B의 데이터 수집을 통해서 음성인식으로 사람 A.B를 구분할 수 있도록 하는 연구를 해보려고 하는데 가능 할까요????

    ReplyDelete
    Replies
    1. 네 화자인식, 화자분류 등의 키워드로 찾아보시죠.

      Delete
  12. 안녕하세요 머신러닝을 처음 접하는 학생입니다. 제가 피아노를 치면 피아노 원곡과 비교하여 음정,박자 비교를 하여 알려주는 프로그램을 짜려고하는데 3~4분정도의 음악도 머신러닝을 하여 비교를 할 수 있을까요?? 아무리 찾아도 안나와서 이렇게 질문을 올립니다...ㅠㅠ

    ReplyDelete
  13. 안녕하세요. 이전에 개와 고양이를 분류하는 간단한 프로그램을 만들어 본 적이 있는데, 그 때는 이미지 사이즈를 28x28로 전처리를 했는데요. 데이터 수가 60개라면 쉐이프는 60, 28, 28이 됐었습니다. 그런데 음성 데이터의 경우 60, 20, 마지막 3차원은 음성 데이터에 따라서 숫자가 제각각이 되더라구요. 혹시 음성 데이터의 경우 어떻게 전처리를 하는 지 알 수 있을까요?

    ReplyDelete
  14. 안녕하세요. 혹시 A라는 음성파일이있는데,
    가지고 있는 B,C,D 중에서 A라는 음성파일과 목소리톤이 비슷한 파일을 가장 비슷한 순서대로 정렬이나 찾을수 있을까요??

    ReplyDelete