Background:
Challenge:
Method:
Tangential Contrastive Learning
MGRC Sampling
Experiment & Result:
목차만 봤을 때 느낀점! : method부분이 엄청 디테일하고, analysis도 분야를 나눠서 꼼꼼하게 분석했다. 까일 구석을 못만들겠다는 듯이. 그리고 수도코드도 있는데 실제 코드도 덧붙였다 ㅇ_ㅇ 와우~
method부분에서 이런게 novelty다 하는 걸 배워보자!!!!!!!
paper: https://aclanthology.org/2022.acl-long.546.pdf
github: https://github.com/pemywei/csanmt
Cheng, Y., Tu, Z., Meng, F., Zhai, J., & Liu, Y. (2018, July). Towards Robust Neural Machine Translation. In Proceedings of the 56th Annual Meeting of the Association for Computational Linguistics (Volume 1: Long Papers) (pp. 1756-1766).
interpolating 해가지고
같은 context를 가지고 있는 단어로 바꾼다.계속 descrete한것의 단점을 말했음. 그래서 continuous한 작동이 필요하단거겠지?
in this paper, adjacency semantic region (the vicinity manifold)을 포함하고 있는 VRM 사용
Continuous Semantic Augmentation (CSANMT):
descrete sentences들을 continuous space로 transforming 시켜서 data space를 augment하고 NMP 모델의 generalization capability를 개선!
adjacency semantic region
을 support하고 region의 tangent points
를 semantic을 유지하는데 중요한 요소로 인식하게 함.Notation
Goal
Task 1 - NMT: to maximize the log-likelihood
Task 2 - Augmentation
[Recap] 기존 seq2seq NMT 한계
- 기존의 supervised setting의 NMT 방식은 데이터 수에 의해 학습이 좌지우지 됌. 그래서 unseen data에 대해서는 성능이 하락해버림.
- 보통 seq2seq은 source space를 target space로 transformation하는 걸 학습함.
[Recap] 원래 transformer 구조
x,y라는 discrete sentences들을 forward function 을 통해 continuous한 vector로 mapping 시켜버림. => source와 targe language들이 universal한 semantic space에 위하게 됨.
그럼 저 공간에 있는 애들 사용해서 새로 만드는 거겠지?
Process
1) adjacency semantic region이 생겼으면 거기서 K
개 만큼 vector sample들을 뽑는다.
x,y 상관없이 뽑는거구나?
2) 그럼 각각의 sample들은 broadcasting integration network를 통해서 원래의 generation process (본래의 NMT 수행하러)로 통합된다.
3) Final training objective
[Recap] 기존 NMT objective
Challenge
traininig instance 를 augmentation하는데 adjacency semantic region에서 다양한 sample들을 가져왔기 때문에 unseen instances에서도 generalize할 것이다! 기존 방식들은 discrete한 방식이라서 pair를 이루며 새롭게 생성했지만 이건 distribution 차원에서 변주를 줬으니 더 다양한 sample이 나올 수 있겠지???
BUT!
Tangential Contrastive Learning
MGRC sampling
[Recap] adjacency semantic region
- 중심으로 펼쳐진 원 안에 있는 애들 랑 의미가 같다고 보는 겨.
따지면 same meaning의 마지노선 이니까?
)그니까 적당히 멀어야 region안에 안들어오는 애들로 negative sample 만드는거군! 굳이 lambda 값을 만든 이유는 tuninig 해가지고 sample 여러개 만들려는 것이군!!
- 근데... 일때라는 건 계산해보니 일 때라는 건데 이게 말이 됩니까? negative sample이랑 orginal이랑 같을 때라니요..????
- 아하 vector 계산으로 해야 하는 구나?
그렇다면 이 뜻은 빨강색선과 초록색 선이 같아지는 때! 일 때 겠다.
- 는 sample의 수가 많아질 수록 stationary 한 distribution이 될 수 있고, 이는 training instance의 diversity가 유한하다는 것을 의미한다.
무슨소리래
- 나의 짐작: sample 수가 충분히 많아지면 분포는 일정한 패턴으로 수렴한다. 그러니까 엄청난 변이는 없다는 것이지. 그러니 original meaninig에서 크게 안벗어날 수 있도록 장치를 썼다. 이런 거 아닐까?
- 얘네의 challenge가 1) Diversitiy 2)기존 meaning preservation 인데 1)은 tangent contrastive로 semantic region만들어서 달성하고, 2)는 sampling을 제한된 공간에서 하면서 원래에서 크게 벗어나지 않게 하는 것이지!
Task | Corpus | Val | Test |
---|---|---|---|
Zh -> En | LDC | NIST2006 | NIST2002,2003,2004,2005,2008 |
En -> DE | WMT14 | newstest2013 | newstest2014 |
En -> FR | WMT14 | newstest2012,2013 | newstest2014 |
*Zh: Zhōngguó
논문 확인
많이 만드는 데 한계를 만들었다?!
)[REF]
tensorflow로 되어있어서 pytorch로 바꿈
similarity 구하는 부분은 어디갔지? negative, positive 부분이 왜 src, tg로 되어있는거지..???
# src_embedding: [batch_size, 1, hidden_size]
# trg_embedding: [batch_size, 1, hidden_size]
def get_ctl_loss(src_embedding, trg_embedding, dynamic_coefficient):
batch_size = src_embedding.size(0)
def get_ctl_logits(query, keys):
# expand_query: [batch_size, batch_size, hidden_size]
# expand_keys: [batch_size, batch_size, hidden_size]
# the current ref is the positive key, while others in the training batch are negative ones
expand_query = query.repeat((1, batch_size, 1)) #tf.tile(query, [1, batch_size, 1])
expand_keys = th.transpose(query, 0,1).repeat((batch_size, 1, 1)) # tf.tile(tf.transpose(keys, [1,0,2]), [batch_size, 1, 1])
# distances between queries and positive keys
d_pos = th.sqrt(th.sum(th.pow(query - keys, 2.0), axis=-1)) # tf.sqrt(tf.reduce_sum(tf.pow(query - keys, 2.0), axis=-1)) # [batch_size, 1]
d_pos = d_pos.repeat(1, batch_size) # tf.tile(d_pos, [1, batch_size]) # [batch_size, batch_size]
d_neg = th.sqrt(th.sum(th.pow(expand_query - expand_keys, 2.0), axis=-1)) # [batch_size, batch_size]
lambda_coefficient = (d_pos / d_neg) ** dynamic_coefficient
hardness_masks = (d_neg>d_pos).float() # tf.cast(tf.greater(d_neg, d_pos), dtype=tf.float32)
hard_keys =(expand_query + lambda_coefficient.unsqueeze(-1)* (expand_keys - expand_query)) * \
hardness_masks.unsqueeze(-1) + expand_keys * (1.0 - hardness_masks).unsqueeze(-1)
# (expand_query + tf.expand_dims(lambda_coefficient, axis=2) * (expand_keys - expand_query)) * \
# tf.expand_dims(hardness_masks, axis=2) + expand_keys * tf.expand_dims(1.0 - hardness_masks, axis=2) # [batch_size, batch_size, hidden_size]
logits = th.matmul(query, hard_keys.transpose(1,2)) # tf.matmul(query, hard_keys, transpose_b=True) # [batch_size, 1, batch_size]
return logits
logits_src_trg = get_ctl_logits(src_embedding, trg_embedding)
logits_trg_src = get_ctl_logits(trg_embedding, src_embedding) + th.unsqueeze(th.diagflat(th.diag(th.ones(batch_size,batch_size))) * -1e9, 1)
# logits_trg_src = get_ctl_logits(trg_embedding, src_embedding) + tf.expand_dims(tf.matrix_band_part(tf.ones([batch_size,
# batch_size]), 0, 0) * -1e9, axis=1)
logits = th.cat([logits_src_trg, logits_trg_src], axis=2) # [batch_size, 1, 2*batch_size]
labels = th.arange(start=0, end = batch_size, step =1) # labels = tf.expand_dims(tf.range(batch_size, dtype=tf.int32), axis=1) # [batch,1]
loss = th.nn.functional.cross_entropy(logits.squeeze(), labels)
#labels = th.nn.functional.one_hot(labels,num_classes=2*batch_size) #tf.one_hot(labels, depth=2*batch_size, on_value=1.0, off_value=0.0) # [batch_size, 1, 2*batch_size]
#cross_entropy_fn = tf.nn.softmax_cross_entropy_with_logits
#loss = tf.reduce_mean(cross_entropy_fn(logits=logits, labels=labels))
return loss
참고 - basic contrastive learning
https://jimmy-ai.tistory.com/312
시간 없어서 못바꿈. 그런데 알고리즘이랑 아주 똑같이 코딩되어 있음
# src_embedding: [batch_size, hidden_size]
# trg_embedding: [batch_size, hidden_size]
# default: K=20 and eta = 0.6
def mgrc_sampling(src_embedding, trg_embedding, K, eta):
batch_size = tf.shape(src_embedding)[0]
def get_samples(x_vector, y_vector):
bias_vector = y_vector - x_vector
W_r = (tf.abs(bias_vector) - tf.reduce_min(tf.abs(bias_vector), axis=1, keep_dims=True)) / \
(tf.reduce_max(tf.abs(bias_vector), 1, keep_dims=True) - tf.reduce_min(tf.abs(bias_vector), 1, keep_dims=True))
# initializing the set of samples
R = []
omega = tf.random_normal(tf.shape(bias_vector), 0, W_r)
sample = x_vector + tf.multiply(omega, bias_vector)
R.append(sample)
for i in xrange(1, K):
chain = [tf.expand_dims(item, axis=1) for item in R[:i]]
average_omega = tf.reduce_mean(tf.concat(chain, axis=1), axis=1)
omega = eta * tf.random_normal(tf.shape(bias_vector), 0, W_r) + \
(1.0 - eta) * tf.random_normal(tf.shape(bias_vector), average_omega, 1.0)
sample = x_vector + tf.multiply(omega, bias_vector)
R.append(sample)
return R
x_sample = get_samples(src_embedding, trg_embedding)
y_sample = get_samples(trg_embedding, src_embedding)
return x_sample.extend(y_sample)
Strength
Weakness
좋은 논문 리뷰글 잘 보았습니다 !
1. 실제로 text augmentation을 할 때 미세한 변화에도 의미가 달라지는 경우가 있지 않을까 ? 의문이 든 적 있었는데 본 논문에서 Continuous Semantic Augmentation를 통해 이를 해결하고자 했던 점이 와닿았습니다! low resource data에 적용할 때 유용할 것이라 생각했는데, rich resource data에 적용했을 때도 좋았다는 점까지 있어서 무릎을 탁! 쳤답니다
2. 코드 리뷰까지 깔끔하게 해주셔서 어떻게 구현되었는지 확인하기 용이했습니다 tf -> pytorch 코드 바꾸는 게 손이 많이 갔을 텐데 정성이 느껴집니다 !
augmentation 관련한 좋은 본 논문 소개해주셔서 감사합니다 !! tangential contrastive 방법과 MGRC sampling 방법 알 수 있어 좋았습니다, 더불어 논문을 읽으시면서 느끼신 부분들에 대해서 알려주신 점들을 통해 논문 읽는 방법들을 함께 배운 것 같아 뜻 깊은 시간인 것 같습니다 !! What if I am a reviewer of this paper? 가 특히 인상깊었습니다. 좋은 논문 소개 감사합니다