Project

[Project]한국 뉴스 감성분류, NER모델 Inference

moonzoo 2023. 2. 15. 16:37

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 후 처리

 

Topic modeling

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

 

[Project]한국 뉴스 토픽 모델링 (feat. BERTopic)

INTRO https://mz-moonzoo.tistory.com/23 [Project]해외 뉴스 토픽 모델링 (feat. BERTopic) INTRO 트렌드를 따라가기 위해 많은 사람들이 뉴스를 봅니다. 하지만 하루만해도 수백 수천개의 뉴스가 올라오고 그 중

mz-moonzoo.tistory.com

Sentiment Analysis

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

 

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

INTRO https://mz-moonzoo.tistory.com/3 [Project]한국 광고 분류 모델 개발(1) Abstract 본 프로젝트는 뉴스 데이터를 분석하기 위한 전처리 과정에서 사용자가 원하지 않는 정보를 자동적으로 필터링하여 전처

mz-moonzoo.tistory.com

NER

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

 

[Project]한국 뉴스 NER 모델 개발 (feat. KCELECTRA)

INTRO https://mz-moonzoo.tistory.com/3 [Project]한국 광고 분류 모델 개발(1) Abstract 본 프로젝트는 뉴스 데이터를 분석하기 위한 전처리 과정에서 사용자가 원하지 않는 정보를 자동적으로 필터링하여 전처

mz-moonzoo.tistory.com

2023년 2월15일 시점으로 Topic modeling과 Sentiment Analysis 그리고, NER까지 코드와 리뷰작성을 끝냈습니다.

한국 광고 분류 모델은 데이터셋을 직접 만드는게 너무 큰 시간이 소요돼서 가장 마지막으로 미루고 있습니다...ㅎㅎ

 

Inference

이번 글에서는 지금까지 학습을 진행시킨 SA모델과 NER모델을 사용해 해당 한국 뉴스 기사의 감성 분류와 기업명을 뽑아내도록 하겠습니다.

 

1. 데이터 불러오기

테스트를 위해 빅카인즈에서 수집한 뉴스 데이터를 가져오도록 하겠습니다.

데이터 전처리는 가볍게 중복제거 정도만 사용해줬습니다.

테스트이기 때문에 총 16846의 데이터중 3000개만 사용하도록하겠습니다.

 

뉴스 기사 문장 단위로 자르기

실제 뉴스 기사 원문을 보면 1000자가 넘어가는 긴 뉴스 기사들도 종종 보실 수 있습니다.

하지만 BERT모델에 들어갈 수 있는 문자의 수는 512자를 넘을 수 없습니다. 그렇기 때문에 긴 뉴스 기사를 Sentence단위로 나눠줄 필요가 있습니다. 문장 단위로 쪼개는 방법은 여러가지가 있는데 테스트 해보고 저는 속도가 비교적 빠르고 성능도 준수한 kolanlp 라이브러리를 사용했습니다.

 

이런식으로 뉴스 본문을 문장 단위로 쪼개고 list에 append해주고 나중에 문장을 하나로 합쳐서 원문으로 만들기 위해 index_list에 뉴스 index를 append 해줬습니다.

하지만 실습에 사용한 빅카인즈 데이터의 본문들은 대부분 짧은 텍스트기 때문에 큰 효과를 보지는 못했습니다.

 

2. NER 모델 Inference

NER 모델 불러오기

NER모델 불러와서 일부 세팅을 진행했습니다. tag2id, unique_tags, id2tag는 학습할 때 사용한 것을 가져오시면 됩니다.

 

ner_tokenizer

tokenizer역시 학습에 사용한 음절 tokenizer을 가져오시면 됩니다.

 

ner_inference

이전 글인 NER모델  ner_inference랑은 미세하게 다른것을 보실 수 있습니다.

이전 글의 ner_inference는 print를 통해 전체 text와 tag를 보여주기 위해서였고 원하는 정보인 ORG만 뽑아내기 위해서 

기존의 ner_inference에서 살짝 변형해줬습니다.

 

문장단위로 분리한 text inference 결과 데이터프레임화

 

앞서 문장단위로 나눠준 sentence_list의 텍스트들을 ner_inference 함수를 사용해 tag를 예측해주도록합니다.

그리고 결과값을 리스트에 따로 저장하고 데이터프레임화 해줍니다.

결과를 보고 설명을 드리는게 쉬울 거같으니 결과 먼저 보여드리도록 하겠습니다.

 

text에대해 ner_inference를 진행해 결과값 output과 tag가 나왔습니다.

그리고 news_index 컬럼을 보시면 0이라는 숫자가 여러개 있습니다. 그 뜻은 1,2,3행의 텍스트는 같은 뉴스에서 나온 문장이라는 것입니다. 하나의 뉴스를 문장단위로 쪼갰기 때문에 뉴스 인덱스가 값이 같은 text끼리 join함수를 사용해 원문으로 재생성 해주기 위해 news_index를 추가했습니다. 그래서 sum_text컬럼을 보면 전체 원문 텍스트를 보실 수 있습니다.

 

ORG_export 함수

이제 생성된 데이터프레임의 각 텍스트의 ner 결과값이 들어있습니다. 하지만 저것만 봐서는 한눈에 추출된 기업명이 뭔지 파악하기가 힘듭니다. 그래서 export함수를 만들어 tag가 ORG인 text를 뽑아내도록 했습니다.

 

만들어준 export함수를 apply를 사용해 각 행마다 적용해주면...

 

Export 샘플

이렇게 ORG 태그가 붙은 텍스트만 뽑아낼 수 있습니다. 잘뽑힌 것으로 보이죠?

그럼 이제 text의 감성분류를 진행해보도록 하겠습니다.

 

3. Sentiment Analysis 모델 Inference

라이브러리 및 모델 세팅

class args는 모델 학습에 사용한 args class인데 저기서 batch_size같은것을 사용해야해서 그대로 들고 왔습니다.

 

NER 모델과 마찬가지로 모델 학습에 사용한 tokenizer을 불러와 주도록 합니다.

 

Dataset 변환

다음으로는 위에 NER모델에서 생성한 df를 SA모델 Inference를 위해 Dataset으로 변환해주고 Dataloader에 넣어주셔야 합니다. 이렇게 하는 이유는 하도 많이봐서 다들 아실거라고 생각합니다.ㅎㅎ

 

Run_predict

NER모델이랑 살짝 달라보이지만 사실 뜯어보면 비슷한 과정입니다.

output과 logit를 뽑아내는 do_predict 함수를 만들어 줍니다.

그리고 run_predict함수를 자세히 보시면 여기서 모델을 불러오시는 것을 볼 수 있습니다.

RobertaForSequenceClassfication.from_pretrained를 통해 학습에 사용한 프리트레인 모델을 불러오고 gpu에 넣어줍니다.

이제 저희가 학습에 진행한 모델의 state_dict값을 불러와서 위의 모델에 load_state_dict함수를 사용해 모델의 매개변수를 불러오고 업데이트 해줍니다.

 

그럼 이제 준비가 끝났습니다. 앞서 정의한 do_predict함수에 모델과 앞에서 생성한 dataloader를 넣어주고 기다리기만하면 감성 분류 모델의 결과값이 나오게 됩니다.

 

*run_predict()함수 안에는 모델의 매개변수가 저장돼있는 model_path를 넣어주시면 됩니다

Inference가 끝났다면 NER 결과값이 있는 데이터프레임에 감성분류 결과값을 추가해주도록 합니다.

 

최종 결과값 Example

 

그럼 이런식으로 NER모델과 SA모델의 Inference 결과가 하나의 데이터프레임안에 들어가게 됐습니다.

 

마치며

  • 감성분류는 학습 데이터셋이 부족함에도 불구하고 아주 잘하는 것으로 보였습니다. 추가 학습을 진행하면 더 좋은 성능을 기대할 수 있을 것 같습니다.
  • NER의 경우 괜찮은 성능을 보이지만 100개중 3~4개 정도 B-ORG를 잡아내지못하고 I-ORG만 잡아내는 경우가 있습니다.
  • 그래도 100개중 3~4개면 괜찮은 성능을 보이는 것 같습니다. 조금만 보완한다면 더 좋은 성능을 보일 것 같습니다.

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

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