티스토리 뷰
※ 현재 사용한 모델
- SentenceTransformer: 문장 단위의 임베딩 벡터를 생성하는 모델.
- 입력한 문장을 임베딩 벡터로 변환하여 유사도 측정.
- 문장 내 의미를 보존하면서 벡터 공간에서의 유사도를 보장하는 임베딩을 생성.
- 한국어 문장 분류, 검색, 클러스터링 등 다양한 자연어처리 테스크에서 성능향상을 기대할 수 있음.
- 그러나 입력한 정보를 바탕으로 데이터 프레임에서 유사한 데이터를 찾아내는 것은 별도의 코드로 구현.
↓
※ 유사도 측정 및 가장 유사한 행 선택하기 과정
- 데이터 전처리
- 입력한 정보와 데이터 프레임의 정보를 비교하기 위해 필요.
- ex) 데이터 프레임의 '재료' 컬럼에서 각 요리의 재료정보를 리스트 형태로 추출해야 함.
- 임베딩 벡터 생성
- 입력한 정보와 데이터 프레임의 정보를 문장 단위로 임베딩 벡터로 변환.
- 이때, SentenceTransformer 모델을 사용하여 각 문장의 임베딩 벡터를 생성할 수 있다.
- 유사도 측정
- 생성된 임베딩 벡터를 사용하여 입력한 정보와 데이터 프레임의 각 행의 유사도를 측정한다.
- 이때, 코사인 유사도(cosine similarity)를 사용하여 유사도를 측정할 수 있다.
- 가장 유사한 행 선택
- 측정된 유사도를 기반으로 입력한 정보와 가장 유사한 행을 선택한다.
- 선택하는 방법은 다양하게 구현할 수 있다. (행의 인덱스 반환/ 행의 정보 출력 등)
▼ 코드 예시
Q1. '토마토 들어간 파스타 추천해줘'라는 문장을 입력했을 때 '재료' 컬럼에서 '토마토'가 들어간 행을 출력하는 코드.
from sentence_transformers import SentenceTransformer
import pandas as pd
from sklearn.metrics.pairwise import cosine_similarity
# SentenceTransformer 모델 로드
model = SentenceTransformer('모델 이름')
# 데이터 프레임 로드
df = pd.read_csv('데이터 파일 경로')
# 데이터 전처리
df['재료'] = df['재료'].apply(lambda x: x.split(','))
# 입력한 정보
input_info = {'재료': ['토마토']}
# 입력한 정보의 임베딩 벡터 생성
input_emb = model.encode(' '.join(input_info['재료']))
# 데이터 프레임의 각 행의 임베딩 벡터 생성
df['emb'] = df['재료'].apply(lambda x: model.encode(' '.join(x)))
# 코사인 유사도 계산
df['similarity'] = df['emb'].apply(lambda x: cosine_similarity([input_emb], [x])[0][0])
# 가장 유사한 행 선택
most_similar_row = df.loc[df['similarity'].idxmax()]
문제점) 그러나, '요리' 컬럼에서 '파스타'를 포함했는지는 찾지 못한다.
Q2. '요리' 컬럼에서는 '파스타'를, '재료' 컬럼에서는 '토마토'를 찾아 모두 해당하는 행을 출력하기
result = df.query("재료.str.contains('토마토') and 요리.str.contains('파스타')")
문제점) 사용자가 문장으로 입력했으나, 코드에 해당 부분이 따로 입력되어야 한다.
Q3. 사용자가 '토마토 들어간 파스타 추천해줘'라는 문장만 입력하고, 나머지는 모두 코드로 자동실행되도록 하기
→ 입력문장을 자연어 처리하여 필요한 정보를 추출한 후, 해당 정보를 이용하여 데이터 프레임에서 유사한 행을 찾는 과정이 필요.
→ 이를 위해서는 NLU(Natural Language Understanding) 기술을 사용하여 자연어를 이해하는 과정이 필요.
<입력 문장 처리 과정>
1. 입력 문장에서 요리명과 재료를 추출한다. 이를 위해 구문분석기(Parser)를 사용.
2. 추출된 요리명과 재료를 데이터프레임에서 찾아 해당 행을 출력한다.
import pandas as pd
from sentence_transformers import SentenceTransformer
import nltk
from nltk import pos_tag
from nltk.tokenize import word_tokenize
# 데이터프레임 불러오기
df = pd.read_csv("recipes.csv")
# SBERT 모델 로드
model = SentenceTransformer('snunlp/KR-SBERT-V40K-klueNLI-aug')
# 입력 문장
input_sentence = "토마토 들어간 파스타 추천해줘."
# 문장 처리
pos = pos_tag(word_tokenize(input_sentence))
dish = ""
ingredient = []
for i in range(len(pos)):
if pos[i][1] == "NNP": # 고유 명사인 경우
dish += pos[i][0] + " "
elif pos[i][1] == "NN": # 일반 명사인 경우
ingredient.append(pos[i][0])
# 요리명과 재료로 데이터프레임 필터링
df_filtered = df[df["요리명"].str.contains(dish.strip())]
for ing in ingredient:
df_filtered = df_filtered[df_filtered["재료"].str.contains(ing)]
# 유사도 계산을 위한 임베딩 생성
embeddings = model.encode(df_filtered["요리방법"].tolist())
# 입력 문장과 유사한 요리 출력
query_embedding = model.encode([input_sentence])
similarities = cosine_similarity(embeddings, query_embedding)
idx = np.argmax(similarities)
recommended_dish = df_filtered.iloc[idx]["요리명"]
print(recommended_dish)
Q5. 사용자가 "추천해줘" 라는 말을 포함했을 때, 챗봇이 자동응답처럼 한 마디 하고 해당 내용을 출력.
(추천시스템은 아닌 코드를 받음;)
# 사용자 입력 받기
user_input = input("무엇을 도와드릴까요? ")
# 추천 요청인 경우
if "추천해줘" in user_input:
# 추천 요리 종류 추출하기
cuisine = extract_cuisine(user_input)
# 추천 요리 레시피 추출하기
recipes = find_recipes(cuisine)
# 응답하기
print("네~ 맛있는 요리 레시피를 추천해드릴게요.")
for recipe in recipes:
print("요리:", recipe["요리"])
print("재료:", recipe["재료"])
print("레시피:", recipe["요리방법"])
- extract_cuisine: 사용자 임력에서 추천할 요리 종류를 추출하는 함수
- find_recipes: 해당 요리종류에 해당하는 레시피를 데이터프레임에서 찾아내는 함수.
(직접 구현해야함)
Q6. '설명해줘'를 입력할 경우 학습데이터셋이 아닌, gpt 모델이 대답하게 하기
from transformers import pipeline
gpt3 = pipeline("text-generation", model="EleutherAI/gpt-neo-2.7B", device=0) # GPT-3 모델 불러오기
while True:
user_input = input("사용자: ")
if user_input == "종료":
break
if user_input == "설명해줘":
prompt = "딥러닝에 대해 간단히 설명해줄래?"
generated_text = gpt3(prompt, max_length=50, do_sample=True, temperature=0.7)[0]['generated_text']
print("GPT-3: " + generated_text)
else:
print("죄송해요, 잘 이해하지 못했어요.")
'으쌰으쌰! 팀 프로젝트' 카테고리의 다른 글
GPT (0) | 2023.05.04 |
---|