Project

[Project]한국 경제 뉴스 기사 감정 분류 모델 개발 (feat.pytorch)

moonzoo 2023. 1. 20. 14:20

INTRO

https://mz-moonzoo.tistory.com/3

 

[Project]한국 광고 분류 모델 개발(1)

Abstract 본 프로젝트는 뉴스 데이터를 분석하기 위한 전처리 과정에서 사용자가 원하지 않는 정보를 자동적으로 필터링하여 전처리 진행 속도와 정확도를 상승시키는 것을 목적으로 한다. 수집

mz-moonzoo.tistory.com

한국 광고 분류 모델의 경우 학습에 활용할 적당한 데이터셋이 없어서 직접 데이터 라벨링을 진행해야 하기 때문에 시간이

오래 걸리는 관계로 한국 광고 분류 모델 개발에 앞서 한국 경제 뉴스 기사 감정 분류 모델 개발을 우선 진행하기로 했다.

이것 외에도 한국 뉴스 NER 모델 개발도 진행 중이다.

 

최종 학습 모델과 학습 데이터셋을 사정상 따로 공개할 수 없어서 베타 버전으로 간단하게만 글을 작성하고자 한다.

최종 목적

1. 한국 뉴스 기사 중 광고성 기사가 많으므로 개발한 한국 광고 분류 모델로 기사 필터링을 진행한다.

  -> Topic modeling에 들어갈 기사가 광고가 많으면 응집도가 떨어지고 혼란도가 높아지기 때문.

2. 필터링된 전체 뉴스 기사를 문장 단위로 자르고 Topic modeling + NER + Sentiment Analysis을 진행한다.

   -> BERT 모델이 지원하는 최대 문장 길이가 512까지이고 문장 길이가 긴 학습 데이터가 많지 않기 때문.

       단, Topic modeling에 들어갈 텍스트는 전체 뉴스 기사를 input으로 넣어서 사용.

 

FLOW

 

뉴스 광고 분류 모델(전처리) -> Topic modeling -> NER -> SA -> Output 후 처리

 

1. 라이브러리 설치 및 세팅

개발 환경 : Google Colab / GPU

 

우선 Pretrained된 한국어 언어 모델을 사용할 것이기 때문에 transformers를 설치 했습니다.

 

다음으로 adabelief-pytorch는 Adam을 수정한 옵티마이저로 Adam보다 성능이 좋다는 연구 결과가 있어 사용 했습니다.

여기까지는 코랩을 사용하신다면 다들 크게 무리없이 세팅이 가능 하실 것이라 생각합니다.

하지만 로컬 환경이라면 가상환경을 구축하고 진행하시는 것을 추천 드립니다.

 

2. 데이터셋 다운 및 전처리

사용 데이터셋은 기존 금융 뉴스 감성 분석 영어 데이터셋을 번역하여 한국어 버전을 만들었습니다.
번역 후 육안 검수하고 동일 크기의 DL 모델에서 기존의 영어 데이터와 일치하는 테스트 정확도를 얻었습니다. 

https://github.com/ukairia777/finance_sentiment_corpus

 

GitHub - ukairia777/finance_sentiment_corpus: 한국어 뉴스의 긍정, 부정이 레이블링 된 금융 뉴스 문장 감성

한국어 뉴스의 긍정, 부정이 레이블링 된 금융 뉴스 문장 감성 분석 데이터셋 (finance sentiment corpus) 입니다. - GitHub - ukairia777/finance_sentiment_corpus: 한국어 뉴스의 긍정, 부정이 레이블링 된 금융 뉴

github.com

깃허브 리포지토리에 있는 데이터셋을 다운로드해 저장해주도록 합니다.

이 후, 영어 원문 문장은 필요 없으므로 제거 해주시고 데이터의 셋의 예측하고자 하는 라벨을 숫자로 치환해줍니다.

여기서 sklearn의 라벨 인코딩을 사용하셔도 무방합니다.

마지막으로 데이터셋에서 중복된 데이터가 몇개 있어서 제거 drop_duplicates함수를 사용해 제거해주도록 합니다.

 

그리고 전처리 해주신 데이터셋을 경로에 저장해주시고 사용해주시면 됩니다.

이제 학습을 하고 검증을 하기 위해 sklearn의 train_test_split을 이용해 전처리한 데이터셋을 스플릿 하도록 하겠습니다.

데이터셋이 그렇게 많지 않아서 TEST_SIZE 비중을 조절해주셔도 될 것 같습니다.

 

학습 데이터셋 포맷 변환
테스트 데이터셋 포맷 변환

BERT 모델에 들어갈 input 포멧에 맞게 데이터를 변환해줄 필요가 있습니다.

위의 함수를 활용하여 훈련 데이터와 테스트 데이터를 BERT 입력 포맷에 맞게 변환해 줍니다.

 

 

앞서 학습, 테스트 데이터셋 포맷 변환을 위해 만들어둔 함수를 학습 데이터와 테스트 데이터에 적용 시켜줍니다.

다음으로 dataloader을 사용했는데 dataloader은  데이터를 1개, 1개 학습을 시키는 방법도 가능하지만

Pytorch의 dataloader를 활용하면 Mini-Batch 단위의 학습이 가능하고 무작위로 데이터를 섞을 수 있다는 장점이 있기 때문에 거의 대부분의 파이토치 학습 코드에선 dataloader을 사용하고 있습니다.

여기서 주의 하실점은 테스트 dataloader에서는 shuffle을 False로 지정해주셔야 합니다.

3. 모델 학습

우선 사용 모델은 허깅페이스의 klue/roberta-base를 사용했습니다. klue/roberta-large가 성능이 조금더 잘 나올 것이라 생각하지만 모델 인퍼런스의 속도도 중요하기 때문에 base를 사용했습니다. 추가로 다른 언어모델을 사용해가시면서 좀 더 task에 맞는 언어모델을 선택하시는 것을 추천합니다.

 

다음으로 미세조정 코드는 데이터 셋의 크기와 성질에 따라 미세조정 방식이 조금씩 달라질 수 있습니다.

이 코드에서는 미세조정을 사용하지 않았지만 사용 시 상황에 따라 사용시 성능이 좋아질 수 있습니다.

지금 사용하고자 하는 대부분의 언어모델의 경우 같은 훨씬 큰 데이터에서 학습된 모델이고 같은 한글 데이터로 학습된 언어 모델이기 때문에 성질이 비슷할 것입니다. 그렇기 때문에 일부분을 얼리고 미세조정을 진행하는 것이 일반적으로 성능이 더 좋게 나오게 됩니다. 숫자를 조절해가시면서 성능을 비교해보시면 될 것 같습니다

 

다음으로 학습 코드는 다른 코드들과 큰차이가 없으므로 생략하겠습니다.

다만 대부분의 코드와 다르게 여기서는 adabelief를 사용하였습니다. 이는 앞서 가볍게 언급했듯이 Adam을 수정한 옵티마이저로 Adam보다 성능이 좋다는 연구 결과가 있어 사용 했습니다.

 

이제 모델 학습을 진행해보도록 하겠습니다. 

쓸데없는 로그가 너무 많이떠서 3 epochs의 train acc는 0.89122의 성능이 나왔습니다. 

이제 앞서 스플릿한 테스트 데이터셋으로 성능 테스트를 해보도록 하겠습니다.

검증 코드는 학습코드와 크게 다를 것이 없고 torch.set_grad_enabled을 False로 세팅해줍니다.

 torch.no_grad()와 같은 코드입니다.

4. 모델 결과 

 

모델이 예측한 라벨과 앞서 저장해둔 검증 데이터의 정답 라벨을 classification_report를 통해 비교합니다.

 

F1-SCORE의 성능이 <0.84 좀 넘게 나오는 것을 확인했습니다.

 

이정도면 대충 가볍게 만들었는데도 쓸만한 성능이 나오는 것 같습니다.

학습 필요없이 필요할 때마다 불러와서 사용하도록 모델을 저장합니다.

5. 저장된 모델 인퍼런스 

코랩으로 학습시킨 모델을 저장해서 로컬로 옮겨 인퍼런스를 진행해보도록 하겠습니다.

 

사용할 라이브러리를 불러와주시고 seed고정 사용할 args 세팅

그리고 허깅페이스의 AutoTokenizer로 학습에 사용된 tokenizer을 불러오도록 합니다.

 

앞서 보신것처럼 데이터 포맷을 BERT 입력 포맷으로 변환해주셔야하기 때문에 코드를 그대로 들고왔습니다.

여기서 TestDataset()에 예측하고자하는 데이터프레임을 넣어주시면 됩니다.

 

이제 예측을 해보도록 하겠습니다. do_predict 함수는 조금 익숙하시겠지만

앞서 테스트 데이터를 예측할 때 사용한 코드를 조금 수정해서 do_predict라는 함수로 지정해주고 사용했습니다. 

 

그리고 run_predict함수도 설정해줬습니다.

run_predict에서 저희가 예측하고자하는 라벨이 중립 긍정 부정 3가지 이므로 num_labels를 3으로 하고 klue/roberta-base모델이므로 RobertaForSequenceClassfication을 사용하겠습니다.

그리고 불러온 roberta모델 위에 코랩에서 학습시킨 모델의 state_dict을 올려주도록 하겠습니다.

그럼 이제 예측준비가 완료됐습니다.

 

마지막 run_predict()안에 모델의 경로와 예측하고자 하는 데이터셋을 dataloader로 변환해준 형태인 test_dataloader을 넣어주면 데이터셋의 예측값이 preds1에 나오게 됩니다. 그리고 그대로 사용하시면 됩니다.

 

6.  후기

사실 지금은 모델을 학습할 환경의 여의치않아서 코랩으로 가볍게 학습을 진행해봤습니다.

하지만 이 모델을 실제로 사용하기 위해서는 성능을 좀 더 향상시키고 싶은 욕심이 있습니다.

 

그래서 성능을 올리는 올리는 방법을 몇가지 정리해보자면

1. 성능을 올리는 가장 쉬운 방법은 데이터셋을 증강 시키는 것입니다.

-> Task가 경제 뉴스라면 다른 감정 분류 데이터셋으로 학습시키면 물론 오를 수도 있겠지만... 성능이 오히려 떨어질 수도 있을 것이라 생각합니다. 그래서 직접 라벨링을 진행하거나 이 글에서 사용한 데이터셋을 텍스트 데이터 Augementation 기법을 사용해 증강시켜 학습을 시키는 방법을 추천합니다.

 

2. 언어모델 변경 및 앙상블

-> 사실 성능 향상이 나에게 가장 중요하다! 싶으면 여러 pretrained된 모델을 학습시켜서 성능을 테스트해보고 성능이 잘나오는 몇 가지 모델의 logit을 평균내면 성능향상을 기대할 수 있습니다. 하지만 이 방법을 사용할 경우 인퍼런스에 너무 많은 시간이 들어서 성능 향상이 가장 중요한 경우 이 방법을 사용하시면 될 것 같습니다.

그런게 아니라 인퍼런스 시간이 중요해 모델이 가벼운게 중요하다 싶으면 성능이 잘 나오는 하나의 모델을 잘 학습시켜서 사용하시는 것을 추천합니다.

 

제가 커스터마이징한 모델과 추가 학습에 사용한 데이터셋은 공개할 수가 없어서 베이스라인용으로라도 글을 써봤습니다.

아직 부족한 점이 많지만 활용할 일이 있으시다면 참고하셔도 좋을 것 같습니다

 

전체 코드는 다음 깃허브 링크를 참고하시면 됩니다.

https://github.com/moonjoo98/News_trend/tree/master/KR_NEWS

 

GitHub - moonjoo98/News_trend: 국내 해외뉴스 토픽 모델링 및 감성분석(Tner + Finbert)

국내 해외뉴스 토픽 모델링 및 감성분석(Tner + Finbert). Contribute to moonjoo98/News_trend development by creating an account on GitHub.

github.com