AI

[뛰어보자!] BERT_ 네이버 리뷰분석

brebb 2022. 8. 10. 02:24

책만 읽으니까 도통 글만 봐서 머리에 잘 안 남아... ㅠㅠ 

실제 해보기로 했다. 

Colab을 처음으로 실행시켜 더듬더듬.. 내가 코드를 짜진 못하지만 

짜여 있는 걸 분석하고 실행시켜 보면서 원리를 이해하려고 많이 노력했다. 

 

2020년, 2019년 것들은 실행시켜보니 최신 버전들이 아니고 불러올 수 없는 라이브러리가 꽤 있어서 오류가 많이 나더라. 

여러 가지를 찾아보다가 아래 url을 활용하여 BERT에 대해 이해해보기로 했다. 

 

이론만 봐서 남에게 설명할 때 더듬더듬했던 나에게.. 그래도 한 문장으로 설명은 해줄 수 있게 해 준 너무나 고마운 포스팅이다! 😊

했던 단계들, 그리고 단계들로 이해한 설명을 적어보려고 한다.

 

아래 포스팅 내용은 공유된 url을 기반으로 학습한 부분들로 이루어져 있습니다.

https://github.com/kimwoonggon/publicservant_AI/blob/master/2_(Hugging%2B%ED%95%9C%EA%B8%80BERT)%EB%84%A4%EC%9D%B4%EB%B2%84%20%EA%B0%90%EC%84%B1%EB%B6%84%EC%84%9D%2090%25%20%EB%8B%AC%EC%84%B1%ED%95%98%EA%B8%B0.ipynb 

 위 모델은 여러 리뷰를 학습하여 이 리뷰가 긍정적인지, 부정적인지를 판별해주는 AI이다. 
AI 모델링 하는순서는 아래와 같다. 

1) 네이버 감성분석 데이터 불러오기 및 전처리

huggingface 패키지를 Colab에 설치했다. 

여기서 huggingface 는 자연어 처리 인공지능 모델에서, BERT 모델 같은 트랜스포머 모델들을 쉽게 다룰 수 있게 해주는 패키지라고 한다. 

구글 드라이브와 Colab을 연동하고, 예제에서 사용할 네이버 영화 감상 분석 데이터를 다운로드해줬다. 

 

# 구글드라이브 연동
import os
from google.colab import drive
drive.mount('/content/gdrive/')
# 네이버 영화 감성분석 데이터 다운로드 
!git clone https://github.com/e9t/nsmc.git

다음으로, 딥러닝 훈련에 사용 할 train 데이터와 test 데이터를 pandas dataframe 형식으로 불러왔다.

학습을 시키기 위해선 훈련과 테스트 데이터를 커플로 만들어줘야 한다. 

 

train = pd.read_table("nsmc/"+"ratings_train.txt")
test = pd.read_table("nsmc/"+"ratings_test.txt")

 

짠!

위에 내용들을 입력하고 나면, 이런 출력 값을 얻을 수 있다.

리뷰의 고유 id값과 리뷰 내용을 document로 해주고, label에 있는 것은 1은 부정, 0은 긍정을 발라놓은 것을 볼 수 있다. 

 

 

 

2) BERT 인풋 만들기

BERT가 기본적으로 다 영어라... 한글 데이터들을 분석 하려면 많은 언어를 지원한 BERT모델을 사용해야 해서 무겁다고 한다.

그래서 내가 공부한 글에서는 SKT에서 만든 KoBERT를 사용하여 학습 시켰다.

위에서 언급한 huggingface에서 토크나이저를 불러온다.

아직 잘 모르겠지만 huggingface에서는 토크나이저를 쉽게 불러올 수 있다고 한다. 

 

나도 몰랐는데, tokenizer 사용방법은 

tokenizer.encode => 문장을 버트 모델의 인풋 토큰 값으로 바꿔줌tokenizer.tokenize => 문장을 토큰화

 

tokenizer = KoBertTokenizer.from_pretrained('monologg/kobert')

 

BERT의 input을 본격적으로 할 텐데, 토큰, 세그멘트, 마스크로 나뉜다. 

3개의 값들이 BERT모형에 들어가서 그 모형에 맞게 임베딩이 되는 원리라고 한다. (무슨 소리인지는 모르겠지만, 3단계 별로 나오는 출력 값들이 신기했다.)

Token : 단어를 단어 사전의 위치 값으로 표현

Segment: 버트 모형에서 문장이 앞 문장인지, 뒷 문장인지 표현

Mask : 문장이 유효한 값인지, 아니면 유효하지 않은 값이라 패딩 값으로 채운 것인지를 나타냄
문장이 유효한 값이면 1, 유효하지 않은 값이면 0

 

"전율을 일으키는 영화. 다시 보고 싶은 영화"라는 문장을 가지고 예를 들면,

 


토큰 인풋 : [101, 9665, 119183, 10622, 9641, 119185, 66815, 42428, 119, 25805, 98199, 119088, 10892, 42428, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

세그먼트 인풋 : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
마스크 인풋 : [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

 

이제, 네이버 영화 평가 문장들을 버트 인풋으로 바꾸는 작업을 한다. 
문장이 토큰 인풋, 세그먼트 인풋, 마스크 인풋으로 변환되는데, huggingface에서는 토큰 인풋, 마스크 인풋, 세그먼트 인풋 순이라고 한다. 

3) 버트를 활용한 감성 분석 모델 만들기

 모델 만드는 작업 본격화에 들어간다. 

많은 정의들을 해준다. 

model = TFBertModel.from_pretrained("monologg/kobert", from_pt=True)
# 토큰 인풋, 마스크 인풋, 세그먼트 인풋 정의
token_inputs = tf.keras.layers.Input((SEQ_LEN,), dtype=tf.int32, name='input_word_ids')
mask_inputs = tf.keras.layers.Input((SEQ_LEN,), dtype=tf.int32, name='input_masks')
segment_inputs = tf.keras.layers.Input((SEQ_LEN,), dtype=tf.int32, name='input_segment')
# 인풋이 [토큰, 마스크, 세그먼트]인 모델 정의
bert_outputs = model([token_inputs, mask_inputs, segment_inputs])

4) 훈련 및 성능 검증

실제 해보면서 4단계가 시간이 가장 많이 걸렸던 것 같다. 

나는 colab으로 해서 웹 가상으로 돌리는 거라 더 그렇겠지만, 사람들이 AI는 장비빨이라고 많이들 그랬었는데, 많은 공감이 갔다.

epoch을 여기선 2번 돌리는데, 

epoch란 전체 트레이닝 set이 신경망을 통과하는 횟수라고 보면 된다. 동일한 set을 두 번 반복학습해주었다.

나는 여기서 1시간 반 정도 걸린 것 같다. 

뭐가 안 움직이고 그러길래 새로고침 했더니 다시 학습해야 했다는.... 

 

sentiment_model.fit(train_x, train_y, epochs=2, shuffle=True, batch_size=64, validation_data=(test_x, test_y))

 

모델을 훈련시키고 예측 성능을 체크하기 위한 작업도 해주었다. (F1 SCORE라고 하는데 아직 잘 모르겠다.)

F1 SCORE는 precision과 recall을 가중 평균하여 계산합니다
recall은 (모델이 TRUE라고 판정한 것의 숫자)/(전체 TRUE의 숫자)
precision은 (진짜 TRUE) / (모델이 TRUE라고 판정한 것의 숫자)


5) 실제 데이터로 실습하기

마지막 결과! 

오류가 중간에 자잘하게 났지만, 잘 헤쳐와서 결과를 보았는데, 

AI가 앞에서 훈련을 거쳐서 판별해내는 게 눈으로 보이니까 너무나도 신기하고 소스 복붙이지만 해낸 내가 너무 자랑스러웠다 ㅋㅋ ;; 

 

AI에 A자도 잘 모르지만...

이렇게 AI에 조금씩 가까워지고 있는 내 모습이 보기 좋고, 또 어떤 걸 복붙 해서 공부해볼까 하는 설렘뿐이다. 😁