nlp 프로젝트로 무언가 하나 완성하고 싶어서 주제를 찾다가 가사 감성 분석을 해보면 어떨까? 라는 생각이 들었다. 멜론으로 가서 장르를 살펴보는데 인디음악이 눈에 들어왔다. 한때 인디음악을 했던 사람으로.. 사실 인디음악은 조금 생소 할 수도 있어서 인디음악 가사의 감성분류를 해서 감성별로 추천해주는걸 해보면 좋을 것 같다는 생각이 들었다. 이것저것 자료를 찾아보며 프로젝트 그림을 대충 그려봤는데 가사를 모으고 형태소 분석을 한 후 word2vec 유사도를 이용해 감성 사전을 구축하고 다시 그걸 이용해 새로운 가사 문장을 학습하는 transformer-based 모델을 만들려고 했다.
데이터 수집
먼저 데이터 수집은 멜론을 이용했다. 인디음악에도 스타일별로 하위 장르가 나뉘는데 바이브나 벅스 등등 다른 곳은 하위 스타일을 나눠놓은 곳이 없어서 멜론으로 결정했다.
셀레니움 크롤러 제작
제목과 가수명은 현재 페이지에서 바로 얻을 수 있지만 가사는 상세정보 페이지로 이동해야 볼 수 있다. 각 노래에는 고유 지정번호가 존재하는데 이를 이용해 상세페이지로 이동해 가사를 모을 수 있었다. 제목을 모을 때 고유번호를 같이 리스트에 저장한 후 나중에 리스트를 돌면서 각 상세페이지에 들어가서 가사를 모으는 방식으로 작업했다.
참고로 두번 정도 크롤링을 마치니 세번째부터 멜론에서 차단을 했는지 수집이 안되었다.. 아마 천개 이상..? 정도 접근하면 차단을 하는 것 같다. 몇분 정도 기다렸다가 다시 하거나 우회해서 차단을 풀 수 있는 방법을 써야 한다.
이제 다음 과정은 수집한 데이터를 살펴보고 필요한 전처리 작업을 할 차례이다.
데이터 전처리
크롤링한 데이터는 엑셀로 곡제목, 가수, 가사 컬럼으로 저장했다. 엑셀파일을 데이터프레임으로 불러와서 특수문자를 제거하고 문장을 나눠줬다. 가사가 없는 데이터도 몇개 있어서 지워줬다. 가사 특성상 문장이 짧고 특수문자 같은게 없어서 크게 만질 건 없었다.
형태소 분석 & 불용어 제거
한글 형태소 분석기는 여러가지가 있는데 꼬꼬마는 시간이 너무 오래 걸려서 패스하고 okt는 댓글 같은 곳에 더 맞을 것 같아서 패스, 속도 빠르고 성능도 좋은 mecab 을 사용했다. mecab으로 품사태깅을 해서 각 품사별로 어떤 단어가 있는지 확인을 먼저 해보았다. 불용어를 제거해야 하는데 여러 자료를 찾아보니 검증되고 통일된 방식이 딱히 있진 않고 보통 빈도수를 체크하거나 조사/접사 등 중요하지 않은 단어들을 삭제하는 방식을 따른다고 한다. 이것저것 시도해봤는데 한글자 단어가 남게 되면 이게 어디서 떨어져 나온건지 애매해져서 명사/동사/형용사 위주로 남기고 한글자 단어도 전부 불용어처리 했다.
여기서 문제점이 가사가 영어가 섞인 가사가 정말 많다는 점이다. 특히 가사 전체가 영어로 된 경우 해당 데이터를 포함해서 워드투벡을 학습하니 이상한 영단어가 자꾸 들러붙는 것이 보였다. 구글, 네이버 번역 api를 사용해서 번역을 돌리려 했는데 무료 버전으로는 하루 제한량이 너무 적어서 그냥 포기하고 가사 전체가 영어인 것은 drop하고 몇 문장정도 포함된 것은 놔뒀다.
불용어 제거 전에는 총 단어 개수가 29만개에 평균 단어개수가 226개 정도 였는데 제거 후 10만개 정도로 줄고 평균 단어 개수로 82개로 줄었다. 노래 가사는 반복 문장이 많다는 것이 특징 중 하나라서 80개의 단어에도 중복이 굉장히 많았고 중복 단어를 뺀다면 아마 길이는 더욱 줄어들 것이다.
불용어 제거후 고빈도 단어를 워드클라우드로 나타내보았다. 노랫말 답게 사랑, 마음, 생각 등등 단어들만 봐도 왠지모르게 서정적이고 시적인 느낌이 든다. (여기서부터 문제 시작되었..)
Word2Vec
문장의 앞뒤 맥락(window)을 이용해 단어끼리의 관계를 파악하는 알고리즘이다. 위에서 토크나이즈한 데이터로 워드투벡을 학습하고 이것저것 유사도를 확인해보았다. 여기서부터 본격적으로 문제가 발생했다.. 감정분류를 위해 이것저것 구글링을 해보면서 정보를 찾았다.
표를 보면 알겠지만 감정을 세분화해서 분류 해놓았다. 하지만 놀라움이라던지 공포라던지..? 그런 감정의 노래는 극히 드물다. 노래는 대부분 정말 거의 대부분의 노래가 사랑에 대한 노래이고 그나마 인디음악은 조금 더 일상이나 자아, 사회적 이야기가 포함되어 있다. 그래서 사랑, 설렘 등 기쁜 분류 / 이별, 추억 등 슬픈 분류 / 우울, 새벽, 힐링 분류로 키워드를 잡아서 이에 대한 유사도를 찾아보았다. 하지만 가사 특성상 각 노래마다 분위기가 비슷한 핵심 단어가 너무 겹치고, 단어 개수도 적은데다가 인디음악이라는 틀 안으로 좁아지다보니 전반적으로 더욱 가사들이 비슷해서 분류가 크게 되질 않았다. 키워드를 여러개 두고 유사도를 계산해서 각 카테고리로 들어갈 수 있게 함수를 짰는데 결과를 확인해보면 거의 한두개의 카테고리에 몰려버렸다.
그림을 보면 1번과 8번 카테고리에 몇만개씩 몰려있는 것을 볼 수 있다.. 정말 다양하게 키워드도 바꿔보고 계산도 단어단어 문장단어로 바꿔봤지만 분류가 제대로 되지 않아서 토픽 모델링을 한번 해봤다.
토픽 모델링
단어나 문서의 집합에서 숨겨진 주제를 찾아내 문서나 키워드별로 묶어주는 알고리즘이다. gensim의 lda 모델을 써서 토픽을 뽑았다.
결과를 보면서 위에 겪었던 문제점을 더욱 확실하게 알 수 있었다. 토픽을 2개에서부터 100개까지 다양하게 줘서 뽑았는데 비슷한 단어를 가진 노랫말이 너무 많고 주제가 다 비슷한게 한 눈에 보였다. 거의 사랑노래에 누군가를 생각하고 이 순간, 이 기분 등등.. 분류라는 작업을 하려면 어느정도 집합 안에서 기준이 될만한 크게 차이가 나는 지점이 필요한데 그런 경계가 모호했다.
결론
1. 인디음악 특성상 결이 비슷비슷해서 분류 할만한 기준점을 찾기 힘듦(노래의 특성이기도. 사랑관련 키워드가 너무나 많다)
2. 불용어를 제거하고 나니 가사가 너무 짧아졌고 반복이 많은 특성 때문에 반복단어를 제외하면 남는 단어가 몇 없어서 학습이 잘안됨.
word2vec으로 감성 사전 구축하는 것은 패스하고 td-idf 나 다른 방식으로 접근해야 할 것 같다.