[자연어처리] 댓글 데이터 전처리 (1) 에서 이어서 가자.
1. 토큰화
!pip install konlpy
from konlpy.tag import Okt
한글 형태소 분석기를 import 하고,
불용어를 만들어준다. ex) 조사
stopwords = ['의','가','이','은','들','는','좀','잘','걍','과','도','를','으로','자','에','와','한','하다']
이후 토큰화 객체를 만들고 데이터프레임의 댓글 내용 중 불용어를 제거한다.
okt = Okt() # 토큰화 객체 생성
df_token = []
for sentence in tqdm(df['댓글 내용']):
tokenized = okt.morphs(sentence, stem=True) # 토큰화
stopwords_removed_sentence = [word for word in tokenized if not word in stopwords] # 불용어 제거
df_token.append(stopwords_removed_sentence)
2. 정수 인코딩
컴퓨터가 텍스트를 분석하기 위해선 토큰화를 마친 댓글 데이터를 정수 형태(0, 1)로 인코딩 해야한다.
일단 토큰화 객체를 집합으로 만들어보자.
tokenizer = Tokenizer() # 토큰화 객체 집합 생성
tokenizer.fit_on_texts(df_token)
print(tokenizer.word_index)
위와 같이 각각의 토큰화 객체에 고유한 정수가 부여되었다.
여기서 '조' 는 1 을 부여받았고, '가나' 는 2, '월드컵' 은 3을 부여받았는데, 이 숫자는 단어 등장의 빈도 수 별로 부여된 것이다. 즉 '조' 라는 단어가 가장 많이 나왔고, 그 다음은 '가나', '월드컵' 이런 순서인 것이다.
집합의 총 원소의 수는 399개, 약 400개인데, 이 중에서 한번 내지는 두번정도 등장한 즉 빈도 수가 낮은 원소는 자연어 처리에서 배제하는게 맞는데.. 400개는 너무 적기 때문에.. 아마 힘들 것 같다..
threshold = 2
total_cnt = len(tokenizer.word_index) # 단어의 수
rare_cnt = 0 # 등장 빈도수가 threshold보다 작은 단어의 개수를 카운트
total_freq = 0 # 훈련 데이터의 전체 단어 빈도수 총 합
rare_freq = 0 # 등장 빈도수가 threshold보다 작은 단어의 등장 빈도수의 총 합
# 단어와 빈도수의 쌍(pair)을 key와 value로 받는다.
for key, value in tokenizer.word_counts.items():
total_freq = total_freq + value
# 단어의 등장 빈도수가 threshold보다 작으면
if(value < threshold):
rare_cnt = rare_cnt + 1
rare_freq = rare_freq + value
print('단어 집합(vocabulary)의 크기 :',total_cnt)
print('등장 빈도가 %s번 이하인 희귀 단어의 수: %s'%(threshold - 1, rare_cnt))
print("단어 집합에서 희귀 단어의 비율:", (rare_cnt / total_cnt)*100)
print("전체 등장 빈도에서 희귀 단어 등장 빈도 비율:", (rare_freq / total_freq)*100)
희귀 단어 등장 빈도가 40퍼다.. 뭐 거의 절반이고..
그냥 희귀 단어 배제하지 말고 진행합시다.
단어 집합의 크기는 399개인데, 이를 케라스 토크나이저의 인자로 넘겨주고 텍스트 시퀀스를 정수 시퀀스로 변환한다.
tokenizer = Tokenizer(total_cnt)
tokenizer.fit_on_texts(df_token)
df_train = tokenizer.texts_to_sequences(df_token)
print(df_train[:2])
상위의 2개 정도를 보면 정수 인코딩이 잘 된 것을 볼 수 있다.
3. 패딩
각각의 댓글이 길이가 다르므로 길이를 같게해주는 패딩 작업을 해야한다.
일단 댓글 데이터의 전체적인 길이를 알아보면,
print('댓글의 최대 길이 :',max(len(review) for review in df_train))
print('댓글의 평균 길이 :',sum(map(len, df_train))/len(df_train))
plt.hist([len(review) for review in df_train], bins=50)
plt.xlabel('review length')
plt.ylabel('number of review')
plt.show()
댓글 그래프를 봤을 때, 평균적으로 댓글은 20~40 글자 인 것 같다.
def below_threshold_len(max_len, nested_list):
count = 0
for sentence in nested_list:
if(len(sentence) <= max_len):
count = count + 1
print('전체 샘플 중 길이가 %s 이하인 샘플의 비율: %s'%(max_len, (count / len(nested_list))*100))
길이를 40 글자로 하고 댓글의 비율을 확인했을 때,
max_len = 40
below_threshold_len(max_len, df_train)
댓글 데이터 중 93.75%의 댓글이 40이하의 길이를 가지는 것을 확인했다. 모든 샘플의 길이를 40으로 맞춘다.
df_train = pad_sequences(df_train, maxlen=max_len)
'캡스톤 > 자연어처리' 카테고리의 다른 글
[자연어처리] LSTM으로 감성 분석하기 (0) | 2022.04.05 |
---|---|
[자연어처리] No module named 'konlpy' 에러 (0) | 2022.04.05 |
[자연어처리] 댓글 데이터 전처리 (1) (0) | 2022.04.04 |
[자연어처리] 댓글 데이터 엑셀에 저장하기 (0) | 2022.04.03 |
[자연어처리] 유튜브 API 를 사용해 영상 댓글 데이터 가져오기 (0) | 2022.04.03 |