Showing posts with label 튜토리알. Show all posts
Showing posts with label 튜토리알. 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차원 벡터로 입력 데이터의 크기를 줄여야겠죠. 장단점이 있어서 해보기전엔 정하기 어려워보입니다. 



Tuesday, August 9, 2016

세상에 있는 (거의) 모든 머신러닝 문제 공략법

좋은 블로그 게시물이 나와서 번역합니다. 원문은 이곳을 참고하시기 바랍니다.
Karpathy의 글도 그랬지만 그림은 그대로 퍼오고, 글도 가급적 그대로 번역합니다. 교육 목적으로 활용해주시길 바랍니다.
제가 보충 설명을 하는 경우엔 괄호안에 (**요렇게) 적어놓았습니다.

세상에 있는 (거의) 모든 머신러닝 문제 공략법 (Approaching (Almost) Any Machine Learning Problem)

저자: Abshshek Thakur 
번역: 최근우

데이터 사이언티스트들은 하루종일 데이터를 다룹니다. 사람에 따라 다르겠지만 60-70%의 시간을 데이터를 전처리하고 원하는 형태로 변환하는데 사용한다는 사람도 있습니다. 그런 과정이 끝나고 나면 실제로 데이터에 머신러닝 알고리즘을 적용합니다. 이 글에서는 간단한 전처리 과정 및 머신러닝을 적용하는 과정을 자세히 다룹니다. 여기에서 소개하는 파이프라인은 제가 백개가 넘는 머신러닝 대회에 참가한 경험을 바탕으로 배운 내용입니다. 

파이썬을 사용해 설명드리겠습니다.

데이터

머신러닝을 활용하려면 데이터를 테이블의 형태로 변환해야합니다. 이 과정은 시간도 오래걸리고 힘든 과정입니다.

이 테이블의 각 행(row)은 각각의 데이터 샘플에 해당합니다. 보통 입력 데이터를 X, 레이블 (혹은 출력)을 y로 표현합니다. 레이블은 하나의 열(single column)일 수도 있고 여러 열로 이루어져 있을 수도 있습니다.

레이블의 종류

  • 단일 열, 이진수 (분류 문제. 레이블엔 두 개의 카테고리가 존재하고 모든 데이터 샘플은 반드시 둘 중 하나의 카테고리에만 해당하는 경우. 0과 1로 각각 다른 카테고리를 표현할 수 있으므로 이진값을 사용한다.)(**예: 텍스트를 보고 저자의 성별을 맞추는 경우)
  • 단일 열, 실수 (회귀 문제. 단일 열이므로 단 하나의 값만 예측하면 된다.)(**예: 텍스트를 보고 저자의 나이를 예측하는 경우)
  • 여러 열, 이진수 (분류 문제. 여러 카테고리가 존재하고 각 데이터는 하나의 카테고리에 해당한다.)(**예: 댓글을 보고 작성자가 응원하는 스포츠 팀을 맞추기, 이 경우에 열의 개수는 스포츠 팀의 개수와 같다.)
  • 여러 열, 실수 (회귀 문제이나 여러 값을 예측함.)(**예: 의료 검진 데이터를 보고 피검사자가 여러 종류의 암에 걸릴 확률을 예측. 이 경우 열의 개수는 암 종류의 개수와 같다.)
  • 다중 레이블 (분류 문제, 각 데이터 샘플이 여러개의 카테고리에 속할 수 있다.)(**예: 음악 신호를 보고 드럼, 기타, 보컬이 있는지 여부를 판단하는 경우. 열의 개수는 3개가 된다.)

평가 방법

어떤 경우든지간에 머신러닝 알고리즘의 평가는 필수입니다. 각 카테고리의 데이터 개수가 크게 차이나는 경우에 ROC AUC를 사용할 수도 있고, 다중 레이블 분류 문제는 카테고리 크로스 엔트로피나 다중레이블 로그 로스 등을 활용합니다. 
평가 방법은 상황에 따라 다르기 때문에 여기에선 자세히 다루지 않습니다.

라이브러리

필수적인 라이브러리를 몇 가지 소개합니다.
  • 데이터를 보고 간단한 연산을 수행: pandas
  • 각종 머신러닝 모델:  scikit-learn
  • 최강의 그라디언트 부스팅 라이브러리: xgboost
  • 뉴럴 네트워크: keras
  • 데이터 시각화: matplotlib
  • 실시간 모니터링: tqdm
아나콘다를 사용해 다양한 라이브러리를 쉽게 설치할 수 있습니다. 저는 사용하고있지 않지만 각자 판단하시길 바랍니다.

머신러닝 프레임워크



2015년부터 제가 개발중인 머신러닝 자동화 프레임워크의 그림입니다. 이 글에서도 그림과 같은 구조로 작업을 수행합니다.

가장 일반적으로 적용되는 단계를 진한 분홍색 화살표로 그렸습니다. 우선 앞에서 이야기한 전처리 과정을 거쳐 표 형태로 데이터를 정리하고나면 이 단계를 시작할 수 있습니다.

전처리


우선 우리에게 주어진 문제가 어떤 문제인지 파악해야합니다. 이진 분류(0 vs 1)인지, 여러 카테고리중 하나를 고르는 다범주 분류(multi-class classification)인지, 다중 레이블 분류문제인지 아니면 회귀 문제인지를 명확하게 결정해야합니다. 그리고 나면 우리가 가지고 있는 데이터를 학습 셋(training set)과 검증 셋(validation set)으로 나눕니다. 아래 그림을 참고하시길 바랍니다.


(**중요) 두 셋으로 나눌 때에는 반드시 레이블 정보를 사용해야합니다.  분류 문제의 경우 stratified splitting을 사용하시기 바랍니다. 파이썬에선 scikit-learn을 사용하면 됩니다. (**이렇게 하면 두 셋에서 레이블의 분포가 동일하게 유지됩니다.)


회귀 문제의 경우 그냥 간단하게 K-fold로 셋을 나눠주면 됩니다. 회귀에서도 분포를 유지하는 방법이 있긴 한데 독자여러분이 생각해보시길 바랍니다. (**아니 저기..)



이 코드에서는 검증 셋의 크기를 전체의 10%로 설정했습니다. 이 값은 가지고 있는 데이터의 크기에 따라 적절히 설정하면 됩니다.

이렇게 데이터를 나눈 뒤에는 두 셋을 동일하게 처리해야합니다. 그리고 절대 학습 셋과 검증 셋에 데이터가 겹치면 안됩니다. 그렇게 할 경우 마치 학습이 아주 잘 된 것 처럼 착각할 수 있습니다. 실제로는 엄청난 과적합(overfitting)이 일어나겠죠.

다음 단계는 데이터에 어떤 형태의 값이 있는지 알아내는 것입니다. 대략 숫자, 범주 정보, 그리고 문자열 데이터정도로 나눠서 생각할 수 있습니다. 카글의 타이타닉 데이터셋을 살펴볼까요?


여기에서는 survival이 레이블이 됩니다. 그리고 각 승객의 좌석 등급, 성별, 탑승한 항구는 범주화해서 생각할 수 있습니다. 나이, 형제자매의 수, 부모/자녀 등은 숫자 정보가 되구요. 마지막으로 이름은 문자열입니다. 이 작업 (**생존 여부를 예측하는 작업)에서는 크게 중요하지 않을 것 같군요.

우선 숫자를 봅시다. 이 값은 특별한 전처리 필요없이 바로 사용할 수 있습니다. 따라서 정규화(normalization) 및 머신러닝 기법을 바로 적용하면 됩니다.

범주 데이터는 두가지 방법으로 처리할 수 있습니다.
  • 카테고리를 라벨로 변환

  • 카테고리를 이진 변수 (one-hot-vector)(**하나의 성분만 1이고 나머지는 0인 벡터)로 변환

여기서 OneHotEncoder를 쓰기 전에 우선 LabelEncoder를 적용해야 하는 점을 주의하시기 바랍니다.

타이타닉 데이터셋의 문자열은 문자열 변수의 예로는 별로 좋지 않습니다. 일반적으로 문자열을 어떻게 다루는지 한번 알아보겠습니다.

우선 (**pandas를 쓸 경우) 아래 코드를 써서 데이터에 있는 모든 텍스트를 하나로 이어 붙일 수 있습니다.


그리고 여기에 CountVectorizer 또는 TfidfVectorizer를 사용합니다.



보통 TfidfVectorizer가 더 잘 작동합니다. (**당연히.. ) 대체로 아래처럼 셋팅하면 무난하게 사용 가능합니다.


만일 이 Vectorizer를 트레이닝 데이터에만 적용했다면, 나중에 사용할 수 있도록 하드디스크에 저장을 해놓아야합니다.


이제 Stacker 모듈을 봅시다. 여기에서는 다양한 특징값을 합칩니다.
일반적인 데이터는 np.hstack으로 벡터를 이어주면 됩니다.
만일 데이터가 sparse한 경우 (대부분의 값이 0인 경우) scipy.sparse를 사용합니다.


만일 PCA같은 과정이 포함되어있다면 sklearn.pipeline.FeatureUnion을 쓰면 됩니다.


자, 드디어 데이터 전처리가 끝났습니다. 
이제 머신러닝 알고리즘을 적용하면 됩니다.

머신러닝 적용

어떤 모델을 적용할까요? 위의 단계를 밟은 경우엔 트리 기반의 알고리즘만 가능합니다. 트리 기반의 모델은 여러가지 종류가 있습니다.

  • RandomForestClassifier
  • RandomForestRegressor
  • ExtraTreesClassifier
  • ExtraTreesRegressor
  • XGBClassifier
  • XGBRegressor
선형 모델을 사용하려면 위의 특징값을 Normalize하는 과정을 거쳐야합니다. sklearn의 Normalizer나 StandardScaler를 사용하면 됩니다. 단, 데이터가 dense한 경우에만 사용이 가능합니다. Sparse한 경우엔 결과가 좋지 않습니다. 

위의 트리 모델을 사용해서 그럭저럭 괜찮은 결과가 나왔다면 이제 모델을 자세하게 튜닝할 차례입니다.

다음 단계는 decomposition 입니다.


여기에선 LDA와 QDA는 생략합니다. 고차원 데이터의 경우 PCA(주성분분석)를 쓰면 차원을 효과적으로 줄일 수 있습니다. 이미지의 경우 10-15개의 성분을 사용해보고 차원을 늘려가며 성능을 비교해보십시오. 그 외엔 50-60개정도의 성분으로 시작해보십시오. 단, 값을 그대로 사용해도 괜찮은 상황이라면 굳이 차원을 줄일 필요는 없습니다.


텍스트의 경우는 sparse 행렬에 SVD를 적용합니다.

보통 120-200정도의 값을 사용합니다. 이보다 큰 값을 쓴다면 연산량에 유의하십시오.


이제 선형 모델도 사용할 수 있도록 특징값을 normalize하거나 re-scaling합니다. (**특징값의 범위를 조절) 그리고 나면 유용한 특징값을 고르는 Feature Selector 단계로 들어갑니다.


특징값을 선정하는 방법은 여러가지가 있습니다. Greedy 알고리즘을 쓸 경우엔, 우선 하나의 특징값을 골라서 모델을 돌리고 여기에 다른 특징값을 더하거나 빼면서 결과를 비교합니다. AUC로 모델을 평가하면서 특징값을 고르는 코드를 참고하십시오. 

아래의 코드는 RandomForest를 이용한 예제입니다. 이렇게 학습한 모델을 저장해놓고 나중에 사용할 수도 있습니다.


n_opimators 등의 하이퍼파라미터를 너무 크게 설정하면 과적합(overfitting)이 일어나니 주의하십시오.

혹은 xgboost를 사용할 수도 있습니다.


데이터가 sparse한 경우에도 RandomForestClassifier, RandomForestRegressor, xgboost 등을 사용 가능합니다.

그 외에도 chi-2로 특징값 선택이 가능합니다.


여기에선 k를 20으로 설정했는데, 이 값 역시 하이퍼파라미터이므로 최적화가 필요합니다.

지금까지 여러 모델을 소개했습니다. 데이터를 처리할 때 이렇게 학습한 모델을 꼭 저장해놓으십시오.

모델 선택 및 최적화

이제 모델을 선택하고 하이퍼파라미터를 최적화하는 일이 남았습니다.


널리 쓰이는 모델은 아래와 같습니다.
  • 분류
    • Random Forest
    • GBM
    • Logistic Regression
    • Naive Bayes
    • Support Vector Machines
    • k-Nearest neighbors

  • 회귀
    • Random Forest
    • GBM
    • Linear Regression
    • Ridge
    • Lasso
    • SVR

하이퍼 파라미터를 최적화하는 과정은 정해진 공식이 없습니다. 많은 사람들이 이와 관련해 질문을 합니다만 데이터와 모델에 따라 달라지기때문에 한마디로 말하기가 어렵습니다. 또, 몇 가지 팁이 있지만 경험이 많은 사람들은 이 비법을 숨기려고 하기도 합니다. 하지만 제가 알려드리겠습니다.

각 모델별로 어떤 하이퍼파라미터가 있는지 정리하면..


위의 값을 임의로 조합한 랜덤 서치를 추천합니다. 
제 생각일뿐이지만, 위의 값을 기반으로 찾아본다면 충분할겁니다.

정리

마지막으로 학습 과정을 정리해보면..




그리고 학습 과정에서 저장한 각종 변환(transform)을 다시 불러와서 validation/test set에 사용해야겠죠?


마무리

위의 과정을 잘 따라하면 대체로 아주 좋은 성능을 얻을 수 있을 것입니다. 물론, 잘 되지 않는 경우도 있겠죠. 그러면서 배우는 것이니 열심히 해보시길 바랍니다.

ISMIR 2016 - Day 0, Day 1, Day 2

지금 학회가 진행중입니다만 우선 2.5일치 정리합니다.

Day 0: Tutorial

T1은 재즈 역사 소개 / 재즈 데이터셋 및 발표자들이 개발한 툴을 소개했습니다. T1의 발표자인 Jakob Abeßer는 재즈 관련 연구를 많이 한 사람입니다. T4는 EEG에 대한 소개였는데 발표는 매우 지루했습니다. 발표자료를 github에 올렸다고 했는데 어딨을까요..;;

제가 제일 관심있는 내용은 Tutorial: Natural Language Processing for Music Information Retrieval입니다. 내용 자체는 매우 기본적인 NLP입니다. 그리고 링크를 들어가 보시면 음악 관련 데이터로 학습한 word2vec 모델을 공유하고있습니다. 

T2는 MIR에 관심있는분이나 연구/공부를 시작하는 분들을 위한 내용입니다.
T6 - Why Hip-Hop is interesting은 MIR에서 일반적으로 가정하는 음악 신호와 힙합이 어떤 차이를 갖고 있는지에 대한 내용입니다.

Day 1: Papers

12음계의 representation인 chromagram은 STFT/CQT에서 하모닉스를 단순히 더하는 방식으로 계산할 경우 신호의 하모닉스 성분때문에 많은 노이즈를 포함하게됩니다. 이를 deep neural network를 이용해 더 잘 계산해주겠다는 내용입니다.
Chromagram은 오디오 feature representation의 하나로 멜로디나 코드 추출 등에 사용할 수 있습니다. 딥러닝으로 Feature를 학습하는 방식이 정확히 어떤 쓰임새가 있을지 따지긴 어렵습니다만 연구 방식은 유효합니다.

한참 boundary detection논문을 내던 저자가 이번엔 다른 문제를 푸는 논문을 냈군요. 10k 트랙을 이용하는데, 레이블링 정보가 트랙 전체에 보컬이 있냐/없냐로만 되어있습니다. 이걸 컨브넷을 써서 학습시킨 결과를 다시 시간 프레임별로 적용하면 결과적으로 각 프레임에 보컬이 있냐 없냐의 문제 (제목의 Pinpoint이 의미하는 바가 이것이겠죠)를 풀 수 있다는 내용입니다.
즉, 곡 전체의 라벨로 학습시켜도 더 작은 단위의 판단을 잘 내릴 수 있게 된다는 내용이구요.

이 방식이 작동할 수 있는 이유를 대충 설명하자면 그냥 데이터가 많아서, 오차가 상쇄된다고 볼 수 있습니다. 다르게 보면 강화학습의 학습 과정과도 같은 셈입니다. 강화학습에서도 t0부터 t1사이에 일어난 모든 이벤트 중에 사실 중요한 이벤트는 아주 일부일 수 있습니다. 그렇지만 t0-t1사이의 모든 이벤트가 같은 레이블에 의해 reward나 penalty를 받게 되지요. 이 논문의 적용 방식도 같고, 다만 강화 학습에서는 그런 다양한 example이 시간축에 분포하는 반면 여기에서는 spectrogram의 하나의 axis일 뿐인 것이죠. 혹은 이미지 분류에서도 꼭 pixel별 라벨링이 되어있지 않아도 deconvolution을 해보면 어떤 위치에 객체가 있는지 대략 알아낼 수 있는것과 같습니다.

발표 마지막에 아주 재미있는 데모가 있었습니다. 결과적으로 이 컨브넷이 뭘 학습하냐?라는 것이었는데 아무 스펙트로그램에다가 선을 마구 그려서 컨브넷에 보여주니까 대각선 성분이 있으면 보컬이 있는것으로, 대각선이 없고 가로/세로선만 있으면 보컬이 없는 것으로 판단하더군요. 아..아이유의 삼단고음은 어떻게 될지 궁금하군요. 아무튼 그래서 스펙트로그램에 VOICE라고 그림을 확 그렸더니 (그림을 그린 부분이 높은 값을 갖게 되겠지요) V, O, C 처럼 대각선 성분이 있는 곳은 보컬이 있다고 판단을 하더군요.




Last.fm 로그를 수집합니다. 플레이로그와 함께 사용자의 나이/국가/성별을 모았구요.
그리고 사용자 모델링을 통해 3가지 feature를 제안했습니다. Exploratoryness, Mainstreamness, Genderness입니다. 앞의 2개는 EchoNest에서 artist profile에 있던것과 비슷한 내용이고, 이름도 직관적이죠. 마지막 featurer의 경우 저는 정확히 이게 어떤 작용을 할 것인지 잘 감은 안왔습니다만 Paul Lamere (Spotify)의 블로그 포스팅 Gender Specific Listening에서 소개한 것 등 남/녀의 취향 차이는 있겠죠.

이제 계산한 user feature와 demographics 정보를 이용해 추천을 해야하는데, 추가된 정보를 어떻게 user-item matrix에 집어넣어서 factorise를 해줄 수 있을 것이냐가 문제겠죠? 이 논문에서는
S. Rendle. Factorization machines. In IEEE 10th Inter- national Conference on Data Mining, pages 995–1000, Sydney, Australia, 2010. IEEE. 
의 방법을 사용했다고 합니다. 논문을 인용만 했는데 설명이 너무 안된것이 좀 아쉽군요. 안봤지만 아마도 여러 유사한 목적의 다른 논문처럼, factorise하기 위한 objective function에, 추가된 criteria에 맞춘 항을 더한뒤에 SGD로 최적화하는 전형적인 방식이 아닐까 생각합니다.

결과는 심플한데요, 논문의 그림 2를 보시면 이런저런 정보를 다 사용하면 Matrix factorisation의 RMSE가 제일 낮아진다 - 즉 retrospective evaluation의 결과로 제일 좋다 - 는 내용입니다.

뒷부분에 추가로 주말/주중이라는 컨텍스트 정보를 추가했는데 결과는 별로 성능이 좋아지지 않습니다. 제 의견은 사용자 모델링에서 사용자가 얼마나 컨텍스트에 민감한지 - 즉 user.contextualness 같은 내용을 더 모델링하지 않으면 컨텍스트 관련 추천은 늘 이런식이 아닐까 합니다. 저자랑도 비슷한 이야기를 했구요.



USC의 Julian McAuley가 발표한 Amazon review dataset이 있습니다. 여기에서 음악 관련 카테고리만 모아서 열심히 정리를 한 데이터셋인 MARD: Multimodal Album Reviews Dataset을 발표했습니다.

아마존 product ID와 Musicbrainz ID가 매칭이 안된다는 슬픈 이유로 (API에 항목은 있지만 값이 대부분 비어있습니다) Entity recognition을 써서 장르나 밴드 이름등을 뽑아는 등 각종 귀찮은 text preprocessing작업을 거쳐서 만든 데이터셋입니다. 

그리고 이 데이터셋을 이용해 장르 분류 작업을 간단히 보였구요. 

드럼 기초 테크닉인 strike(치는것), buzz roll, flam, drag 네가지를 구별하는 논문입니다. 


Day 2


MIREX라는 이벤트가 있습니다. ISMIR에서 하는 competition인데요, 음.......... 한마디로 이야기하면 이제 정말 문제가 많습니다. 작업 개수는 너무 많고, 관리에 어려움이 많고 비효율적이고 등등. 참다못한 Brian이 Kaggle for MIR을 만들어야한다! 라는 내용을 제안하는 발표였습니다.

각종 인프라를 위한 소프트웨어가 공개되어있고, 이래저래 가능한 시나리오입니다. 다만 중간중간에 돈이 들어가는 부분이 있고, 사람들의 참여가 많이 필요하겠죠. 시도가 잘 되길 빌고있습니다.

각종 스트리밍 서비스 - 정확히는 클라우드 뮤직 서비스, 즉 본인의 음악을 업로드해서 쓰는 iTunes Match, Amazon, Google Music - 에 대한 사용자 조사입니다.

중간에, 60%정도 되는, 많은 사람들이 돈을 지불하고 쓸 용의가 있다고 응답했다. 고 써있는데 저는 좀 회의적입니다. 설문조사에서 사람들이 솔직하게 답하지 않는 흔한 오류가 아닐까요? 그 사람들이 스스로 '돈을 낼 용의도 있는데?'라고 말하거나, 혹은 진심으로 그렇게 믿는다 하더라도 이렇게, 이렇게! 이렇게 좋은 뮤직 스트리밍 서비스가 많은데 지금도 공짜로 쓰는 사람들이 엄청나게 많은 마당에 무슨 의미가 있는걸지 잘 모르겠습니다. 행여나 그게 진심이라면 스트리밍 업체에서는 무료 사용자의 만족도를 일부러 낮춰서 결제를 유도해야하는걸까요?

슬라이드가 공개되어있는지 모르겠습니다만 사진 몇장 첨부합니다.










Michele가 퀸메리에 방문연구와서 연구한 내용이군요. NLP동네에 ANEW라는, Affective Norm for English Words, 즉 각종 감정에 관련된 단어를 Arousal-Valence-Dominance 총 3개의 축으로 된 3d 공간에 맵핑시켜놓은 데이터가 있습니다. 이 데이터가, 즉 벡터 맵핑이, 음악의 감정(mood/emotion) 관련된 태깅이나 분류 문제에 직접 사용하기엔 좀 맞지 않는 면이 있습니다. 저도 한번 테스트해봤다가 너무 맞지 않아서 관뒀는데, 이걸 이래저래하게 고쳐쓰자는 내용입니다.

몇 달동안 같은 연구실에 앞-옆자리에 앉아있던 친군데 이걸 연구했는줄을 오늘 알았습니다...


아주 재밌는 내용입니다. 전에 영문 블로그에 정리했던 ICML 2016: ML4MD 워크샵에서도 비슷한 논문이 있었습니다. 각종 아이템 (song, user, playlist,...)의 co-occurrence를 이용해 word2vec비슷한 embeddings을 학습시키고 그걸 이용해 추천이나 분석을 하는 내용이고 이 논문도 유사한 내용입니다.

이 연구의 특징은 Song, Session, User 이렇게 3가지 카테고리를 하나의 평면에 맵핑했다는 내용입니다. 여기서 Session이란 대략 플레이리스트 비슷한건데, 곡 하나가 끝나고 다음 곡 재생되는 시간 간격이 10분이 넘으면 별도의 session으로 보는걸로 정의했습니다.


그리고 위의 그림처럼 같은 network에 있으면 co-occurrence라고 보구요.

시각화를 위해서는 직접 2D로 embedding을 구했고, 추천에 이용한 벡터는 128차원입니다.

사용한 데이터는 타이완의 KK Music이라는 곳의 로그이고 2015년 상반기 6개월간의 데이터를 썼습니다.


평가는 precision-recall을 보았는데 가장 기본적인 MF보다 좋은 성능을 보입니다.



이 데이터가 좀 재밌습니다. 사용자 한명을 고정하고 그 사용자가 들은 음악을 2D 평면에 배치시킨 것입니다. 여기에 Clustering을 써서 사용자가 현재 듣는 세션이 어떤 '모드'의 세션인지 (즉 어떤 cluster에 해당하는지) identify한 뒤에 그에 맞는 추천을 해준다면 자연스럽게 personalised contextual recommendation이 될 것 같습니다.

제 연구 분야이기도 해서 저는 아주 맘에드는 내용이었습니다.

제가 포스터 세션이 조금 일찍 갔는데, 3저자인 지도교수가 1저자인 학생에게 아주 자세한 내용을 묻더군요. 음... 그러니까 와서 발표할때까지 지도교수는 이 논문이 어떤 내용인지 잘 몰랐다는 이야기가 되겠습니다. 거기에서라도 물어보고 관심 가지는게 어디냐 하는 생각을 했습니다.

그리고 이 세션이 끝나고 어쩌다가 아마존 뮤직(@씨애틀)에서 엔지니어로 일하고있는 사람과 이야기를 했는데, 자세한건 이야기할 수 없지만 이 논문과 아주, 아주 비슷한 알고리즘을 회사에서 사용중이라고 하더군요. 그 정도면 이미 말해선 안되는 내용을 말한 것 같습니다만... 


서울대 이교구교수님 연구실에서 나온 논문입니다. DNN을 스펙트로그램이 아닌 cepstrogram에 적용하는 내용입니다. 왜냐하면,
...because a cepstrogram is shown to be a more robust representation to capture the dymanics of the overall timbre than a spectrogram.
이라고 합니다. 제가 잘 모르는 내용이라 논문 본문을 인용했습니다.

...input representation을 잘 몰라서 뒷부분 내용을 리뷰하기가 어렵군요...

실험에서는 GTZAN dataset을 사용했습니다. 너무 오래된 데이터셋이라 좀 문제가 있는데, 
  1. Corey Kereliuk, Bob L. Sturm, and Jan Larsen. Deep learning and music adversaries. IEEE Transactions on Multimedia, 17(11):2059–2071, 2015. 
에서 제안한 splitting을 사용했습니다. 그리고 random splitting의 결과도 같이 본문에 포함했습니다. 



음악 추천 관련입니다. 사용자의 skip/playing을 기반으로 현재 곡에서 다음 곡으로 나아가야할 '방향' 벡터를 구해주고, 이에 맞춰 곡을 추천해주는 알고리즘입니다. '방향'을 구하는 알고리즘이 핵심이구요.

대략 설명하면, 사용자의 log를 보고 co-occurrence를 통해 곡과 곡의 관계를 graph로 정의합니다. 이 때 co-occurrence를 사용해 곡와 곡을 잇는 edge의 값 (=similarity)을 구해주구요. 그리고 그 graph를 그대로 사용하기엔 연산량이 많아서 ISOMAP으로 n-dimensional space로 맵핑해줍니다. 

그리고 그 space에서 각 곡의 '진행 방향', 즉 공간에서 곡과 다음 곡의 상대적인 위치를 이용해 현재 사용자의 '관성' (혹은 진행 방향/속도..)를 구하고, 이를 통해 다음 곡을 고릅니다. 만일 사용자가 스킵할경우엔 그 방향의 반대방향으로 진행하게 되구요.

상당히 잘 진행한 연구라고 생각합니다. 다만 평가하는 부분에서 와닿지 않는 부분이 많이 있었습니다. 실험 설계가 과연 제안한 알고리즘을 평가하기에 적합한지도 잘 모르겠구요. 하지만 dynamic listening 상황을 가정한 연구라 평가하기가 엄청나게 어려웠을걸 감안해야겠죠. 아주 아주 유효한 접근 방식이라고 생각합니다. 실험까지 잘되었으면 (그리고 지도교수의 도움으로 앞부분이 좀 더 멋지게 포장이 된다면) 진짜 훌륭한 논문이 되었을거란 생각이 들었습니다.

Thursday, March 17, 2016

제가 번역한 딥러닝 문서 목록 (deeplerarning4j.org)



딥러닝 & deeplearning4j 튜토리알

  • 용어 선택에 고민이 많네요. 예를 들어..
    • 뉴럴 네트워크/신경망/인공 신경망
    • 딥 뉴럴 네트워크/심층 신경망
    •  weights, coefficients, parameters, hyperparameters - 계수/가중치/매개변수/파라미터/하이퍼파라미터
    • epoch
    • Gradient descent: 경사 하강법?
    • RBM, RBMs, 제한된 볼츠만 머신...
  • 하다보니 저도 헷갈리기도 하고 고민되는 단어도 있어서 번역용 저장소를 하나 만들었습니다.

  • 그럼 머신러닝/딥러닝 공부에 많은 도움 되길 바랍니다.

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


Thursday, January 21, 2016

리알못: 리눅스 알지도 못하는 사람들을 위한 가이드

스티브 잡스님의 은혜를 받으며 살아가던 저같은 앱등이도 살다보면 리눅스를 써야할 날이 옵니다. 아니, 왔습니다. 저에게 리눅스는 제 컴덕 친구들이나 흐흐거리며 다루는, 혹은 리눅스를 만든 녀석이 메일링 리스트에서 또 누군가랑 싸웠다는 기사를 흘낏 보며 떠올리는, 아주 추상적인 존재였죠. 그러나 학교와 회사의 서버를 써야하고, 그런데 서버는 리눅스로 되어있고, 나는 일개 학생/직원일 뿐이고, 그래서 20년전 MS도스를 쓰던 시절에 혹은 PC통신에서나 쓰던 ls, cd ..같은 명령어를 써보며 마치 내가 뭘 할 줄 아는 것 처럼 이런 저런 디렉토리를 오간 뒤에 결국은 인정했습니다. 아, 이걸 공부해야 하는 구나.

막상 리눅스 책이나 강좌를 보면 수백 페이지 분량의 엄청난 것들이 나옵니다. 리눅스란 무엇이고, 누가 언제 만들었고, 무슨무슨 종류가 있고, 어쩌구 저쩌구... 커널은 뭐고..등등.

이런 내용 다 제끼고! (저도 모를뿐더러; ) 리눅스 초보를 위해 아주 간략히 정리해드리겠습니다. 사실, 네이버 구글 찾으면 어지간한건 다 나옵니다. 그런데 문제는 이거죠. 뭘 찾아야 할지 모른다는 것.

그래서 아주 간략히, 정말 간략히 개념만 설명합니다. 더 자세하고 훌륭한 설명은 다시한번 구글링 하시길 바랍니다.


  • 리눅스? 유닉스?
    • 리눅스는 유닉스의 한 종류입니다. 아니 정확하게 따지면 유닉스와 유사한 뭐라고 하는데 그냥 리알못들은 그런가보다 하고 넘어갑니다. 
  • 무얼 설치해야하나요?
    • 혹시 직접 설치해야 한다면 linux ubuntu download를 구글링하셔서 맨 위 링크를 누르세요. 여러 버전이 나올텐데 LTS (Long Term Support) 버전을 쓰세요. 지금은 14.04네요.
  • 알아야할 명령어 목록
    • $ ls - list
      • 디렉토리의 내용을 보여줌
    • $ pwd - print working directory
      • 현재 디렉토리의 위치를 알려줌
    • $ less some_text_file.txt
    • $ more some_txt_file.txt
      • 텍스트 파일의 일부를 후다닥 볼 수 있음.
    • $ tail some_text_file.txt
    • $ head some_text_file.txt
      • 마찬가지. 텍스트 파일의 맨 앞/맨 뒤를 출력해줍니다.
    • $ touch temp.abc
      • 저 파일이 없다면 temp.abc라는 파일을 생성합니다. 파일의 내용은 비어있습니다.
      • 파일이 있다면 저 파일을 한번 툭 건드려주게됩니다. 결과적으로 파일의 '최종 수정한 날짜'가 현재 시간으로 바뀝니다.
    • $ mkdir directory_name
      • 디렉토리를 만듭니다.
    • $ rmdir directory_name
      • 디렉토리를 삭제합니다.
    • $ cp file.txt new_file.txt
      • 파일을 복사합니다.
    • $ mv file.txt new_name.txt
      • 파일을 이동합니다. 이 명령어를 이용해 이름을 바꿀 수 있습니다. 
    • $ echo 'blah blah
      • blah blah 라고 출력합니다.
    • $ cat files.
      • 여러 파일을 붙입니다.
    • $ tar, zip
      • 파일 압축/해제.
    • $ wget url
      • url의 파일을 다운받습니다.
    • $ chmod, chown
      • 파일/디렉토리의 권한을 바꿔줍니다.
    • $ sudo 
      • 각종 커맨드 앞에 sudo를 붙여주면 super user의 권한으로 뭔가를 하게됩니다. 수퍼 유저는 다시말해 admin, 관리자 계정입니다. 따라서 이걸 하려면 관리자 계정의 권한을 갖고있어야합니다.
    • $ top
      • 작업관리자입니다. 아주 유용하죠.
    • $ iotop, iostat
      • top과 비슷한데 각종 기기간의 입출력 내역을 보여줍니다.
    • $ nohup
      • $ nohup python main.py > log_file_name.txt &
      • 커맨드 실행 내역의 결과를 log_file_name.txt 에 저장합니다.
      • 서버에 접속해서 이걸로 커맨드를 실행하면 그 이후에 접속을 끊어도 커맨드가 계속 실행되게 됩니다. 아주 유용하죠. 
      • 그럼 중간에 실행을 중지하고싶다면?
    • $ kill, pkill
      • pkill python
      • kill 12345
      • pkill python은 실행중인 파이썬을 전부 종료합니다.
      • kill 12345는 프로세스 아이디 12345를 종료합니다.
      • 프로세스 아이디는 top 을 실행하면 왼쪽에서 볼 수 있습니다.
    • $ screen
      • nohup과 비슷한데, 저는 더 유용하게 쓰고있습니다.
      • 쉽게말해 가상의 스크린을 여러개 띄워놓고 필요할 때 해당 스크린에 접속해서 사용하는 것 입니다.
      • screen -S screen_name 으로 새 스크린을 만들고,
      • 새 스크린 내부에서는 ctrl+a, d 를 눌러서 밖으로 나올 수 있습니다.
      • screen -x 를 하면 스크린 목록을 볼 수 있습니다.
      • screen -x screen_name 으로 기존에 만들어놓은 스크린에 다시 들어가서 일을 할 수 있습니다.
      • 서버에 접속해서 일하실 땐 디폴트로 스크린을 하나 만들어서 들어가서 쓰시면 중간에 접속이 끊어져도 서버에서 실행중인 프로세스가 종료되지 않아서 좋습니다.
    • [tab]
      • tab키는 정말 중요합니다.
      • 디렉토리에서 abdefefsdsdfsdfsdcscs.sh 라는 파일을 실행하고 싶다면...
      • 다 타이핑 하지 마시고, 앞에 몇개만 타이핑한 뒤 [tab]키를 눌러보세요.
      • 만일 디렉토리에
        • abc123.txt, abc456.txt, ddd.txt
      • 이렇게 3개의 파일이 있다고 하면,
        • a 까지 치고 탭을 누르면
          • $ a [tab]
        • abc까지 자동 완성이 됩니다.
          • $ abc
        • 여기서 추가로 1을 타이핑하고 탭을 누르면
          • $ abc1 [tab]
        • abc123.txt가 자동완성이 됩니다.
          • $ abc123.txt
        • 왜냐면 abc로 시작하는 파일이 두개가 있기때문이죠. 즉, ddd.txt의 경우 훨씬 쉬워지죠. d로 시작하는 파일은 저것 하나뿐이므로...
          • $ d [tab]
        • 을 누르면
          • $ ddd.txt
        • 라고 자동 완성이 됩니다.

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