working_helen
[리뷰 감정분석] Llama를 이용한 리뷰 감정분석 본문
각 리뷰들에 대하여 긍정/부정/중립 감정을 라벨링하는 감정분석을 진행한다. LLM 프롬프트 엔지니어링을 사용해 감정분석을 진행한 과정에 대해 정리해본다.
1. Llama few-shot prompting
2. 감정분석 결과
▶ KcELECTRA을 fine-tuning 모델을 활용한 리뷰 감정 분석
: ELECTRA 모델에서 감정분석 성능이 좋지 않았음
→ 모델 크기가 더 큰 LLM에 해당하는 Llama 사용 시도
2024.09.06 - [deep daiv./NLP project] - [리뷰 감정 분석] KOTE 논문 리뷰 / KOTE fine-tuning 모델을 활용한 감정 분석
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
'deep daiv. > NLP project' 카테고리의 다른 글
[카테고리 태깅] GPT API를 이용한 리뷰 내용 카테고리 태깅 (0) | 2024.11.15 |
---|---|
[키워드 추출] Llama를 이용한 리뷰 키워드 추출 및 카테고리 선정 (0) | 2024.09.15 |
[모델링] LLM : OpenAI GPT & Meta Llama / LLM few-shot prompting (0) | 2024.09.15 |
[리뷰 감정분석] KOTE 논문 리뷰 / KOTE fine-tuning 모델을 활용한 감정분석 (2) | 2024.09.12 |
[리뷰 감정분석] ELECTRA / Korean Pre-trained Language Models (6) | 2024.09.08 |