working_helen

[리뷰 감정분석] Llama를 이용한 리뷰 감정분석 본문

deep daiv./NLP project

[리뷰 감정분석] Llama를 이용한 리뷰 감정분석

HaeWon_Seo 2024. 11. 16. 11:37

각 리뷰들에 대하여 긍정/부정/중립 감정을 라벨링하는 감정분석을 진행한다. LLM 프롬프트 엔지니어링을 사용해 감정분석을 진행한 과정에 대해 정리해본다. 

 

 

1. Llama few-shot prompting

2. 감정분석 결과

 


 

▶ KcELECTRA을 fine-tuning 모델을 활용한 리뷰 감정 분석

   : ELECTRA 모델에서 감정분석 성능이 좋지 않았음

    → 모델 크기가 더 큰 LLM에 해당하는 Llama 사용 시도 

2024.09.06 - [deep daiv./NLP project] - [리뷰 감정 분석] KOTE 논문 리뷰 / KOTE fine-tuning 모델을 활용한 감정 분석

 

[감정 분석] 한국어 감정 분석 데이터셋 KOTE 논문 리뷰 / Python에서 KOTE 모델 사용하기

마켓컬리 리뷰 텍스트에 대하여 긍정/부정/중립 감정 라벨리을 위하여 감정분석 모델을 사용하는 과정에서 시도해본 KOTE를 활용한 fine-tuning 모델에 대해 정리해본다.  1. KOTE 2. 논문 리뷰 : Us

working-helen.tistory.com

 

 

 

1. Llama few-shot prompting

Llama few-shot prompting으로 마켓컬리 리뷰 감정분석 시도

 

LLM에게 요구할 task

- 리뷰 감정 카테고리 : 긍정/부정/중립 3가지 

- 주어진 리뷰 전문으로부터 리뷰의 중심 감정을 분류하는 task 

- 리뷰 감정 분류 task 수행 결과 예시 

 

 

(1) few-shot 예제 선택

 

- 예제로 사용할 리뷰 데이터를 선정한 기준

  • 긍정/부정/중립적인 리뷰들를 고르게 포함 
  • 명확하게 긍정적 혹은 부정적 표현이 나오지 않지만 중립적이라 보긴 어려운 간접적이고 다중적인 표현의 리뷰들을 예제로 사용 
  • 한 리뷰 내에서 긍정적인 표현과 부정적인 표현이 동시에 나와 문맥을 파악하는 것이 중요한 리뷰들을 예제로 사용 
  • Llama 모델에 일부 리뷰들에 대한 감정 분석을 사전 실험
    → Llama가 잘 분류하지 못한 내용의 리뷰들을 예제로 사용
        예제를 통해 기존에 잘 판단하지 못한 리뷰들에 대해 올바르게 분류하도록 유도 

- 사용한 few-shot 예제의 일부 

더보기

example = """
리뷰='''
맛 별로 쟁여템이에요
비상식량으로 비축해 둡니다
'''
positive

리뷰='''
고추장 찌개 평범해요
그냥 먹을 만은합니다
'''
neutral

리뷰='''
그냥저냥 보통이였어요
'''
neutral

리뷰='''
이거는 도대체 무슨 맛인지 모르겠네요
'''
negative

리뷰='''
갈비는 아주 아주 작은 거 세 개에 갈비탕 맛은 없고
안 매운 고추만을 넣어 삶은 물을 마시는 느낌'
'''
negative

리뷰='''
물 반 컵 정도 더 넣었는데도 짜요
'''
negative

리뷰='''
생각보다 닭이 실하고
국물이 진한 편이예요
백숙 맛이 진하고 좋아요
'''
positive

리뷰='''
감동적인 맛 재구매 다른 김치 우동류보다 젤
맛있음 다만 1인분씩 양념 면 오뎅이 분할되어 있음 좋겠음
'''
positive

리뷰='''
물을 240ml 더 넣고 끓여서 먹었어요
맛은 너무 좋은데 짜서 물 더 부으니
라면 사리도 넣고 맛있게 먹었습니다
햄은 종류별로 많이 들어 있었어요
''''
positive
"""

 

 

(2) prompt 작성

 

- 프롬프트 성능을 위해 사용한 작성 방식

  • delimiters(** **)를 사용해 프롬프트 내용의 각 부분('지시사항', '출력 방식', '예시')를 모델이 인식하기 좋게 구분
  • LLM에게 리뷰의 감정을 분류하는 '소비자 분석가'라는 페르소나 지정 
  • 각 리뷰는 가장 중심적으로 드러나는 감정 하나로만 분류하도록 제한 
  • 'positive', 'negative', 'neutral' 중 하나로만 답변하도록 출력 형식을 지정, 예제에서 정답도 3가지 중 하나의 텍스트를 반환하는 형태로 제시
  • 출력에서 "이 리뷰의 감정을 분류해보겠습니다." 혹은 "리뷰의 감정 분석 결과입니다." 등 부가적인 문장을 함께 출력하는 경우가 발생 → '다른 어떠한 추가 설명도 함께 출력해서는 안된다.'라는 제약 조건을 사용해 출력 형식을 제한 
  • API 호출 시간 및 비용을 절약하기 위해 모델의 성능을 저하시키지 않는 선에서 예제와 프롬프트에 사용되는 토큰을 최소화 
prompt = f"""
당신은 상품에 대한 고객의 리뷰를 감정에 따라 분류하는 소비자 분석가이다.

**지시사항:**
주어진 리뷰에 드러나는 가장 주된 감정을 분석하여
'positive', 'negative', 'neutral' 중 하나의 감정으로 태깅하라.
리뷰의 문맥을 충분히 반영해야하며, 각 리뷰는 한 감정에만 태깅된다.

**출력 방식**
'positive' 혹은 'negative' 혹은 'neutral' 중 하나만 출력한다.
다른 어떠한 추가 설명도 함께 출력해서는 안된다.

**예시**
{example}
"""

 

 

 

(3) 감정분석 진행

 

- hugging face에서 8B 크기 Llama3 모델 불러오기

  • 구글 코랩에서 실행하여 cuda GPU 사용
  • tensor 데이터 타입을 float16으로 설정 +  모델을 4비트 양자화를 사용하여 로드 
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig
from huggingface_hub import login
login(token="hugging face token")

device = "cuda" if torch.cuda.is_available() else "cpu"
torch_dtype = torch.float16
model_name = "meta-llama/Meta-Llama-3.1-8B-Instruct"
model = load_model(model_name, use_quantization=True)
tokenizer = AutoTokenizer.from_pretrained(model_name)

 

- Llama 답변 생성

  • Llama3 special tokens 사용해 입력문 inputs 생성 
  • tokenizer가 텍스트 inputs을 tensor 형태의 토큰으로 변환하여 GPU에 전달 
  • model.generate를 통해 모델의 응답 텍스트를 생성 
# Llama 모델의 리턴에서 답변에 해당하는 부분만 추출하는 함수 
def extract_assistant_text(outputs):
    return tokenizer.decode(outputs[0], skip_special_tokens=True).split("assistant")[-1].strip()
    
data=[]
for text in df[df['product_id']==상품id]['cleaned_Kiwi_review']:
    query=text
    inputs = f'''<|begin_of_text|><|start_header_id|>system<|end_header_id|>\n{prompt}<|eot_id|><|start_header_id|>user<|end_header_id|>\n{query}<|eot_id|><|start_header_id|>assistant<|end_header_id|>'''
    outputs = model.generate(**tokenizer(inputs, return_tensors="pt").to(device), max_new_tokens=10, pad_token_id=tokenizer.eos_token_id)
    data.append([query, extract_assistant_text(outputs)])

 

- Llama가 생성한 답변을 데이터프레임 형태로 저장 

df = pd.DataFrame(data, columns=['review', 'sentiment'])

 

 

 

 

 

2. 감정분석 결과

감정분석 결과 예시

# positive로 잘 태깅된거
맛있네요
고기가 너무 작은 거 아닌가 싶었는데
딱 괜찮은 양이었어요
2 팩 끓여서 4 식구 적당하게 맛있게 잘 먹었네요 
'positive'

냉동실 쟁여템 많이 짜지 않고 건더기도 실하고 냄새도 많이 나지 않아 너무 맛나요 
'positive'

청국장 남편이 좋아해서 가끔 주문합니다 
들어 있는 딱딱한 두부만 빼고는 맛 좋고 괜찮습니다 김치 넣고 끓이면 얼큰하고 맛있어요
'positive'

간편하게 미역국 먹을 수 있어서 넘 조아요 유통기한도 길고
'positive'
# negative로 잘 태깅된거
갑자기 묽어졌어요 
혹시 물량이 많아졌나요 
진한 맛이 나라 17000원에 한 끼 아깝지 않게 먹었는데
이렇게 물 탄 맛이면 앞으로는 시킬 이유가 없겠어요
왜 맛이 묽어졌는지 궁금합니다  
'negative'

대파만 푸짐허고 얼큰하지도 않고 갈비대가  큰 고하나 아주 작은 거 하나  살도 거의 안 붙어 있고
그냥 대파 탕 
'negative'

청국장이 맛있다는 평이 있어서 주문했는데 청국장 맛이 좀 부족했어요 청국장을 진하게 먹고 싶으신 분들은 실망할 수 있어요 
'negative'

컬리 주문할 때마다 빠뜨리지 않는 최애 국밥인데요
갈수록 내용물이 부실해져요 실망
'negative'
# neutral로 잘 태깅된거
그냥저냥 먹을 만은한데 특별히 맛있는 줄은 모르겠어요 
'neutral'

아직 먹기 전이구요
경복궁 제품과 비교해 보고 싶어 구매했어요 
'neutral'

간이 좀 슴슴해요 엄청 맛있는 건 모르겠고 적당한 맛 
'neutral'
# 잘못 태깅된 예시
국물 깔끔 고기 튼실 거를 타선이 없어요
'negative'

살코기며 이만 한 게 없어요
'negative'

이거 물건입니다 1 인분으로 딱
'negative'

흐음
지금이 618일인데 821일까지면 2개월 정도 남은 건데 원래 냉동식품 유통기한 1년 정도 되지 않나 유통기한이 원래 짧은 제품인가 아님 오래된 걸 보낸 걸까
뭔가 출발이 안 좋지만 맛이라도 있기를
'positive'

 

KcELECTRA fine-tuning 모델이 잘 분류하지 못했던 문장에 대해 비교 

  • 아래의 리뷰들은 KcELECTRA 모델에선 'negative'로 분류
  • Llama에서는 'positive'로 올바르게 분류됨 
블럭 국이라 그냥 끓는 물 부으면 돼서 편리해요
블럭 국 주제에 꽤 실해요
'positive'

고래 사 어묵은 믿고 먹죠
'positive'

슴슴하니 부담 없이 먹을 수 있어 괜찮았어요
'positive'

비상식량으로 냉동실에 쟁여 둡니다 
'positive'

 

 

 

➡️ 앞서 시도한 KOTE 기반 KcELECTRA fine-tuning 모델보다 Llama에서 훨씬 더 좋은 분류 결과 

      Llama prompting을 통한 리뷰 내용 감정분석 결과 사용 

 

 감정분석 결과 dataframe