HanyangTechAI / 2023-Deep-Learning-Study

2023 HAI 딥러닝 스터디 진행과정을 기록하기 위한 레포지토리입니다.
MIT License
7 stars 2 forks source link

7주차 과제 #7

Open GirinMan opened 1 year ago

GirinMan commented 1 year ago

여섯 번째 과제: BERT를 이용한 sentence embedding의 cosine similarity 계산하기

회합 자료 링크: https://github.com/HanyangTechAI/2023-Deep-Learning-Study/issues/1#issuecomment-1552608087 image

Colab Python 노트북을 사용한 BERT sentence embedding 실습

sentence_embeddings.ipynb

Step 1. 예시 노트북을 실행해보며 sentence embedding과 cosine similarity 계산 방법 익히기

Step 2. 입력된 키워드와 유사한 뉴스 기사 추천 프로그램 만들기

작동 예시

입력 > 신재생 에너지
출력 > 입력과 유사한 상위 5개의 뉴스 제목을 출력합니다.
1. 에너지정책 유턴  재생에너지 대신 원전으로  (score: 56.85)
2. 전기 아껴쓴 만큼 현금 돌려받는다...에너지캐쉬백 전국 확대    (score: 54.78)
3. 수자원공사 한국에너지기술연과 그린수소 연구 업무협약 (score: 53.07)
4. 이어지는 폭염 늘어나는 전력수요    (score: 51.01)
5. 코오롱 수소 밸류체인 플랫폼 구축… 생산부터 발전까지 원스톱    (score: 50.95)

Hint

제출 방식

ymnseol commented 1 year ago

4조

김율희

KakaoTalk_Photo_2023-06-01-16-22-40 001 KakaoTalk_Photo_2023-06-01-16-22-40 002 get_sentence_embeddings() 함수는 입력 문장들에 대한 임베딩 벡터를 계산합니다. 파라미터로 받은 입력 문장들을 tokenizer를 사용해 토큰 인덱스 배열로 변환하고, 변환된 토큰 인덱스 배열을 모델에 입력하여 임베딩 벡터를 계산합니다.

get_similarity_scores() 함수는 입력 텍스트와 미리 계산된 임베딩 벡터들과의 유사도 점수를 계산합니다. 두번째 파라미터로 받은 입력 텍스트를 get_sentence_embeddings() 함수를 사용하여 임베딩 벡터로 변환한 후, 미리 계산된 임베딩 벡터들과의 유사도 점수를 계산 후 각 유사도 점수를 scores 리스트에 추가합니다. 이때 emb와 input_text의 크기를 맞추기 위해 get_sentence_embeddings()함수를 호출할 때 input_text를 리스트로 감싸서 전달했습니다.

설유민

스크린샷 2023-06-01 오전 11 21 08

get_sentence_embeddings

get_similarity_scores

결과

스크린샷 2023-06-01 오후 12 37 30
t2easure commented 1 year ago

2조

1. image

  1. tokenizer를 사용하여 토큰화한다
  2. get_sentence_embeddings함수로 input_text를 임베딩한다
  3. cal_score로 유사도를 계산한다

결과

image

2.

image

결과 image

image

JOHAJUN commented 1 year ago

5조

5 31 hai
  1. 입력문장들을 tokenizer를 이용하여 토큰인덱스로 변환
  2. 임베딩 계산
  3. 임베딩 둘의 유사도를 계산
YUNHYUNWOO commented 1 year ago

3조

image

  1. Tokenizer를 통해 입력문장을 변환.
  2. 토큰화된 배열을 model을 통해 임베딩으로 변환
  3. cal_score 함수를 통해 벡터간 유사도를 계산하여 scores 리스트에 저장

HAI 7-2 결과

twkang43 commented 1 year ago

강태욱

1. Cosine Similarity 사용

Screenshot 2023-07-24 at 22 46 28

  1. Tokenizer를 사용해 뉴스 기사 제목들을 토큰 인덱스 배열로 변환 후, 임베딩을 계산한다.
  2. 입력받은 input_text와 미리 토큰화한 뉴스 제목들 사이의 유사도를 계산해 유사도 점수가 가장 높은 5개의 뉴스 제목을 출력한다.

결과

Screenshot 2023-07-24 at 22 50 06

2. Euclidean Distance 사용

cal_score 함수를 다음과 같이 변경하여 euclidean distance를 계산하도록 하였다. Screenshot 2023-07-24 at 23 09 13

그러나, 해당 함수는 뉴스 제목 사이의 유사도를 정확히 계산하지 못해 다음과 같이 키워드와 연관 없는 뉴스 제목을 출력하였다.

Screenshot 2023-07-24 at 23 11 08

mnxcv commented 1 year ago

임세훈

코드

import numpy as np
import math
def cal_score(a, b):
    # 0번째 토큰에 해당하는 임베딩 벡터만 사용
    a = a[0:1]
    b = b[0:1]

    # 각 벡터 정규화
    a_norm = a / a.norm(dim=1)[:, None]
    b_norm = b / b.norm(dim=1)[:, None]

    # 정규화된 두 벡터를 곱하여 유사도 점수 계산
    return torch.mm(a_norm, b_norm.transpose(0, 1)).item() *100

def proj_sim(a, b):
  a = a[0:1]
  b = b[0:1]

  diff = torch.matmul(a, b.transpose(0, 1)) / (b.norm(dim = 1) ** 2)[:, None]
  diff = abs(diff[0].item() - 1)
  return 2 / (1 + math.e ** diff)
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, cal):
  # 입력 텍스트에 대한 임베딩을 계산합니다.
  input = []; input.append(input_text);
  input_embedding = get_sentence_embeddings(input)[0] # <- Input text에 대한 Vector

  # 입력 텍스트의 임베딩과 미리 계산된 임베딩 사이의 유사도를 계산합니다.
  scores = []
  for emb in embeddings:
    scores.append(cal(emb, input_embedding))

  return scores
# 이 부분은 수정하지 마세요!

def main(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에 해당하는 뉴스 제목과 유사도 점수 출력
  for i, idx in enumerate(top_5_idx):
    print(f"{i+1}. {news_titles[idx]}\t(score: {format(similarity_scores[idx], '.2f')})")

실행

입력 > 비건
출력 > 입력과 유사한 상위 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)

사용한 Colab Notebook 주소는 여기에서 확인할 수 있습니다.

KangMeanWoo commented 1 year ago

강민우

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를 이용하여 문장을 토큰 인덱스로 변환

  1. 임베딩을 코사인 유사도를 통해 계산
  2. 유사도가 비슷한 상위 5개 뉴스 제목 출력

image