김서영

readme file

......@@ -27,26 +27,134 @@
- 장르 시각화 : matplot, Seaborn 패키지를 통한 시각화
## Model
- 데이터 수집 : [CMU Movie Summary Corpus][CMU]의 Detaset 42,306개, 뮤지컬 줄거리 255
- 데이터 수집 : [CMU Movie Summary Corpus][CMU]의 Detaset 42,306개, 뮤지컬 줄거리 307
- 데이터 전처리 : Detaset 토큰화, 불용어 처리 후 정수 인코딩
- 데이터 분석 : 의사결정나무 모델, RNN, k-nearest neighbor < 연구중
- 데이터 분석 : lstm
- 데이터 검증 : k-fold 교차검증을 활용하여 장르별 정확도를 확인
- 데이터 시각화 : 분석된 장르를 장르 단어 분포도로 시각화한다.
## Schedule
__3월__
- 주제 선정
__4월__
- 뮤지컬 줄거리 웹 크롤링
- 테스트 데이터 라벨링
__5월__
- 데이터 전처리
+ 토큰화 (완료)
+ 라벨링 (진행중)
- 데이터 시각화 : 분석된 뮤지컬 데이터를 장르 단위로 시각화한다.
## 과제 수행
### 데이터 수집
[ 장르 분류 모델 학습 데이터 ]
모델 학습을 위한 데이터는 뮤지컬 줄거리로는 양이 충분하지 못해 뮤지컬과 줄거리가 비슷한 영화 데이 터를 활용했습니다. http://www.cs.cmu.edu/~ark/personas/에서 영화 줄거리(영어) 데이터를 42,306개 수집했 습니다.
* 수집한 영화 줄거리 태깅 일부 : 각 영화 줄거리에는 데이터 제공 사이트에서 미리 장르를 다양하게 태깅 된 상태였습니다.
미리 태깅되어 있는 장르를 [‘romance’, ’fantasy’ ,‘thriller’, ‘drama’, ’ history’ , ‘social’ , ‘#N/A’] 같이 6개의 장르로 재분류했습니다.
재분류 방법은 위 표처럼 직접 모든(364개) 장르를 확인하며 위 6가지 정해놓은 장르 중 가장 유사한 장르 를 선택했습니다. 장르 분류가 애매한 경우는 ‘#N/A’으로 처리했습니다. 이러한 방법을 364개의 장르를 재 태깅했습니다.
재태깅된 장르를 기반으로 줄거리를 6가지 장르로 분류해서 장르별 csv파일로 추출했습니다
[ 모델 테스트 데이터 ]
브로드웨이 뮤지컬 줄거리를 크롤링을 통해 수집했습니다. 크롤링한 웹사이트는 https://broadwaymusicalhome.com/shows.htm 입니다. 총 307건의 줄거리를 크롤링하였습니다. (Beautifulsoup 패키지를 사용했습니다)
### 데이터 전처리
[ NLTK 라이브러리 활용 전처리 ]
장르가 NULL인 줄거리를 제외하고 약 35,000개의 줄거리 데이터 전처리를 진행했습니다. 이때단어 토큰화, 불용어 제거를 위해 NLTK 자연어처리 라이브러리를 사용했습니다.
* 전처리 소스코드 일부 (자세한 내용은 주석처리했습니다.)
```from tqdm import tqdm
all_vocab = {}
all_sentences = []
stop_words = set(stopwords.words('english'))
for i in tqdm(allplot):
all_sentences = word_tokenize(str(i)) # 단어 토큰화를 수행합니다.
result = []
for word in all_sentences:
word = word.lower() # 모든 단어를 소문자화하여 단어의 개수를 줄입니다.
if word not in stop_words: # 단어 토큰화 된 결과에 대해서 불용어를 제거합니다.
if len(word) > 2: # 단어 길이가 2이하인 경우에 대하여 추가로 단어를 제거합니다.
result.append(word)
if word not in all_vocab:
all_vocab[word] = 0
all_vocab[word] += 1
all_sentences.append(result)
all_vocab_sorted = sorted(all_vocab.items(), key = lambda x:x[1], reverse = True)
all_word_to_index = {}
i=0
for (word, frequency) in all_vocab_sorted :
if frequency > 1 : # 빈도수가 적은 단어는 제외한다.
i=i+1
all_word_to_index[word] = i
vocab_size = 15000 #상위 15000개 단어만 사용
words_frequency = [w for w,c in all_word_to_index.items() if c >= vocab_size + 1] # 인덱스가 15000 초과인 단어 제거
for w in words_frequency:
del all_word_to_index[w] # 해당 단어에 대한 인덱스 정보를 삭제
all_word_to_index['OOV'] = len(all_word_to_index) + 1
```
[ 전체 줄거리(전체 : 로맨스, 판타지, 스릴러, 역사 줄거리) 단어 인덱스 부여 ]
단어 사용 빈도수가 적은 단어는 제외하기 위해서 빈도순으로 인덱스를 부여했습니다. 15,000순위 미만인 단어 정보는 삭제했습니다.
[ 학습 데이터(= RM_train+TH_train+FN_train+HS_train ) 인코딩 ]
총 학습 데이터는 7000개로 ‘로맨스 : 스릴러 : 판타지 : 역사 = 2 : 2 : 2 : 1’의 비율로 맞추었습니다.
* 인덱스 부여 소스코드 일부 (자세한 내용은 주석 처리했습니다.)
### 모델 학습
다중 분류를 위해 순환 신경망 모델을 사용했습니다.
* LSTM 모델 구현 소스코드 (자세한 설명은 주석 처리했습니다.)
```from tensorflow.keras.preprocessing.sequence import pad_sequences
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, LSTM, Embedding
from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint
import numpy as np
M_test=Mu_encoded
M_test= np.array(M_test)
max_len = 230
X_train = pad_sequences(X_train, maxlen=max_len)
X_test = pad_sequences(X_test, maxlen=max_len)
model = Sequential()
model.add(Embedding(15002, 120))
model.add(LSTM(128))
model.add(Dense(4, activation='softmax'))
es = EarlyStopping(monitor='val_loss', mode='min', verbose=1, patience=4)
mc = ModelCheckpoint('best_model.h5', monitor='val_acc', mode='max', verbose=1, save_best_only=True)
X_train = np.array(X_train)
Y_train = np.array(Y_train)
X_test = np.array(X_test)
Y_test = np.array(Y_test)
model.compile(loss='categorical_crossentropy', optimizer='rmsprop', metrics=['acc'])
model.fit(X_train, Y_train, validation_data=(X_test, Y_test), epochs=7, batch_size=64, callbacks=[es, mc])
```
뮤지컬 데이터로 테스트 결과 많은 뮤지컬 작품이 로맨스로 분류된 것을 확인하였고, 스릴러가 가장 적은 비율로 분류된것을 확인했습니 다.
[ 실제 줄거리와 비교 ]
* 오페라의 유령 뮤지컬 줄거리의 장르를 예측한 결과 아래와 같이 로맨스로 정확하게 분류되었습니다. 오 페라의 유령같이 장르 특징이 뚜렷한 줄거리의 경우는 항상 정확한 분류가 이루어지는 것을 확인했습니다.
## 기대효과 및 활용방안
공식 티켓 판매처(인터파크, 예스 24공연 등)에도 뮤지컬 장르구분은 존재하지 않았습니다. 이런 사이트에서 축적된 공연 데이터를 통해 더 정확한 장르 구분을 한다면 일반인들의 뮤지컬에 대한 관심과 접근성을 높 일 수 있을것으로 기대합니다. 또한, 국내 창작 뮤지컬에 로맨스 뮤지컬 뿐만 아니라 다양한 장르가 존재함 을 알릴 수 있을 것입니다. 또한, 분류된 결과를 데이터베이스에 구축하고 웹사이트를 구현하면 뮤지컬 장 르 체계화에 도움이 될 것입니다.
## 결론 및 제언
이진 분류의 경우(예시- 로맨스 vs 판타지)에는 테스트이렇 데이터 정확도가 80%에 이르며 높은 정확도를 보였습니다. 하지만 다중 분류(4개)의 경우에 학습한 경우 정확도가 최대 63%까지만 이르며 모델의 성능을 높이지 못했습니다. 원인으로 첫째, 학습한 줄거리 데이터의 길이가 짧아 내용이 불충분한 경우가 있습니다. 둘째, 줄거리 길이는 충분하지만 분류를 위한 특성을 추출하기 어려운 단어가 많은 경우가 있었습니다.
프로젝트 진행 초반에는 한글 줄거리로 국내 뮤지컬 장르를 분류하고자 했습니다. 하지만 국내 뮤지컬 줄 거리의 대부분은 홍보용으로 내용에 대한 설명이 부실한 경우가 많아 분석에 어려움이 있었습니다. 충분한 한국어 뮤지컬 줄거리 데이터를 구하지 못해 영어 자연어처리로 주제가 변경된 부분이 아쉽습니다
### 역할 분담
양윤지 :
영화 데이터 수집&정리, 줄거리 데이터 장르 재태깅, Train,Test데이터 시각화&패딩, LSTM모델구현, 시각화
김서영 :
뮤지컬 데이터 수집&정리, 장르 데이터 전처리, Train,Test데이터 인코딩, LSTM모델로 학습, 테스트 데이터 학
습, 뮤지컬 데이터 분류,
시연 영상 링크 : https://youtu.be/EKjjQ0tHM4s
......
This file is too large to display.
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# <4월 20일 ~ 4월 24일>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"(1) 플레이DB 웹크롤링 -> 에러처리, csv파일로 옮기기 남음\n",
"\n",
"(2) **tf-idf**로 키워드 추출 고려 <br/>\n",
" -> 줄거리가 짧아서 단어 빈도수가 커야 6정도 ==> 따라서 장르별 대표작들 줄거리를 모아서 해보기로 계획\n",
"\n",
"(3) **word2vec**로 문맥이 비슷한 단어 파악하려했지만<br/>\n",
" ->학습 시간이 오래걸리는 문제 <br/>\n",
" ->단어 관계 파악 후에 어떻게 처리할지 고민,,<br/>\n",
"\n",
"---"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# <다음주 계획>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"-장르별 키워드 생각(크롤링x, 생각대로) <br/>\n",
"ex) 로맨스 = ['사랑','연인','애틋',........]<br/>\n",
"-가볍게 테스트<br/>\n",
"\n",
"\n",
"### 테스트 결과가 잘 나온다면,, 장르별 키워드 추출 모델 만들기\n",
"#### (잘 나오지 못하면,, 새로운 방법 고려)\n",
"---\n",
"\n",
"(1-1) **불용어 대표 사전 제작**<br/>\n",
"\n",
"- 뮤지컬정보관련된거 ('뮤지컬','제작사','콘텐츠', 뮤지컬이름, '창작','티켓', '매진'....)<br/>\n",
"- 고유 명사<br/>\n",
"- 시간관련 명사, 부사 모든것, (시작 ,나이, '최초','전날' '작년', OOOO년 OO월 OO일, '당시')<br/>\n",
"- 장소는 애매,, ('감옥'이런 장소는 유의미,,)(그런데 지명은 무의미)<br/>\n",
"- 감정이 아닌 단어 예를 들면 ('표현', '세상',...) <br/>\n",
"- 흔한 불용어('우리' ,,)<br/>\n",
"- 한국어가 아닌 단어(한자, 영어)<br/>\n",
"\n",
"(1-2) **장르 대표작 30편씩 고르기**<br/>\n",
"=> 장르별 대표작 30편씩은 줄거리 + 그 이외 기사, 대본 가능한대로 긁어와..<br/>\n",
"\n",
"*키워드 추출은 불용어 사전을 통해 불필요한 단어를 제외하고, 나머지 단어들의 사용된 빈도를 기준으로함.<br/>\n",
"*이때 키워드를 사전 api와 비교해서 나오지 않는것은 이름으로 간주하고 제거.<br/>\n",
"\n",
"(1-3) 장르 대표작들을 통해 **‘장르별 대표 키워드 사전 만들기’** => 이때 키워드가 포함된 문장도 추출<br/>\n",
"(왜냐하면 word2vec을 사용하려면 문장 필요)<br/>"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.6"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1. 불용어 처리\n",
"## 2. 어근 추출\n",
"## 3. 인코딩\n",
"## 4. 패딩 \n",
"\n",
"## 5. "
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.3"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
No preview for this file type
No preview for this file type