Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MonoLingRD: 왜 로스가 수렴하지 않을까? #7

Closed
eubinecto opened this issue Jun 13, 2021 · 7 comments
Closed

MonoLingRD: 왜 로스가 수렴하지 않을까? #7

eubinecto opened this issue Jun 13, 2021 · 7 comments
Labels

Comments

@eubinecto
Copy link
Owner

eubinecto commented Jun 13, 2021

The Problem?

A red fruit a yellow fruit the fruit that monkeys love
image image image

어떤 입력이 들어와도, 랭크가 동일하다... 첫번째, 세번째는 출력이 그냥 동일하다.

Analysis

어떤 인풋이 들어오던간에, 순서가 고정이다. 고정인 이유가 무엇인가?
일단, pineapple이 꼴찌인 것을 보면... 분명 데이터에서 무엇인가를 학습한 것은 맞다.
아마 문제는 둘로 나뉘지 않을까 싶다.

  1. 로스 계산과정에 오류가 있던지.
  2. 데이터 부족에서 나온 이유이던지.
@eubinecto
Copy link
Owner Author

eubinecto commented Jun 13, 2021

어떤 인풋을 넣던 동일한 인풋으로 들어가는 상황인가?

한번 pre-trained bert로 시도를 해보자.

image

여전히 bias가 있긴하지만, 랭크에 유의미한 변화가 있긴 있다. 즉 다른 인풋을 넣으면 다른 인풋이 들어가는 것은 맞음.

@eubinecto
Copy link
Owner Author

eubinecto commented Jun 13, 2021

Data shuffle을 안한 것이 문제인가?

그동안 dataloader에서 shuffle을 False로 두고 훈련을 해왔었다. 혹시 이게 문제인가? 데이터셋도 contiguous한 것을 고려해보면, 이것이 문제인 것일 수도 있다.

변경해보기

  • DataLoader의 shuffle을 True로 두고, 다시 학습을 진행함.
  • 랭크 스코어를 좀 더 직관적으로 이해하기 위해서, fruitify마지막 값을 softmax로 확률분포로 바꿈.

결과

A red fruit a yellow fruit the fruit that monkeys love
image image image
  • 문제는 여전함; 랭크는 모든 입력에 대하여 고정.
  • 다만 달라진점이 있다 - 미미한 차이긴 하지만, 모든 입력에 대하여 값이 다르긴 함. MonoLingRD: 왜 로스가 수렴하지 않을까? #7 에서 A red fruitThe fruit that monkeys love가 모두 동일한 경우와는 확실히 다르다.
    • 즉 미미하긴 하지만, 로스를 구하는 배치의 다양성 증가 -> 성능의 향상이 있긴 한것 같음.

해결책?

배치 = 전체 훈련셋의 크기로 바꾸면 어떻게 될까? ( 5 * 8) = 40.
그러면 다양성은 100% 보장이 되는거니까..
일단 한번 이렇게 시도를 해보자.

@eubinecto
Copy link
Owner Author

eubinecto commented Jun 13, 2021

배치 속의 다양성 부족이 문제인가?

변경해보기

batch_size = 40, 즉 모든 트레이닝 셋을 하나의 배치로 그냥 다 넣어보았다. 그러면 각 단어별 데이터의 개수가 동일하니,
배치 속의 다양성은 이론적으로는 최대치.

  • 이에 맞춰서 epoch도 20까지 늘렸음.
    학습된 모델: mono_epoch=17_train_loss=1.60.ckpt

결과

A red fruit A yellow fruit The fruit that monkeys love
image image image

분석

  • 랭크가 고정이되는건 여전하다.
  • 다만 확률값이 변하는 정도가 많이 변하긴 했음.
  • 이것이 의미하는 것? 아마 코드 상의 문제라기 보단, 데이터 부족이 원인이 아닐까 싶다.
  • 그리고 로스가 1.60 언저리에 머무르는 것도 마음에 들지가 않는다 (the loss does not converge). 이게 좋은 로스가 아닐수도 있다.

해결책

  • the loss does not converge; what should I do?
  • https://stackoverflow.com/q/56952916; increasing the batch size helps - well I have done that; I guess I don't have enough data then.
  • 데이터를 더 가져올 수도 있겠지만, 그냥 torch.repeat으로 각 과일별로 문장이 100개 정도 있도록 up-sampling을 해보는 것도 한가지 방법일 것?
  • 그리고 로스 계산과정에 문제는 없는지, 적어도 dimension을 testing을 하는 코드를 짜자.
  • 정량적인 metric도 필요하다. training accuracy를 한번 측정해보자.

@eubinecto
Copy link
Owner Author

eubinecto commented Jun 13, 2021

로스 계산로직에 문제가 있는 것은 아닐까?

변경해보기

  • forward, S_word, training_step 함수의 in -> out dimension 체크하는 것만. test 스크립트 짜기.

결과

33272071758f1d90035d8a4b26c26359fd511301

    def test_forward_dim(self):
        # (N, 3, L) -> (N, K, |S|)
        S_subword = self.mono_rd.forward(self.X)
        self.assertEqual(S_subword.shape[0], self.X.shape[0])
        self.assertEqual(S_subword.shape[1], self.mono_rd.hparams['k'])
        self.assertEqual(S_subword.shape[2], self.S)

    def test_S_word_dim(self):
        # (N, 3, L) -> (N, K, |S|)
        S_subword = self.mono_rd.forward(self.X)
        # (N, K, |S|) -> (N, |V|)
        S_word = self.mono_rd.S_word(S_subword)
        self.assertEqual(S_word.shape[0], self.X.shape[0])
        self.assertEqual(S_word.shape[1], self.V)

    def test_training_step_dim(self):
        # (N, 3, L) -> scalar
        loss = self.mono_rd.training_step((self.X, self.y), 0)
        self.assertEqual(len(loss.shape), 0)  # should be a scalar

이렇게 dimension만 테스트를 하는 코드를 짜보았는데, 전부 패스한다.

분석

일단, 로스 계산 로직에 큰 문제가 없다는 가정을 해야할 것 같다.

@eubinecto
Copy link
Owner Author

eubinecto commented Jun 14, 2021

단순히 데이터 수가 부족한 것이 문제인걸까?

변경해보기

데이터를 더 수집해보았자, 각 과일에 해당하는 정의는 거기서 거기일 것.
그렇다면 그냥 torch.repeat 함수로 데이터를 단순복사해서 upsampling하는 것도 한가지 방법이다.

그런데 솔직히 이게 될까? 클래스 별 불균형이 있는 것도 아니고, 어차피 샘플의 개수만 늘리는 것으로는...
그냥 훈련시간만 길어지는 결과를 초래하는 것 아닐까?

일단 한번 해보자!

GPU를 사용해보려고 했는데, device에 옮기는 작업을 안해서 좀 애먹었다.
새로운 tensor를 만들때 마다, 반드시 X = X.cuda()를 해줘야 한다. 이 패턴 기억하자.

image

이렇게 그냥 샘플을 늘릴 수 있도록 추가했다.

그리고 cuda() 관련 오류도, 새로운 tensor를 만드는 경우 반드시 cuda()를 호출하는 식으로, 일단 핫픽스를 했다. infer를 할때도 모델을 cuda()로 옮겨야 한다. 3de9798f6656f5979e33823d80ceca286658b2bb

결과

repeat 을 20으로 두고서 학습을 진행함.
batch size는 여전히 40으로 고정.

A red fruit a yellow fruit The fruit that monkeys love
image image image

별 달라진 점이 없다.

배치 크기를 늘려보면 어떨까?

repeat = 20,
batch = 100으로 해보았다.

image

크게 변하는 것은 없다.
어쩌면 이 랭크가. 최적의 순서인 것일수도 있다. 로스 함수가 단순히 모든 score를 더하는 것 뿐이니...
도대체 로스가 무엇을 기준으로 최적화되는 것인지 가늠이 가지가 않는다.

다음?

현재의 고정된 랭크가 최적의 순서라면, 이건 혹시 underfitting이 문제는 아닐까?
안그래도 #7 여기에서 loss가 1.6에서 머무르는 것이 마음에 들지가 않았는데. 그러면 learning rate를 낮추면 해결할수 있지 않을까?

@eubinecto
Copy link
Owner Author

eubinecto commented Jun 24, 2021

Underfitting 이 문제인가?

변경해보기

lr: 0.001 -> 0.00001 로 줄여보자!

결과

image

기존에는 1.59에 머무르던 loss가 (training loss), 이번에는 0.0459까지 내려갔다.

그렇게 얻게된 모델:
data/
├── fruit2def.tsv
└── lightning_logs
└── version_0
├── checkpoints
│   └── mono_epoch=11_train_loss=0.04.ckpt
├── events.out.tfevents.1624510963.eubinCloud.37272.0
└── hparams.yaml

결과:

A red fruit A yellow fruit The fruit that monkeys love
image image image

해결했다아아아아아ㅏ

특히 세번째 쿼리가 흥미롭다. 데이터셋에 바나나에 대한 정의에 monkeys가 언급된 부분은 없었는데, 쿼리로 The fruit that monkeys love를 주니, 해당하는 단어가 바나나일 확률이 70%로 출력된다. 다시한번 반복해도, 똑같은 결과가 나온다 (model.eval()).

Reflection

역시 기본기가 중요하다. 왜 learning rate를 낮출생각을 못했을까.

하지만 덕분에 별의별 삽질을 다하며 배운게 많다. #7 배치 속 다양성이 성능에 영향을 끼친다는 것을 배웠고, #7 출력의 차원을 테스트하는 것으로 로직을 간이 테스트할 수 있다는 것을 배웠고, #7 파이토치에서 gpu를 사용하기 위해서는 새로운 tensor를 instantiate할 때마다 tensor.cuda()로 gpu에 텐서를 옮겨야한 다는 것 을 배웠고, #7 입력에 관계없이 prediction이 거기서 거기라면 underfitting을 의심해야한다는 것도 배웠다. 1.60이 생각보다 큰 로스상태라는 것도 알게되었다.

@eubinecto
Copy link
Owner Author

closing the issue with 2837b67ca697d4c9941a929b3775e51300f18083

@eubinecto eubinecto transferred this issue from eubinecto/fruitify Apr 15, 2022
@eubinecto eubinecto changed the title Debugging MonoLingRD MonoLingRD: 왜 로스가 줄어들지 않을까? Apr 15, 2022
@eubinecto eubinecto changed the title MonoLingRD: 왜 로스가 줄어들지 않을까? MonoLingRD: 왜 로스가 수렴하지 않을까? Apr 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant