Open BaekTree opened 2 years ago
Assume that news data is NOT splitted. Also premised that dataset is defined as ( one news text, multiple passages of one corp )
for given batch with batch size B
batch <- ( news_data, dart_data )
# news_data # (B, 1, hidden_dim, seq_len)
# dart_data # (B, k_j', hidden_dim, seq_len)
# must change dim before input here to ( B, hidden_dim, seq_len )
# encoder output use CLS token at first. No reason. Just convinience.
news_vec = news_encoder(news_data) # ( B, hidden_dim, 1)
change dim from (B, hidden_dim, 1) => (B, 1, hidden_dim)
# must change dim before input here to (B * k_j', hidden_dim, seq_len )
# encoder output use CLS token at first. No reason. Just convinience.
dart_vec = dart_encoder(dart_data) # (B * k_j', hidden_dim, 1)
change dim from (B * k_j', hidden_dim, 1) => (B, k_j', hidden_dim, 1) => (B, k_j', hidden_dim)
# calculate similiarity
# tensor의 multiplication은 뒤 두개는 내적하고 그 앞은 element wise한다는 성질을 적용할 수만 있다면...
sim_score = news_vec * dart_vec.T # ( B, 1, hidden_dim ) * ( B, hidden_dim, k_j') => (B * B, 1, k_j')
change dim from (B * B, 1, k_j') => ( B * B, k_j')
# 동일 기업에 대해 하나로 만들어야 한다.
# soft voting 혹은 평균으로 실수화. 혹은 max. 이것도 나름의 pooling 인것 같다...
# 버트에서 나올 때 pooling, 여기서 또 pooling... 잘 될까...? ㅜㅜ
sim_score_per_corp = some_func(sim_score) # (B * B, 1)
change dim from (B * B, 1) => (B * B)
# ground truth는 대각행렬을 구하면 됨.
# one_B = torch.ones(B) # ( B )
# target = torch.diag( one_B ) # 2D diagonal matrix with value 1 size ( B, B )
# 하지만 언제나 cross entropy가 이걸 알아서 해주지만 항상 까먹지 히히
target = torch.arrange(B)
# calc loss
# B개에서 각 sample 마다 news와 유사한 dart 기업을 선택해야 함.
loss = cross_entropy_loss( sim_score_per_corp, target)
loss.backward()
...
기본 DPR에서는 틀린 답답랑 같이 유사도를 구해서 틀린 답을 구할 수 있었음. 여여기에서는 어떻게?
어차피 1기업 <-> 1뉴스에서는 1차원의 실수로 변환.
우리 task에서도 틀린 것들과 비교를 해야 하는가?
카카오브레인 STS KoSTS baseline 코드를 참조하면 될것 같다.
논문에도 baseline 코드의 approach가 나옴.
대체로 bi encoder가 cross encoder 보다 성능이 떨어지지만 less costly.
두개를 합친 trans encoder 2021 https://www.google.com/search?q=STS+cross+encoding+approach&oq=STS+cross+encoding+approach&aqs=chrome..69i57j69i60j33i160.4022j0j7&client=tablet-android-samsung-ss&sourceid=chrome-mobile&ie=UTF-8
cross encoding: 2개의 pair을 동시에 집어넣는다. 그리고 0과 1 사이에서 유사도를 표현. 인코더 1개. inference할 때 뉴스를 받으면, 각각의 다트 데이터 passage와 pair으로 만들어서 한번씩 모두 inference을 해봐야 한다. 그리고 가장 높은 값 뽑아서 보여줘야 함.
bi encoder: 인코더 두개. 다트는 다트 인코더로 다 인코딩 해둔다. inference할 때 뉴스만 inference 해서 인코딩 하고 나서 다트 인코딩 값들과 유사도 비교해서가장 높은거 뽑음. 뉴스 1개만 인코딩 하면 되어서 real time에 더 가까울 것. 그리고 위에서 직접 시도해봤더ㅏㄴ 방법
Sentence BERT https://arxiv.org/abs/1908.10084
요약: 기존의 버트는 cross encoding을 사용햇음. 위에 적었듯이 inference 느림. 그리고 V100으로 10,000개의 문장 학습할 때 65시간?이 걸렸다고 함. 그래서 bi encoder을 소개하고 아주 빠르다! 샴네스 네트워크 사용
In order to fine-tune BERT / RoBERTa, we cre- ate siamese and triplet networks (Schroff et al., 2015) to update the weights such that the produced sentence embeddings are semantically meaningful and can be compared with cosine-similarity.
논점2 네트워크 구조 혹은 loss 함수 a. classification objectife function k개의 데이터(아마도 배치?)가 들어가면... 두 인코더에 pair의 한짝 씩 들어감. 하나는 u이고 하나는 v이다. u와 v의 차원은 n이다. u, v, u-v을 concat해서 마지막 weight 내적. weight은 3n k차원이다. 내적 결과는 1 k이다. 이 결과를 softmax. k개의 값이 나옴. 각 k개의 label과 cross entropy으로 학습. inference에서는, softmax의 가장 높은 값 출력. => 이 방법이 기존의 dpr과 가장 유사하고 실제고 생각했던 부분이기는 함... dpr에서 했던 것처럼 negative sample은 안해도 되는지? 그냥 random 하게 데이터 섞어서 학습하면 주변 데이터들이랑 혼동하지 않고 잘 할까?
b. Regression Objective Function u와 v을 cossine sim 해서 MSE으로 최적화.
c. triplet objective 일반적인 샴네스 loss임. anchor a와 positive pair p, negative n이 있으면, a - p의 거리가 a- n의 거리보다 크게 학습한다.
$$ loss = max( | a - p | - | a - n | + epsilon, 0 ) $$
논문에서는 euclidian distance으로 계싼할 때 epsilon = 1으로 뒀다 함. 1보다 클 때 제대로 가고 있다고 인정 함. 만약 1보다 작으면 다 0으로 만들어버리고, CE에서 1과 비교 할 때 더 많이 weight 이동하게 됨.
직관적으로 생각해보면... 이렇게 하면 그냥 일반적인 softmax -> cross entopy와 어떤 차이점? softmax - > CE는 주변 데이터셋과 비교해서 학습함. 반면에 triplet 은 우리가 헷갈리는 negative을 직접 만들 때 더 robust한 모델을 만들 수 있을 것 같음. 대신 negative sample을 유의미하게 만들어내야 함. 만약 이걸 쓴다면... 직접 라벨링을 하든지, 혹은 softmax + CE으로 먼저 만든 모델과 bm25을 혼용해서 pseudo labeling까지는 가능할 것도 같아 보임.
STS에 대한 Evaluation supervised STS을 했을 때 regression objective function을 사용했다고 하고 0.8이상의 성능을 냈음. 버트와 로버타의 차이는 크지 않았다고 함. 특이한 점은 STSb을 학습하기 전에 NLI? NLU?을 먼저 학습하고 STSb을 다시 학습했더니 점수가 1,2점 상승했다고 함. 우리도 domain adatiption 등으로 이런 효과를 기대할 수 있을까? 특이한점 2: 학습할 때 시드 고정을 하지 않음. 일부러 randomness을 적용해서 bias을 피하려고 했다고 함. 희망적인 부분은 사용한 데이터가 캡션, 뉴스, 포럼 데이터라는 것. 우리도 뉴스 데이터를 사용하고, 다트 데이터는 passage으로 짧게 잘려 있음.
단점은 정확도가 떨어진다는 것?
영어지만... 각종 유사도가 다들어 있는 라이브러리! https://www.sbert.net/docs/publications.html
생각하는 방향성: 일단 논문에서 나온대로 주변 데이터에서 제일 좋은 성능을 냈다고 하는대로 regression objective function을 만들어보고, 샴네스로 넘어가는 것도?
그런데 이렇게 하려면... STSb와 같이 유사도가 0~5 사이와 같이 어쨌거나 실수로 유사도가 표현이 되어야 함. 이것 역시도 추가적인 데이터가 필요함...
일단 softmax + CE으로 만들어보고 pseudo labeling을 해야 하나? 일단 만들고 -> 어느 정도 모델이 유사하다고 판단한 데이터를 새로 만들되, 유사도 결과가 내적값 실수로 나올테니까 그 값으로 유사도 결과를 사용?
Assumption: 뉴스 기사가 1개일 때
뉴스 기사에 m개의 기업이 나옴. 나오는 기업 집합 C= {c_i | i = 1, ..., m}
데이터셋에 k개의 다트 기업이 있음. 각 기업 $c_j$는 $k_j'$개의 passage으로 구성 됨.
dataset columns corp : news_text : corp_passage
train set 기업 $c_j$에 대해, ($c_j$가 나오는 뉴스기사 text, $c_j$에 속한 passage $c_j'$)가 1개의 데이터셋이 됨. 기업 $c_j$에 $k_j'$의 passage가 있으므로, 위의 데데이터이 $k_j'$개 있음.
train when batch size = 1,
encoder1은 뉴스 기사 text을 인코딩 -> 1개
encoder2는 $k_j'$개의 다트 passage 인코딩 -> $k_j'$개
loss 계산
vectorization을 더 할 수 있을까? 데이터셋 마다 수가 달라서...