You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Step 1. 예시 노트북을 실행해보며 sentence embedding과 cosine similarity 계산 방법 익히기
Google 계정 로그인 후 colab에 접속해서 현재 레포지토리의 /Week7/sentence_embeddings.ipynb 노트북을 실행해보면서 한국어 문장을 임베딩 벡터로 표현하는 과정과, 각 벡터들 사이의 cosine 유사도를 이용해 문장 사이의 의미적 유사도를 계산하는 방법에 대해 살펴봅시다.
예시 데이터 대신 자신만의 데이터를 입력해서 사용해도 좋아요!
Step 2. 입력된 키워드와 유사한 뉴스 기사 추천 프로그램 만들기
위에서 사용했던 BERT 모델을 이용하여, 사용자가 입력한 내용과 가장 유사한 뉴스 제목을 찾아 추천해주는 프로그램을 만들어 봅시다.
프로그램의 뼈대를 이루는 함수 이름과 정의가 마련되어 있으니, 필요한 부분을 자유롭게 구성하여 프로그램을 완성해 봅시다.
주의: main 함수의 정의는 바꾸지 마세요!
작동 예시
입력 > 신재생 에너지
출력 > 입력과 유사한 상위 5개의 뉴스 제목을 출력합니다.
1. 에너지정책 유턴 재생에너지 대신 원전으로 (score: 56.85)
2. 전기 아껴쓴 만큼 현금 돌려받는다...에너지캐쉬백 전국 확대 (score: 54.78)
3. 수자원공사 한국에너지기술연과 그린수소 연구 업무협약 (score: 53.07)
4. 이어지는 폭염 늘어나는 전력수요 (score: 51.01)
5. 코오롱 수소 밸류체인 플랫폼 구축… 생산부터 발전까지 원스톱 (score: 50.95)
Hint
Hint 1: news_title에는 뉴스 데이터셋에 포함되어 있는 각 뉴스 기사들의 제목이 포함되어 있습니다. 예시 문장의 임베딩을 계산한 것과 같은 방식을 사용할 수 있습니다.
Hint 2: 위에서 정의하고 사용했던 cal_score 함수를 사용하면 사용자가 입력한 요청사항과 뉴스 제목들 사이의 similarity score를 계산할 수 있습니다.
get_sentence_embeddings() 함수는 입력 문장들에 대한 임베딩 벡터를 계산합니다. 파라미터로 받은 입력 문장들을 tokenizer를 사용해 토큰 인덱스 배열로 변환하고, 변환된 토큰 인덱스 배열을 모델에 입력하여 임베딩 벡터를 계산합니다.
get_similarity_scores() 함수는 입력 텍스트와 미리 계산된 임베딩 벡터들과의 유사도 점수를 계산합니다. 두번째 파라미터로 받은 입력 텍스트를 get_sentence_embeddings() 함수를 사용하여 임베딩 벡터로 변환한 후, 미리 계산된 임베딩 벡터들과의 유사도 점수를 계산 후 각 유사도 점수를 scores 리스트에 추가합니다. 이때 emb와 input_text의 크기를 맞추기 위해 get_sentence_embeddings()함수를 호출할 때 input_text를 리스트로 감싸서 전달했습니다.
설유민
get_sentence_embeddings
Input sentences을 tokenizer를 사용해 tokenizing합니다.
입력이 여러 문장으로 이루어진 list인 경우, 각 문장을 모두 tokenizing해줍니다!
return_tensors를 pt(torch.Tensor로 반환)로 설정한 경우, 각 문장에 대한 tokenizing 결과가 같은 차원의 벡터여야 합니다. 입력 문장들이 모두 같은 차원의 벡터로 표현되도록, 길이가 부족한 경우에는 padding을 수행하도록 설정합니다.
길이가 모델의 최대 입력 차원보다 긴 경우에는 truncation을 할 수 있도록 설정합니다.
Tokenized sentences를 모델에 입력으로 주어, 각 문장에 대한 embedding을 구합니다.
get_similarity_scores
입력 텍스트의 embedding을 get_sentence_embeddings로 구합니다.
입력 텍스트 한 개의 경우 embeddings의 size가 (1, {number of tokens}, {dim.})입니다. cal_score의 수정 없이 입력 텍스트의 [CLS]의 embedding만 연산에 사용할 수 있도록 squeeze를 수행해줍니다.
fromtqdmimporttqdmdefget_sentence_embeddings(sentences):
# 입력 문장을 tokenizer를 사용하여 토큰 인덱스 배열로 변환합니다.inputs=tokenizer(sentences, padding=True, truncation=True, return_tensors="pt").to(device)
# 모델을 활용하여 임베딩을 계산합니다..withtorch.no_grad():
embeddings, loss=model(**inputs, return_dict=False)
returnembeddingsdefget_similarity_scores(embeddings, input_text, cal):
# 입력 텍스트에 대한 임베딩을 계산합니다.input= []; input.append(input_text);
input_embedding=get_sentence_embeddings(input)[0] # <- Input text에 대한 Vector# 입력 텍스트의 임베딩과 미리 계산된 임베딩 사이의 유사도를 계산합니다.scores= []
forembinembeddings:
scores.append(cal(emb, input_embedding))
returnscores
# 이 부분은 수정하지 마세요!defmain(cal):
# 뉴스 기사 제목의 임베딩 벡터 계산news_embeddings=get_sentence_embeddings(news_titles)
input_text=input("입력 > ")
# 입력된 텍스트와 뉴스 기사 제목들 사이의 유사도 계산similarity_scores=get_similarity_scores(news_embeddings, input_text, cal)
print("출력 > 입력과 유사한 상위 5개의 뉴스 제목을 출력합니다.")
# 유사도 점수가 가장 높은 5개의 index 찾기top_5_idx=reversed(np.argsort(similarity_scores)[-5:])
# 각 index에 해당하는 뉴스 제목과 유사도 점수 출력fori, idxinenumerate(top_5_idx):
print(f"{i+1}. {news_titles[idx]}\t(score: {format(similarity_scores[idx], '.2f')})")
main함수에 함수를 인수로 받도록 추가해서 새로운 Calculation Function을 적용하기 쉽도록 변경하였습니다.
입력 > 비건
출력 > 입력과 유사한 상위 5개의 뉴스 제목을 출력합니다.
1. 현대백화점그룹 비건 시장 본격 출사표 (score: 59.60)
2. 반도건설 충남 천안 유보라 천안 두정역 분양 (score: 42.14)
3. 셀바스AI 하나금융파인드 플랫폼서 셀비 체크업 서비스 (score: 41.83)
4. 그래픽 수학자 허준이 한국계 최초 필즈상 수상 (score: 40.89)
5. 정유사가 무슨죄 시장원리 모르나…베이조스 또 바이든 저격 (score: 38.35)
입력 > 채식주의
출력 > 입력과 유사한 상위 5개의 뉴스 제목을 출력합니다.
1. 퓨리나의 지속가능한 친환경 실천... 반려동물과 함께하는 삶 꿈꾸죠 Weekend 반려동물 (score: 35.69)
2. 가정간편식 플랫폼 구스통 엄선한 제철 식재료 및 음식 선보여 (score: 32.36)
3. 풀무원 알래스칸 명태살 ‘볼카츠’ 출시 (score: 29.07)
4. 인스웨이브 웹 공유 서비스 ‘W셰어링’ 베타 오픈 (score: 28.78)
5. 金배추가 한차에 가득 (score: 28.58)
"비건"과 "채식주의"의 결과가 전혀 다르게 나왔습니다. 뉴스 제목에 "비건"이라고 명시되어있지 않으면 외래어에 대해서는 정확도가 낮게 나오는 것 같습니다.
Projection과 Cosine Similarity에 대해서 결과가 매우 비슷하게 나왔습니다. 계산 방식이 약간 차이는 있지만, 결과적으로 벡터가 많이 벌어져 있으면 정확도가 낮게 나오는 점은 동일하기 때문에 생긴 현상으로 보입니다.
from tqdm import tqdm
def get_sentence_embeddings(sentences):
# 입력 문장을 tokenizer를 사용하여 토큰 인덱스 배열로 변환합니다.
inputs = tokenizer(sentences, padding=True, truncation=True, return_tensors="pt").to(device)
# 모델을 활용하여 임베딩을 계산합니다..
with torch.no_grad():
embeddings, loss = model(**inputs, return_dict=False)
return embeddings
def get_similarity_scores(embeddings, input_text):
# 입력 텍스트에 대한 임베딩을 계산합니다.
input_embedding = get_sentence_embeddings([input_text])[0]
# 입력 텍스트의 임베딩과 미리 계산된 임베딩 사이의 유사도를 계산합니다.
scores = []
for emb in embeddings:
scores.append(cal_score(emb,input_embedding))
return scores
1.Tokenizer를 이용하여 문장을 토큰 인덱스로 변환
2. 임베딩을 코사인 유사도를 통해 계산
3. 유사도가 비슷한 상위 5개 뉴스 제목 출력
Activity
ymnseol commentedon Jun 1, 2023
4조
김율희
get_sentence_embeddings() 함수는 입력 문장들에 대한 임베딩 벡터를 계산합니다. 파라미터로 받은 입력 문장들을 tokenizer를 사용해 토큰 인덱스 배열로 변환하고, 변환된 토큰 인덱스 배열을 모델에 입력하여 임베딩 벡터를 계산합니다.
get_similarity_scores() 함수는 입력 텍스트와 미리 계산된 임베딩 벡터들과의 유사도 점수를 계산합니다. 두번째 파라미터로 받은 입력 텍스트를 get_sentence_embeddings() 함수를 사용하여 임베딩 벡터로 변환한 후, 미리 계산된 임베딩 벡터들과의 유사도 점수를 계산 후 각 유사도 점수를 scores 리스트에 추가합니다. 이때 emb와 input_text의 크기를 맞추기 위해 get_sentence_embeddings()함수를 호출할 때 input_text를 리스트로 감싸서 전달했습니다.
설유민
get_sentence_embeddingstokenizer를 사용해 tokenizing합니다.return_tensors를pt(torch.Tensor로 반환)로 설정한 경우, 각 문장에 대한 tokenizing 결과가 같은 차원의 벡터여야 합니다. 입력 문장들이 모두 같은 차원의 벡터로 표현되도록, 길이가 부족한 경우에는 padding을 수행하도록 설정합니다.get_similarity_scoresget_sentence_embeddings로 구합니다.결과
t2easure commentedon Jun 1, 2023
2조
결과

결과

JOHAJUN commentedon Jun 1, 2023
5조

YUNHYUNWOO commentedon Jun 1, 2023
3조
결과
twkang43 commentedon Jul 24, 2023
강태욱
1. Cosine Similarity 사용
결과
2. Euclidean Distance 사용
cal_score 함수를 다음과 같이 변경하여 euclidean distance를 계산하도록 하였다.

그러나, 해당 함수는 뉴스 제목 사이의 유사도를 정확히 계산하지 못해 다음과 같이 키워드와 연관 없는 뉴스 제목을 출력하였다.
mnxcv commentedon Jul 25, 2023
임세훈
코드
실행
사용한 Colab Notebook 주소는 여기에서 확인할 수 있습니다.
KangMeanWoo commentedon Jul 31, 2023
강민우
1.Tokenizer를 이용하여 문장을 토큰 인덱스로 변환
2. 임베딩을 코사인 유사도를 통해 계산
3. 유사도가 비슷한 상위 5개 뉴스 제목 출력