indexing.py 8.73 KB
#!/usr/bin/env python
# coding: utf-8

# In[1]:


import pandas as pd
from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize
import re


thriller_plot = pd.read_csv('/Users/yangyoonji/Documents/2020-1/2020-dataCapstone/data/moviedata/moviePlot/thrillerPlot.csv')
drama_plot = pd.read_csv('/Users/yangyoonji/Documents/2020-1/2020-dataCapstone/data/moviedata/moviePlot/dramaPlot.csv')
fantasy_plot = pd.read_csv('/Users/yangyoonji/Documents/2020-1/2020-dataCapstone/data/moviedata/moviePlot/fantasyPlot.csv')
history_plot = pd.read_csv('/Users/yangyoonji/Documents/2020-1/2020-dataCapstone/data/moviedata/moviePlot/historyPlot.csv')
social_plot = pd.read_csv('/Users/yangyoonji/Documents/2020-1/2020-dataCapstone/data/moviedata/moviePlot/socialPlot.csv')
romance_plot = pd.read_csv('/Users/yangyoonji/Documents/2020-1/2020-dataCapstone/data/moviedata/moviePlot/romancePlot.csv')
# /Users/김서영/Desktop/datacap/data/moviedata/moviePlot/romancePlot.csv

print(len(romance_plot)) #5699 ==> train 2500 test 2500
print(len(thriller_plot)) #9823 ==> train 2500 test 2500
print(len(drama_plot))
print(len(fantasy_plot))
print(len(history_plot))
print(len(social_plot))

train_data_size = 1463
test_data_size = 1463

#전처리(1) 전부 소문자로 변환


#romance_plot.줄거리 = romance_plot.줄거리.str.lower()
#thriller_plot.줄거리 = thriller_plot.줄거리.str.lower()

#전처리(1-1) 데이터 csv 파일로 옮기기
#romance_plot 2899개 train_data로 to_csv || 2800개 test_data로 to_csv
#thriller_plot 2899개 train_data로 to_csv || 2800개 test_data로 to_csv


# In[2]:


RM = [[] for _ in range(5699)]
for i in range(5699):
    RM[i].append(''.join(thriller_plot.줄거리[i]))
    
TH = [[] for _ in range(9823)]
for i in range(9823):
    TH[i].append(''.join(thriller_plot.줄거리[i]))

FN = [[] for _ in range(2727)]
for i in range(2727):
    FN[i].append(''.join(fantasy_plot.줄거리[i]))
    
HS = [[] for _ in range(1498)]
for i in range(1498):
    HS[i].append(''.join(history_plot.줄거리[i]))
    
SC = [[] for _ in range(1464)]
for i in range(1464):
    SC[i].append(''.join(social_plot.줄거리[i]))

DR = [[] for _ in range(14019)]
for i in range(14019):
    DR[i].append(''.join(drama_plot.줄거리[i]))
   


allplot = RM+TH+FN+HS+SC+DR #모든 드라마 줄거리


# In[4]:


print(len(allplot))


# ## 모든 장르 줄거리 

# In[5]:


# 토큰화+전처리(3) 전체 불용어 처리
# 전체 플롯
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) 


# In[6]:


all_vocab_sorted = sorted(all_vocab.items(), key = lambda x:x[1], reverse = True)

#전처리(4) 인덱스 부여
all_word_to_index = {}
i=0
for (word, frequency) in all_vocab_sorted :
    if frequency > 1 : # 정제(Cleaning) 챕터에서 언급했듯이 빈도수가 적은 단어는 제외한다.
        i=i+1
        all_word_to_index[word] = i
#print(all_word_to_index)

vocab_size = 15000 #상위 15000개 단어만 사용
words_frequency = [w for w,c in all_word_to_index.items() if c >= vocab_size + 1] # 인덱스가 200 초과인 단어 제거
for w in words_frequency:
    del all_word_to_index[w] # 해당 단어에 대한 인덱스 정보를 삭제

    
all_word_to_index['OOV'] = len(all_word_to_index) + 1


# ## 로맨스

# In[7]:


# 토큰화+전처리(3) 불용어 처리
# 로맨스 플롯

vocab_r = {} 
RMsentences = []
RMstop_words = set(stopwords.words('english'))

for i in tqdm(RM):
    RMsentence = word_tokenize(str(i)) # 단어 토큰화를 수행합니다.
    result = []

    for word in RMsentence: 
        word = word.lower() # 모든 단어를 소문자화하여 단어의 개수를 줄입니다.
        if word not in RMstop_words: # 단어 토큰화 된 결과에 대해서 불용어를 제거합니다.
            if len(word) > 2: # 단어 길이가 2이하인 경우에 대하여 추가로 단어를 제거합니다.
                result.append(word)
                if word not in vocab_r:
                    vocab_r[word] = 0 
                vocab_r[word] += 1
    RMsentences.append(result) 

R_encoded = []
for s in RMsentences:
    temp = []
    for w in s:
        try:
            temp.append(all_word_to_index[w])
        except KeyError:
            temp.append(all_word_to_index['OOV'])
    R_encoded.append(temp)


# ## 스릴러

# In[8]:


# 토큰화+전처리(3) 불용어 처리
# 스릴러 플롯

vocab_th = {} 
THsentences = []
THstop_words = set(stopwords.words('english'))

for i in tqdm(TH):
 
    THsentence = word_tokenize(str(i)) # 단어 토큰화를 수행합니다.
    result = []

    for word in THsentence: 
        word = word.lower() # 모든 단어를 소문자화하여 단어의 개수를 줄입니다.
        if word not in THstop_words: # 단어 토큰화 된 결과에 대해서 불용어를 제거합니다.
            if len(word) > 2: # 단어 길이가 2이하인 경우에 대하여 추가로 단어를 제거합니다.
                result.append(word)
                if word not in vocab_th:
                    vocab_th[word] = 0 
                vocab_th[word] += 1
    THsentences.append(result) 

TH_encoded = []
for s in THsentences:
    temp = []
    for w in s:
        try:
            temp.append(all_word_to_index[w])
        except KeyError:
            temp.append(all_word_to_index['OOV'])
    TH_encoded.append(temp)


# In[ ]:


#전처리 방법에는 NLTK의 FreqDist, 케라스(Keras) 토크나이저도 사용 가능.


# 로맨스 플롯, 스릴러 따로 토큰화 해서 x train에 넣을지... 고민중
# 
# 이번주 : 전처리 완료, 
# 이번 달 목표 : 뮤지컬 장르 분류 << 다양한 모델 사용해보기.
# 
# 6월에 교차검증 및 장르 시각화 설계까지.
# 
# 다음주 :  2진분류(LSTM) 완료, RNN 분류기 만들어보기

# ## 학습데이터

# In[ ]:


# 영화 줄거리는 X_train에, 장르 정보는 y_train에 저장된다.
# 테스트용 줄거리 X_test에, 테스트용 줄거리의 장르 정보는 y_test에 저장된다.
#맞춰서 저장하기. (진행중)

#X_train = train_sc_df.dropna().drop(‘trade_price_idx_value’, axis=1)


# In[9]:


X_train = []
Y_train = []  #0 : romance, 1 : thriller 
for i in range(train_data_size):
    X_train.append(R_encoded[i])
    Y_train.append(0)
    X_train.append(TH_encoded[i])
    Y_train.append(1)


# In[10]:


#print(X_train[2])
#print(Y_train[2])


# In[11]:


import matplotlib.pyplot as plt

len_result = [len(s) for s in X_train]
print("줄거리 최대 길이 : ",max(len_result))
print("줄거리 평균 길이 : ",sum(len_result)/len(len_result))

plt.subplot(1,2,1)
plt.boxplot(len_result)
plt.subplot(1,2,2)
plt.hist(len_result, bins=50)
plt.show()


# ## 테스트 데이터
# 
# 

# In[12]:


X_test = []
Y_test = []  #0 : romance, 1 : thriller 
for i in range(test_data_size):
    X_test.append(R_encoded[train_data_size+i])
    Y_test.append(0)
    X_test.append(TH_encoded[train_data_size+i])
    Y_test.append(1)
    
    


# In[13]:


import matplotlib.pyplot as plt

len_result = [len(s) for s in X_test]
print("줄거리 최대 길이 : ",max(len_result))
print("줄거리 평균 길이 : ",sum(len_result)/len(len_result))

plt.subplot(1,2,1)
plt.boxplot(len_result)
plt.subplot(1,2,2)
plt.hist(len_result, bins=50)
plt.show()


# ## LSTM 분류 
# 

# In[14]:


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

max_len = 100
X_train = pad_sequences(X_train, maxlen=max_len)
X_test = pad_sequences(X_train, maxlen=max_len)


# In[ ]:


model = Sequential()
model.add(Embedding(5000, 120))
model.add(LSTM(120))
model.add(Dense(1, activation='sigmoid'))

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)

model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['acc'])
model.fit(X_train, Y_train, validation_data=(X_test, Y_test), epochs=10, batch_size=64, callbacks=[es, mc])





# In[ ]:





# In[ ]: