파이토치 학습

제가 논문이 구현되어있던 코드를 고치고 있습니다.

알고리즘을 대략 설명해드리면 logits이라는 행렬을 log_softmax() 함수를 통해서 로그 소프트맥스값을 얻은 뒤,
그 로그 소프트맥스가 취해진 행렬에서 정답 값을 가져와서 로스를 만들어 주고 있습니다.

논문에서는 logits이라는 행렬 전체에서 한번에 구했는데 저는 불가피하게 for문을 한번 넣은 뒤, 각 행마다의 sub_loss를 구하고 final_loss를 구해주는 방식으로 코딩을 했는데요, 제가 작성한 코드는 학습이 되질 않네요.

뭐가 문제일까요…?
loss1

loss2

위에는 제가 작성한 코드이며 아래는 논문에서 작성된 코드입니다.

////////////////////////////////////////////////////////////////////////////////////////////////////////////

모델을 계속 디버깅하다가 확인했는데
optimizer.zero_grad()
loss.backward()
optimizer.step()
을 통과해도 모델의 weight가 바뀌지않네요.
이런 경우는 어디를 먼저 확인해봐야할까요?
혹시 logits과 loss의 텐서가 서로 다른 gpu에 선언되면 backward가 안되나요??

감사합니다.

옷, 제가 올려주신 코드와 질문을 이해를 못한 것 같습니다ㅠ

구현하신 코드와 비교할 코드를 나눠서 보여주시면 같이 헤맬 수 있지 않을까요 -0-;;

1개의 좋아요

loss를 계산하실 때 모델을 통과한 값들을 사용하셨으면 autograd가 잘 들고 있다가 backward()를 해줄거 같은데 이상하네요 :confused:

loss2

위의 코드가 기존 논문에서 작성된 코드입니다.
model을 통과한 feature가 z구요, z와 z.t()를 곱해서 코사인유사도를 구한 매트릭스가 logits입니다.
그 후에 logits의 log_softmax값을 구한뒤, 정답 label의 log_softmax값의 평균을 구한게 전체 loss입니다.

loss1

이게 제가 다시 구현한 코드입니다. 행을 하나하나씩 다 찾아봐야할 이유가 생겨서 각 행렬을 for문을 한번 사용해서 행마다 log_softmax를 구한뒤 정답값을 sub_loss로 구현하여 logits 전체의 sub_loss를 다 더한뒤 평균을 구해서 전체 loss로 구현하였습니다.

loss 값이 나오긴하는것같은데 모델의 weight를 optimizer.step()하기 전과 후로 나누어서 여러번 찍어봤는데
하나도 변하지가 않네요.

텐서 사이즈가 제가 생각한게 맞는지 확인 부탁드립니다.
logits가 (batch_size, feat_dim) 이면
logprob이 (feat_dim) 이 될 것 같은데요
맞을까요?

softmax 부분을 for 안으로 넣으시면서 사이즈를 착각하신건 아닐까요?
제 생각에는 아래와 같은 형식이 되야할 것 같습니다

logprob = F.log_softmax(logits,dim=1)
for i in range(len(logits)):
  if i < batch_size:
    sub_loss = -logprob[batch_size+i]
...

logits이 (2batch_size, feat_dim) * (feat_dim, 2batch_size)이기 때문에 (2batch_size, 2batch_size)가 됩니다.
logprob도 (2batch_size, 2batch_size)가 됩니다.
따라서 logits의 한 행은 한 이미지와 나머지 배치 사이즈의 코사인 유사도를 나타냅니다.
logprob을 한 행마다 구해야해서 for문 안에 logprob = F.log_softmax(logits[i], dim=0)으로 구현한 상태입니다.

혹시 제 생각이 잘못되거나 틀린부분 알려주시면 감사하겠습니다.
이게 코드 전체를 올릴수도 없어서 답답하네요 ^^;

일단 말씀 해주신건 이해했습니다. 그래도 softmax는 효율상 밖으로 빼시는게 좋을듯…

loss를 구할때 여러개를 합하는건 문제가 없습니다.
그리고 디바이스를 바꾸도것도 문제가 없을 것 같습니다. 요건 확신이 좀 없지만…

로스의 크기나 그레디언트, 러닝레이트, 옵티마이저 등등을 봐야하지 않을까 싶은데요
이런 것들은 돌려봐야되는 문제라서 좀 봐드리기가 어렵네요

1개의 좋아요

흡… 네 알겠습니다.
다시 확인해보니 많이 돌리면 weight가 조금씩 변하긴 하네요.
원인은 좀 더 찾아봐야겠군요 ㅠㅠ

감사합니다.

문제 해결했습니다!
디버깅으로 앞부분을 한줄한줄 뜯어보니 중간에 배치사이즈가 바뀌어있네요;
그래서 정답값을 잘못선택해서 생긴일이었네요 ;;
댓글써주신 분들 모두 감사드립니다!!

다음부턴 좀 더 잘 찾아보고 질문하도록 하겠습니다 ㅠㅠ;;

1개의 좋아요

오, 축하드립니다~ :tada:

저는 누구한테 물어보고 나면 더 잘 보이더라구요 ㅎㅎㅎ

질문 올려주시고, 자문자답해주시는 것도 환영합니다! :star_struck:

이 글은 마지막 댓글이 달린지 오래(30일)되어 자동으로 닫혔습니다. 댓글 대신 새로운 글을 작성해주세요! :slight_smile: