Showing posts with label MIR. Show all posts
Showing posts with label MIR. Show all posts

Monday, December 5, 2016

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

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

서문

가이드 3편입니다. 기존 가이드는 1편, 2편을 참고하세요.
모 대학원의 모 분께서 음악 신호와 머신러닝에 대한 질문을 주셨는데 중요한 점을 콕콕콕콕콕콕 집어서 물어보셔서 블로그에 글을 쓰기로 했습니다.

질문-답변 1


음악 인식쪽이 생소하다 보니 일단 먼저 music genre classificaiton(음악,음성신호 입력 --> [전처리] --> [특징값 추출] --> [분류기] --> 결과) 를 주제로 toy porject를 해보려고 합니다. 툴은 librosa를 쓸 예정입니다.

궁금한 점이 몇가지 있는데

1) 혹시 mp3파일이 주어졌을때 전처리를 하고 특징값 추출을 하는 하는 소스코드가 있으시면 공유 가능한가요?

- 상황에 따라 다르지만 대체로 추출과정은 https://github.com/fchollet/keras/blob/master/keras/applications/audio_conv_utils.py#L27 을 참고하시면 됩니다.
여기에서는 mel-spectrogram만 뽑는데, 여기에 다른 추출기를 추가하시면 되겠습니다.

2) 제 계획은 librosa가 제공하는 여러개의 특징을 최대한 많이 사용하고 후에 PCA등으로 후처리를 하려고 하는데, librosa가 제공하는 특징 (http://librosa.github.io/librosa/feature.html)중에 음악 분류에 적합한 특징에는 어떤 것이 있을까요?

- MFCC는 필수고, 그 외에 spectral-시리즈와 zero-crossing + tempo (http://librosa.github.io/librosa/generated/librosa.beat.estimate_tempo.html) 등을 쓰시면 됩니다.
그리고 특징값 추출 전에 http://librosa.github.io/librosa/generated/librosa.decompose.hpss.html 을 사용하셔서 두 채널을 따로 하시면 도움이 될겁니다.

질문-답변 2


지난번에 말씀하신데로 간단한 특징 추출 과정을 수행해보고 있는데, 몇가지 궁금한점이 있습니다. 

1) https://github.com/fchollet/keras/blob/master/keras/applications/audio_conv_utils.py#L27 을 참고하라고 하셔서 소스코드를 살펴봤습니다. 보통 음악 파일들은 3분이상이며, 제각기 길이가 다른데 소스코드에서 음악 파일의 가운데 DURA = 29.12 초 구간만을 프로세스 하더라고요. 이렇게 하는 이유는 각 음악 파일 별로 길이(재생 시간)가 다르지만 같은 크기(차원)의 특징 벡터를 얻기 위함인가요? 그리고 가운데 29초만으로도 충분한 정보가 있다고 가정하고 처리하는건가요?  끝으로 이렇게 가운데 구간을 trim 하는 기법이 일반적인 기법인가요?

- 이유: 맞습니다. 시간에 따른 정보를 어떻게 합치느냐에 따라 다르겠지만 링크의 컨브넷은 입력 신호의 길이를 29.12초로 제한하고 있습니다. 이보다 짧은 경우에는 나머지를 0으로 채워서 입력으로 넣어도 무방하지만 긴 경우에는 적당한 구간을 잘라줘야합니다. 그리고 말씀하신대로 가운데 29초가 충분한 정보가 있다고 가정하는 것입니다. 물론 상황에따라 다를테고, 제가 논문에서 사용한 음원은 기본적으로 30-60초의 '미리듣기'용 음원입니다. 이런 경우엔 사실 어디를 사용하더라도 무방하겠죠.
가운데를 사용하는건 아무래도 가장 단순하고 그러면서도 적당히 작동하는 방법입니다. 그 외에도 대중 가요의 경우 60-120초 사이에 하이라이트 (혹은 chorus, 혹은 싸비..)가 있다고 가정할수도 있구요.  이 외에도 가장 중요한 구간을 뽑아주는 방법를 여러가지로 생각해볼 수 있겠죠. 간단한 방법으로는 frame별로 energy를 계산해서 평균 에너지가 제일 높은 30초를 뽑을수 있겠죠. 보다 복잡한 방법으로는 음악 내 다양한 구간을 잘라주는 알고리즘을  사용한 뒤에 어디가 하이라이트인지 뽑을수도 있구요. 이는 원하시는 성능과 연산량에 따라 결정하시면 됩니다.

2)  음성/음악신호+머신러닝 초심자를 위한 가이드 [2편]을 보면,  프레임 마다 특징값을 뽑는 것이 아니라 오디오 신호 전체를 표현할 특징값을 찾기 위해 평균 및 분산 MAX를 뽑는다고 하는데 혹시 관련 논문 아시면 제목 알려주 실 수 있나요?
그리고 1)질문과 연관지었을 때 제가 음악 처리를 할때, 음악 파일 1개의 전체 구간에 대해서 평균 분산을 구하게 되면 아무래도  정보가 많이 뭉개질것 같더라고요. 그래서 1)번의 코드처럼 아예 처음부터 가운데 구간이 충분히 의미 있다고 가정하고 29.12초의 짧은 구간만을 평균, 분산 등을 이용해서 오디오 레벨 특징을 뽑으려고 하는데  reasonable한 방법인가요?

http://dspace.library.uvic.ca:8080/bitstream/handle/1828/1344/tsap02gtzan.pdf?sequence=1 를 보시면 평균과 분산 등을 사용했습니다. 그 외에도 frame-based feature를 clustering하고 이를 기반으로 quantized count를 사용하는 방법(http://dawenl.github.io/publications/LiangZE15-ccm.pdf)도 있습니다.
그리고 가운데 구간만 사용하는것이 곡 전체를 사용하는 것보다 나을것이라는데 동의합니다.  

3) 특징 추출 시 HPSS를 통해 2채널로 분리한 뒤  특징을 추출하라고 하던데, 예를들면 제가  LIBROSA에서 제공하는 특징들 중   A,B,C 를 추출하려고 한다면, 하나의 음원으로부터 각 채널별로  A,B,C를 추출해서 총 6개(3*2)의 특징을 구하라는 말씀이신가요? 예제들을 잘 보면 어떤 특징은 H채널에서 뽑고, 어떤 특징은 P채널에서 뽑더라고요. (https://github.com/librosa/librosa/blob/master/examples/LibROSA%20demo.ipynb

말씀하신대로 Harmonic + Percussive에서 모든 특징을 다 뽑아도 큰 문제는 없겠지만 가장 relevant한 정보만 뽑는다고 한다면, 각 트랙에 맞춰서 특징값을 골라주는게 좋겠네요. 하모니나 pitch에 관련된 특징값(chroma-어쩌구, ) 은 harmonic 트랙에서 뽑고, rhythm/onset/tempo 등은 percussive 트랙을 이용하시구요. spectral_어쩌구; (spectral centroid, ..)가 좀 애매한데, 얘네들은 분리하기 전 채널을 이용해 추출하는 것이 좋아보입니다.

4) 종종 특징들을 뽑고 아래와 같이  LOG화 시키던데 이렇게 하는것이 일반적인 방법이며, 인식 향상에 도움이 되나요? 
# Convert to log scale (dB). We'll use the peak power as reference.
log_S = librosa.logamplitude(S, ref_power=np.max)
네. 우선 STFT/CQT/Melgram등의 time-frequency representation은 log()를 씌워 데시벨 스케일로 바꿔주는것이 좋습니다. (그 외에도 일반적인 머신러닝에서 하듯 zero-mean unit-variance로 standardisation을 해주는것이 좋을테구요.) 이런 전처리는 인식 향상에 도움이 됩니다. 
5) 음악 인식 분야에서도  CNN을 이용한 기법들이 도입되고 있다고 들었는데, 보통  CNN의  input 은 주로 어떻게 처리해서 주나요? 그리고 혹시 관련 논문을 알려주실 수 있나요?
여러가지 경우가 있습니다.
Pitch와 관련된 정보 추출: CQT를 사용하고 대역폭을 음의 fundamental frequency가 분포할 수 있는 영역으로 제한한다. (대략 30Hz - 3kHz정도가 되겠죠)
리듬관련: STFT나 Mel-spectrogram을 사용한다.  
풀고자 하는 문제가 사람의 musical perception에 관련된 경우 (예: 감정 인식): Mel-spectrogram을 우선적으로 고려하고 STFT도 가능하면 테스트해본다. 주파수 대역은 대략 4kHz - 11K를 고려한다.
잘 모름: 8kHz나 16kHz로 샘플링하고 STFT (n_fft=1024 또는 512)와 Mel-spectrogram (128 bins)를 써본다.
음악이 아니라 음성이 입력이다: Mel-spectrogram을 최우선적으로 고려한다.
음악, 음성이 아니라 '소리'에 관련된 작업이다: STFT를 사용하고 Mel-spectrogram을 고려해본다. 
그리고 이와 관련된 논문은 아직 없습니다. 제가 대략 2-4개월내로 하나 작성하려고 계획중입니다. 

6) 제가 앞으로 해보려는 것은 일단  음원이 주어지면 고정 길이로 음원 구간을  trim  시키고, 이 구간에 대해 여러개의 특징벡터를 추출하려고 해요. 이렇게 하면, 음원에 대해서 (프레임 개수)  X (프레임당 특징 벡터들의 차원의 합)의 행렬이 만들어 질텐데, 음악 장르를 구분하는  task라고 가정하고  CNN 의 input으로서 이 이차원 행렬 그대로 주는게 좋을까요 아니면 2)에서 언급한것처럼 이 2차원 행렬의 프레임별  평균, 분산등을 구해서  1차원 벡터로 차원을 축소 한 뒤 입력으로 주는 것이 좋을까요?

데이터 개수가 충분히 많다면 2차원 데이터를 쓰시고, 그렇지 않으면 1차원 벡터로 입력 데이터의 크기를 줄여야겠죠. 장단점이 있어서 해보기전엔 정하기 어려워보입니다. 



Saturday, August 20, 2016

음악 자동 태거 (auto-tagger): 학습된 컨브넷 공개

깃헙 저장소에 제가 학습시킨 음악 자동 태거를 공개했습니다.
참고하시길 바랍니다.

예제 파일과 음원을 포함하고 있어서 코드만 보셔도 쉽게 이해하실 수 있습니다.

https://github.com/keunwoochoi/music-auto_tagging-keras


Saturday, June 25, 2016

논문 요약 - "Taste Space Versus the World: an Embedding Analysis of Listening Habits and Geography", Joshua Moore et al., ISMIR 2014

개요

  • 논문 다운로드는 여기를 누르세요.
  • 논문은 코넬 대학의 Joshua Moore가 쓴 논문입니다. 저자는 랩 동료인 Shuo Chen과 공저자로 MIR 관련 논문을 여러개 발표했습니다. Shuo Chen은 Markov Embedding을 이용한 플레이리스트 생성 논문을 발표한것이 좀 유명하구요, 지금은 졸업하고 MIR이 아닌 다른 분야에 있다고 하네요. 이 사람들 연구는 대부분 Embedding에 대한 내용입니다.
  • 이 논문은 ICML 2016: Machine learning for music discovery에서 발표한 "Embedding methods for visual analysis of music data"와 내용이 같습니다. 정확히 말하면 2014 ismir 논문을 다시 2페이지로 요약해서 icml에 냈다고 해야겠군요. Invited talk이기도 해서 별 문제될거야 없지만 저는 왜 2년전 연구가 조금의 추가 내용도 없이 이렇게 나올 수 있었는지 불만입니다.  게다가 성의도 없고 레퍼런스는 dataset 인용 하나와 본인논문 4개;; 음;; 뭐 ...
  • 그렇지만 ismir 논문은 괜찮은것같고, embedding을 어떻게 정의하고 사용하는지 사례를 알고싶어서 자세히 읽어보기로 했습니다.

Embeddings

임베딩, 보통 word embeddings가 많이 쓰이죠. 임베딩이란..
  • 고차원의 데이터를 그보다 낮은 차원으로 맵핑하되,
    • 즉 N-dim vector → M-dim vector로 바꾼다고 하면 N>M이고, 대체로 N>>M이겠죠. 
  • 맵핑한 결과(embeddings)가, 낮은 차원의 공간 각 데이터의 '관계'가 성립하도록 해주는 작업입니다.
    • N차원 공간의 특성이 무엇이었든지간에, M차원으로 옮겨줬을 때 각 데이터 벡터 - 즉 임베딩 - 사이가 의미가 있길 바라는거죠. 예를 들면,
      • word2vec:
        •  5만개의 단어가 있다 치죠. 얘네들은 5만차원의 one-hot-vector로 나타낼 수 있습니다. 그리고 5만차원의 벡터를 100차원 공간에 맵핑시키는데, 맵핑한 결과가
          • w2v(남자) - w2v(여자) == w2v(왕) - w2v(여왕)
          • w2v(한국) - w2v(서울) == w2v(프랑스) - w2v(파리)
        • 와 같은 등식이 (근사적으로) 성립하도록 만들어주는 것이지요.
      • t-SNE:

          • 고차원의 데이터를 2차원으로 줄여서 시각화하는 방법입니다. 유사한 데이터가 비슷한 곳에 모이게 되죠. 예를 들어 MNIST의 숫자 필기의 픽셀 값을 (28*28=784차원 데이터) t-SNE를 써서 2차원으로 표현해주면 아래와 같이 됩니다.

Embeddings: HOW?

  • 여러가지 방법이 있죠. word2vec은 단어의 문맥을 보고 판단합니다. 즉 주변에 있는 단어의 값을 활용합니다. 따라서 word sequences - 충분한 양의 글 - 만 있으면 됩니다.
  • t-SNE는, 그 이름을 보면
    • t-distributed Stochastic Neighbor Embedding 입니다. 즉,
    • t-SNE는 비슷한 값들이 비슷한 위치에 - 즉 neighbor가 되도록 만드는 것이 목적입니다. 역시 원본 데이터 - 고차원 벡터 - 만 가지고 판단합니다. 
  • 그런데 이 외에도 다양한 경우가 있습니다.
    • 예를 들어 Joshua의 논문은 Million Song Tweets Dataset을 사용했습니다. 이 데이터셋은 트윗에서 긁어모은 데이터인데, 수많은 (음악(곡,아티스트,앨범), 위치(도시)) 의 tuple로 이루어져있습니다.
    • 그리고 이 논문의 목적은 이 데이터를 이용해서
      • embedding 1, X( ): city ti embedding space, c → X(c)
      • embedding 2, Y( ): artist to embedding space, a → Y(a)
    • 를 만들어주는데, 이 X( )Y( )의 차원이 같게 설정해주는거죠. 그리고나서 Y(a), artist와 X(c), 도시(city)의 관계를 찾아보자는 내용입니다. 
    • tuple형태의 데이터가 있다면 다른 상황에도 적용이 가능하겠죠. 

제안한 알고리즘

자세한 내용을 보면, 우선 여기에서는 트위터에서 곡 정보를 빼고 아티스트 정보만 모았습니다. 그리고 위치 정보는 '도시'만 남겼구요. a를 아티스트,  c를 도시라고 하면 임베딩을 학습한 결과는..
    • P(a|c), 즉 각 도시에 대해 아티스트 a를 들을 확률과
    • euclidean distance(X(c) - Y(a))
  • 이 둘이 비례하는 결과가 나오면 됩니다.
섹션 3의 식을 보면 p_a가 추가되어있는데 이건 아티스트의 인기(popularity)를 감안해주기 위한 bias입니다. 이를 이용해 P(a|c)를 정리했습니다. 바로 아래와 같죠. (이 논문엔 왜 식에 번호를 안붙였을까요; 우린 그냥 (1)이라고 합시다.)
 (1)

이제 이 확률 식에 맞추어 X(), Y()를 찾으면 됩니다!

찾는 방법은 Maximum (log) Likelihood로 정리하고, 이를 SGD로 푸는거군요. 즉, 가지고 있는 데이터에 근거해 (1)을 극대화해주는 X, Y, p_a를 구하면 됩니다. 다시말해,
 (2)
가 됩니다.

이제 SGD문제가 되고, 열심히 돌려주면 됩니다. 저자가 언급하기를 여기서 연산량의 문제가 되는 부분이 (1)의 분모로 들어가있던 partition function Z()입니다. [6]의 방법으로 근사했다는데 역시 같은 저자의 2013년 ismir논문이네요.

그 외

뒷부분은 실제로 실험을 돌렸더니 이러저러하더라 라는 내용이라 생략하겠습니다.

정리

결과적으로 우리가 원하는 의미에 따라 식 (1)을 정의해주고 이를 식(2)처럼 풀면 된다는 막상 간단한 내용이네요.
[6]의 논문은 tuple이 아니라 triplets에 대한 내용입니다만 역시 유사한 방법으로 문제를 풀어줍니다. 수식 전개가 비교적 더 자세히 나와있습니다.
ISMIR논문이 레퍼런스 섹션 별도 할당 없이 전체 6페이지이던 시절이라 레퍼런스가 좀 부실하지만, 원하는 상황에 어떻게 Embedding을 만들어 줄 수 있는지 간단하게 이해가 되었네요.

최적화는 늘 그럿듯 SGD가 두루두루 쓰일테고, 식 (1)을 얼마나 실제 데이터에 맞추어 잘 세워주느냐가 중요한 내용일 듯 합니다.



Wednesday, May 25, 2016

딥러닝과 음악 분류 (Deep learning and music classification), 2016-05-24, 카이스트

카이스트 남주한 교수님의 수업인 GCT634에서 Deep learning and music classification이라는 제목으로 세미나를 했습니다.
덕분에 교수님과 연구실에 계신분들 만나뵙게되었네요. 같은 분야에 계신 분들을 여럿 만나뵙게되어 여러모로 의미있는 자리였습니다.
강의에 사용한 슬라이드를 공유하니 참고하셔요.



Deep learning for music classification, 2016-05-24 from Keunwoo Choi

PS. GCT634 강의자료가 업로드되어있는데, Music information retrieval 공부하시는 분들에게 훌륭한 공부자료입니다.


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


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를 쓰게될지는 모르겠습니다만 여튼 도움이 되었으면 좋겠습니다.





Tuesday, August 11, 2015

[Korean] 한국어 노래 가사에 제일 많이 나오는 단어는?

일단 성격 급한 분들을 위해 (ex;저) 결론부터.

=== TOP N WORD ===
1: 13719 times; 보다
2: 10558 times; 주다
3: 7597 times; 사랑
4: 6936 times; 사랑하다
5: 6133 times; 가다
6: 6102 times; 되다
7: 5363 times; 이제
8: 5136 times; 말다
9: 4855 times; love
10: 4766 times; 오다
11: 4696 times; 알다
12: 4169 times; 다시
13: 4011 times; 모르다
14: 3947 times; 사람
15: 3825 times; babi
16: 3476 times; 너무
17: 3370 times; 버리다
18: 3345 times; 아니다
19: 3247 times; 좋다
20: 3205 times; 마음
21: 3061 times; 눈물
22: 3048 times; 없어
23: 3043 times; 오늘
24: 2939 times; 없는
25: 2877 times; 잊다
26: 2850 times; 있어
27: 2730 times; 말하다
28: 2684 times; 못하다
29: 2628 times; 세상
30: 2530 times; 아프다
31: 2496 times; 지금
32: 2399 times; 떠나다
33: 2394 times; 가슴
34: 2313 times; 만나다
35: 2256 times; 웃다
36: 2242 times; 나다
37: 2199 times; 이렇다
38: 2188 times; girl
39: 2101 times; 울다
40: 2099 times; 있는
41: 2029 times; 같은
42: 2012 times; 살다
43: 2010 times; 모든
44: 1990 times; 아직
45: 1983 times; 보이다
46: 1950 times; 없이
47: 1932 times; 하루
48: 1929 times; 기다리다
49: 1860 times; 정말
50: 1837 times; 모습

자 위의 50개 단어를 적당히 섞어서 그럴싸한 가사를 만들어보세요!!

상세 내용:
2015년 *월 *일부터 *월 *일까지 약 *일간 * 뮤직 서비스에서 재생된 곡 중 상위 *곡. 중에서 가사가 존재하는 음원 *개를 분석했습니다.
국문/영어를 같이 처리했고 stop words는 이곳 저곳에서 구해서 합쳤는데, 내부적으로 사용하는 모듈에서 처리되는 부분도 있어서 정확한 목록을 밝히기가 애매하군요.
명사인 사랑과 동사형태인 사랑하다를 합치면 14000번이 넘게 나옵니다. 뜻 위주로 생각하면 love까지 더해도 될 것 같구요. 그러먼 무려 19000번! 압도적인 1위입니다.
그 외엔 일반적인 말뭉치(corpus)의 순위를 어느정도 따르지 않을까 합니다. 특이사항을 꼽자면 14위의 사람, 15위의 babi (baby, babi, babe 를 다 합친것같은데 파이썬의 normalization 코드를 다시 한 번 봐야 알 것 같네요), 20 마음, 21눈물, ... 29 세상 30 아프다 33 가슴 38 girl 48 기다리다, 등이 눈에 띄네요.



Monday, August 3, 2015

[Korean] 노래 가사 자연어 처리를 위한 준비작업


노래 가사를 텍스트로 보고 처리하는 과정에서 흥미로운 내용이 있어서 정리했습니다. 자연어 처리 관점에서 노래 가사를 다루니 일반적인 텍스트와 다른 점이 많이 보이네요.


  • 구두점의 활용이 불명확함

예:

이런 그대를 믿으라고 했나요..
그 때 왜 나를 사랑한다 했나요..
그대가 바랬던 마음을 그려왔었던..
그 모습에 내가 많이 모자란 건가요..
예:
버리고 싶은 건 니가 아니었어
버려지는 건 내가 되어줄께
이렇게 그냥 버려둬 오지마
첫 번째 예는 문장 끝마다 '..' 을 붙였습니다. 반면 두 번째 예는 문장 끝에 마침표가 전혀 찍혀있지 않습니다. 결론적으로 노래 가사에서 마침표, 쉼표, 느낌표 등 모든 구두점은 전부 없애버리는 편이 처리하기에 수월해보입니다. 노래 가사는 일관된 규칙으로 작성하지 않으니까요.
자연어 처리를 단어 레벨에서 한다면 큰 문제는 없습니다. 다만 문장 레벨로 처리하려면 좀 곤란하겠죠.



  • 특수문자의 활용이 다양하고 다채로움


예:
사르륵녹은 그대를 보면 사랑을 느끼죠
oh so beautiful 사랑을 말해봐요 
매일 너와 함께! ~~해!~~~
조금더 다가와줘
예:
다가와- 느껴봐 음- 
위의 예를 보시면 물결과 느낌표, 대쉬 기호가 같은 것을 의미합니다. 이 외에도 -, - - , ---, ~, 등 아주 다양합니다.


  • 사용하는 언어가 다양하다


(극단적인) 예:
簡単に
(칸탄니)
간단히
You make me happy
一言で
(히토코토데)
한마디로
夕べの すれ違い
(유우베노 스레치가이)
저녁때의 엇갈림
まだまだ 埋まってない
(마다마다 우맛테나이)
아직아직 채워지지 않아
So I'm waiting ソワソワ Oh
(소와소와)
안절부절
무슨 노래인지는 모르겠지만 이 노래는 영어가사, 일본어, 일본어 발음, 한국어 해석이 적혀있습니다. 위의 예가 조금 특이한 경우지만 영어 단어/문장과 국문이 섞여서 나오는 가사는 아주 흔하죠.


  • 각종 잡; 내용
예:

Simply just look at you
Why must I fall for you? Ooo-Ooo-Ooo
Or why I can't think of words when I, 
Simply approach you
I don't know what to do, Ooo-Ooo-Ooo


^ㅅ^/
예:
[Chorus]
Yeah (yeah) 
Shorty got down to come and get me [x2]

첫 번째 예는 잘 나가는데 가사 맨 끝에 왠 이모티콘을 넣어놨습니다. 두번째 예는 [chorus], [x2] 와 같은 부가적인 정보가 그대로 텍스트에 포함되어있습니다.


  • 예 워 오 우 
노래 가사에 yeah, oh, whoa, 예, 워, 예이예, 라라라, 워, 오, 오오, .... 가 아주 많이 나옵니다.



  • 그 외에 나를 힘들게 하는 것들
예:


to moonn6pence  from shootingstar
가사입력 papayeverte
[Jazz Instrumental]
가사 어쩌구저쩌구<br>가사 다음줄<br>가사 가사 <br>
from A-Zlyrics, ... 





  • 위의 내용을 다 보듬어 보면 아래와 같은 식의  Stopword를 추가해야 한다는 결론이 나옵니다. 물론 이외에도 많이 있겠죠. 
    • 일반적으로 stopword로 인식되는 값 확인사살
      • * ** *** + " ' ` . .. ... / ~ ~~ ~~~ ~~~~ ~~~~~ ? - -- --- ^, ^^, a, b, c,...z,...
    • 노래 가사에 붙어있는 불필요한 단어
      • chorus, verse, pre-chorus, bridge, feat, hook, song, solo, twice, outro, sabi, intro, pre-hook, rap, x2, x3, x4, x5, x6, x7, x8, x9, x10, copyright, azlyrics, writer, br, choir, guitar
      • 간주, 후렴, 반복, 가사입력, 출처, 작성자, 악보, 연주곡, 간주중