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

Lyrics for text processing

Recently I'm looking into lyrics before implementing music lyric processing codes. 
There are many aspects that make song lyrics different from usual text, which are quite interesting and going to give me some pain. Few of them are introduced as below. Please enjoy!

  • Incomplete sentence
example:
Scars make us who we are
Hearts and homes are broken, broken
Far, we could go so far
With our minds wide open, open

example:
Love you forever and forever 
Love you with all my heart 
Love you whenever we're together 
Love you when we're apart 

In terms of grammar, it's easy to find some incomplete sentences. What makes them trickier is however, that they don't have proper punctuation marks. It would be okay for word-level processing (though there is still some issues such as negation..), but sentence-level processing would require a huge pre-processing. New-line character doesn't always indicate the end of the sentences, of course!



  • Use of arbitrary special characters
example:
사르륵녹은 그대를 보면 사랑을 느끼죠
oh so beautiful 사랑을 말해봐요 
매일 너와 함께! ~~해!~~~
조금더 다가와줘
example:
다가와- 느껴봐 음- 
It may be more about Korean speaker's writing habit. Korean (and Japanese) prefers to use '~' than '-'. In some cases, -- is automatically 'corrected' to  , a long dash, which makes the problem more complex. (Not that much, actually, since all of them should be just ignored as a stopword.)

  •  Multiple languages
example:
簡単に
(칸탄니)
간단히
You make me happy
一言で
(히토코토데)
한마디로
夕べの すれ違い
(유우베노 스레치가이)
저녁때의 엇갈림
まだまだ 埋まってない
(마다마다 우맛테나이)
아직아직 채워지지 않아
So I'm waiting ソワソワ Oh
(소와소와)
안절부절

The example above is an extreme one, written with Korean, Japanese, and English (+Korean interpretation for Japanese sentences in parentheses). However, it's very common to use English words in Korean lyrics.


  • Corruption by other information
example:
[Chorus]
Yeah (yeah) 
Shorty got down to come and get me [x2]

There are many non-lyric texts such as [Chorus] or [x2] to help the viewer, while giving me pain.


  • So many Yeah's and Oh's
There are so many Yeah's and Oh's in lyrics. I'm not sure what should I do with them. 





  • To summarise, these are the lists that I think I should add to usual stopwords list to process lyrics.
    • Some special characters (which should be already included in stopwords list)
      • * ** *** + " ' ` . .. ... / ~ ~~ ~~~ ~~~~ ~~~~~ ? - -- --- ^, ^^, a, b, c,...z,...
    • Unnecessary (and common) words that are included in lyrics texts
      • 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
      • (Korean words:)간주, 후렴, 반복, 가사입력, 출처, 작성자, 악보, 연주곡, 간주중



[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
      • 간주, 후렴, 반복, 가사입력, 출처, 작성자, 악보, 연주곡, 간주중 


Wednesday, July 8, 2015

[Korean] 컨볼루션 뉴럴 넷 Convolutional Neural Network 자세한 설명

키워드: 딥러닝, 컨볼루션 넷, 컨브넷, cnn, convnet, convolutional neural network, deep learning
참고자료: keras

keras의 예제 파일 중 cifar10.py에 구현된 간단한 컨브넷을 설명드리겠습니다.
우선 이 작업은 손으로 쓴 숫자 0~9를 구분하는 것을 목적으로 합니다. 즉 Hand-written digit recognition task입니다.

모델 부분 코드만 보면 아래와 같습니다.

model = Sequential()
model.add(Convolution2D(32, 3, 3, 3, border_mode='full'))model.add(Activation('relu'))model.add(Convolution2D(32, 32, 3, 3))
model.add(Activation(
'relu'))
model.add(MaxPooling2D(poolsize=(
2, 2)))
model.add(Dropout(
0.25))
model.add(Convolution2D(
64, 32, 3, 3, border_mode='full'))
model.add(Activation(
'relu'))
model.add(Convolution2D(
64, 64, 3, 3))
model.add(Activation(
'relu'))
model.add(MaxPooling2D(poolsize=(
2, 2)))
model.add(Dropout(
0.25))
#------절취선--------
model.add(Flatten())
model.add(Dense(
64*8*8, 256))
model.add(Activation(
'relu'))
model.add(Dropout(0.5))
model.add(Dense(256, 10))
model.add(Activation('softmax'))
sgd = SGD(lr=0.1, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='categorical_crossentropy', optimizer=sgd)

  • 전체 구조
전체 구조를 간단히 설명하면 이렇습니다. ReLU와 드롭아웃은 설명에서 빼겠습니다.
모든 convolutional layer에서 이미지 패치는 3x3입니다.
맥스풀링도 없다고 가정하면 전체 과정은,

- 이미지 파일 로딩 (크기:  32x32, RGB채널)
- 3-32 convolutional layer
- 32-32 conv layer
- 32-64 conv layer
- 64-64 conv layer
- flatten (벡터 형태로 reshape)
- (64*8*8) - 256 fully connected layer
- 256 - 10 fully connected layer
- softmax + making decision
입니다.


  • 파라미터 설명 ---절취선 이전---
model.add(Convolution2D(32, 3, 3, 3, border_mode='full'))
(32, 3, 3, 3, border_mode='full')
- border_mode: full, valid가 있고 그 중간격인 same도 매트랩에선 지원합니다. 자세한 설명 생략. 컨볼루션 할때 이미지 끄트머리; 가장자리를 어떻게 처리할지 하는 내용입니다.
- (32, 3, 3, 3)에서 ...
- - 뒤의 3,3은 이미지 패치 사이즈입니다. 즉 (3, 3) 크기의 패치가 이미지를 쭉 훑고 다니게 됩니다.
- - 앞의 (32, 3)은, 3개 채널의 이미지 stack을 32개의 이미지 stack으로 만들어주겠다는 이야기입니다. 즉, 이 부분에서는 총 32개의 피쳐를 추출하게 됩니다. 그 추출은 (3x3)의 이미지 패치의 값 (=9개의 계수, weight parameter)를 learning하여 사용합니다. 따라서 이 과정을 거치면 32x32의 이미지(의 피쳐)가 32개가 쌓이게 됩니다. 
- - 같은걸 (32, 32)로 또 해줍니다.
- - 이번엔 (32, 64)로 또 해줍니다.
- - 마지막으로 (64, 64)로 또 해줍니다. 이런 과정을 거쳐서 이미지는 Low-level feature (직선, 곡선 등의 단순한 피쳐)에서 high-level feature (눈 모양이 있는지, 얼굴 모양이 있는지 등등..)로 변환됩니다.

"그런데말입니다,"
중간에 Max-Pooling이 두 번 있었죠. 그래서 이미지의 크기는 (32x32)가 아니라 (8x8)이 됩니다.

여기까지를 feature learning이라고 생각할 수 있습니다. 

  • 파라미터 설명 ---절취선 이후---
여기서부터는 classification에 가까운 단계입니다.
앞서 convolutional layer를 여러 단계 거친 결과 8x8 이미지가 총 64개가 쌓여있게 됩니다. 즉 전체 데이타 포인트는 64*8*8=4096개가 됩니다.

Dense(64*8*8, 512) 에서는 입력 4096개, 출력 512개의 fully-connected 레이어를 추가합니다.
Dense(512, 10)는 입력 512개, 출력 10개의 레이어를 추가합니다.
여기서 출력 유닛 10개는 각각 0~9의 숫자를 나타냅니다.
그 뒤엔 softmax로 최종 결과가 나옵니다.


  • 그림으로 이해하기


  • 파라미터 개수
패치 사이즈는 9 (3x3)
스택 사이즈는 (3-32) - (32-32) - (32-64) - (64-64) - now fully connected - ( 64*8*8 - 512) - (512 - 10 )
따라서 각각 단계에서 파라미터 개수는 입력 채널 개수 * 출력 채널 개수 * 이미지 패치 크기 가 됩니다. 숫자로 쓰면,
#parameters: 3*32*9 + 32*32*9 + 32*64*9 + 64*64*9 + (64*8*8*)*512 + 512*10

= 288 + 288 + 576 + 576 + 2097152 + 5120

이 된다. 

해당 코드에서 데이타는 트레이닝에 45000개를 불러오고, 회전해서 x20, 좌우 뒤집어서 x2 등의 데이타 뻥튀기 과정을 거치면 대략 200만개가 된다. 시스템의 파라미터 개수와 데이타 개수를 참고 바람.

------

정리할 겸 작성한 내용이니 틀린 부분이 있다면 알려주세요!