Home [BoostCamp AI Tech / P Stage 2] Day51 - Project Day 11
Post
Cancel

[BoostCamp AI Tech / P Stage 2] Day51 - Project Day 11

P Stage 2 : Project Day 11


Day 11 list

  1. VASP 논문 발표
  2. RecVAE 학습 pipeline 설계 및 리팩토링

시간이 늦어서 좀 간단하게 적고 가겠습니다.


VASP 논문 발표

  • MovieLens에서 좋은 성능을 보이고 있는 VASP 논문 발표를 진행함
  • 준비가 좀 덜 된 상태에서 발표하다보니 약간 아쉬움이 존재했음
  • 좀 더 자세한 내용은 현재 포스팅으로 작성중
  • 발표자표 링크

RecVAE 학습 pipeline 설계 및 리팩토링

  • 지난 Multi-VAE와 마찬가지로 학습 파이프라인 구축이 덜 된 모델을 파이프라인 형태로 설계했음
  • 해당 과정에서 일부 pandas 버전이 맞지 않는 부분에 대해서도 리팩토링을 진행함
  • VAE 계열의 모델은 preprocessing 과정이 동일해서 1개의 전처리 코드로 통일하는 것이 좋아보임
  • RecVAE에 대한 이해가 없는 상태에서 일단 기존 코드를 재가공했는데, Recall@10이 초반에 확 컸다가 끝으로 갈수록 내려가는 이상한 현상이 나타남
  • 모델의 인코더와 디코더를 학습하는 과정이 존재하는데 이 과정에서 모델 자체가 global로 유지되야 할 것 같음
    • 근데 파이썬은 모델을 인자로 넘겨줘도 유지가 될텐데…
    • 내일 팀원한테 물어보거나 모델 코드 원본이나 논문을 좀 읽어볼 필요가 있을듯
  • 리팩토링 과정에서 코드적인 부분에서 몇가지 의문점이 드는데 간단히 작성해두자

torch.zeros VS torch.Tensordata.fill_(0)

RecVAE에서 CompositePrior의 구현부에서 원본 코드는 다음과 같이 작성되어 있었습니다.

1
2
3
4
5
6
7
8
self.mu_prior = nn.Parameter(torch.Tensor(1, latent_dim), requires_grad=False)
self.mu_prior.data.fill_(0)

self.logvar_prior = nn.Parameter(torch.zeros(1, latent_dim), requires_grad=False)
self.logvar_prior.data.fill_(0)

self.logvar_uniform_prior = nn.Parameter(torch.Tensor(1, latent_dim), requires_grad=False)
self.logvar_uniform_prior.data.fill_(10)

이 부분에서 왜 굳이 torch.zeros를 안쓰고 torch.Tensor를 활용하고 0으로 초기화하는지 이해가 가지 않았습니다. 큰 영향을 주진 않을 거 같지만 좀 더 좋은 코드를 위해 아래와 같이 수정했습니다.

1
2
3
4
self.mu_prior = nn.Parameter(torch.zeros(1, latent_dim), requires_grad=False)
self.logvar_prior = nn.Parameter(torch.zeros(1, latent_dim), requires_grad=False)
self.logvar_uniform_prior = nn.Parameter(torch.Tensor(1, latent_dim), requires_grad=False)
self.logvar_uniform_prior.data.fill_(10)

반복문을 활용한 코드의 압축은 항상 좋을까?

이 부분은 사실 미관상 너무 길고 반복된 코드를 좋아하진 않는 편이라 진행한 코드 수정과정입니다. 우선 원본 코드부터 보여드리겠습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Encoder(nn.Module):
    def __init__(self, hidden_dim, latent_dim, input_dim, eps=1e-1):
        super(Encoder, self).__init__()
        
        self.fc1 = nn.Linear(input_dim, hidden_dim)
        self.ln1 = nn.LayerNorm(hidden_dim, eps=eps)
        self.fc2 = nn.Linear(hidden_dim, hidden_dim)
        self.ln2 = nn.LayerNorm(hidden_dim, eps=eps)
        self.fc3 = nn.Linear(hidden_dim, hidden_dim)
        self.ln3 = nn.LayerNorm(hidden_dim, eps=eps)
        self.fc4 = nn.Linear(hidden_dim, hidden_dim)
        self.ln4 = nn.LayerNorm(hidden_dim, eps=eps)
        self.fc5 = nn.Linear(hidden_dim, hidden_dim)
        self.ln5 = nn.LayerNorm(hidden_dim, eps=eps)
        self.fc_mu = nn.Linear(hidden_dim, latent_dim)
        self.fc_logvar = nn.Linear(hidden_dim, latent_dim)

RecVAE에서 Encoder 부분의 레이어 선언부입니다. 입력에 연결되는 self.fc1self.ln1을 제외하고 나머지 레이어 세트 (fcn, lnn)은 반복되는 형태를 띄고 있습니다. 따라서 적은 수의 반복문을 돌기 때문에 코드 간소화를 하고자 nn.ModuleDict를 활용하여 다음과 같이 수정했습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Encoder(nn.Module):
    def __init__(self, hidden_dim, latent_dim, input_dim, eps=1e-1):
        super(Encoder, self).__init__()

        self.encoder = nn.ModuleDict()

        # original code is too long
        for i in range(0, 5):
            if i == 0:
                self.encoder[f"fc{i+1}"] = nn.Linear(input_dim, hidden_dim)
                self.encoder[f"ln{i+1}"] = nn.LayerNorm(hidden_dim, eps=eps)
            else:
                self.encoder[f"fc{i+1}"] = nn.Linear(hidden_dim, hidden_dim)
                self.encoder[f"ln{i+1}"] = nn.LayerNorm(hidden_dim, eps=eps)
        self.fc_mu = nn.Linear(hidden_dim, latent_dim)
        self.fc_logvar = nn.Linear(hidden_dim, latent_dim)

근데 이렇게 수정하고 문득 들은 생각은 과연 반복문으로 코드를 압축한게 좋은 코드일까?라는 생각이 들었습니다. 우스갯소리로 ‘1~10까지 출력하는 코드를 짤 때 반복문을 쓰는 것도 좋지만 때로는 그냥 출력문 10개 적는게 나을 수도 있다’는 말도 있는데 이게 이런 상황에서 적용되는게 아닐까라는 생각이 들긴했습니다.
막 엄청 성능에 영향을 미치지는 않을 것으로 보이나 과연 다른 사람이 봤을때 이 코드는 원본 코드보다 Encoder module의 구조를 잘 알 수 있을까? 라는 생각이 들기는 합니다.


이번주 할 것 (Rough)

  • EASE 모델 코드 확인해보기
  • AutoRec 구현 및 대회에 적용해보기
  • NGCF 최적화 작업 시도해보기
  • 앙상블 아이디어 고려하기
  • 모델 관점보다 데이터적인 관점을 좀 더 바라볼 필요가 있을듯
    • 추천 모델을 본격적으로 다뤄보다보니 데이터를 너무 간과하고 있었음
    • EDA를 처음부터 다시 하나하나 구상해볼 필요가 있을듯
This post is licensed under CC BY 4.0 by the author.

[Paper Review] Deep Variational Autoencoder with Shallow Parallel Path for Top-N Recommendation (VASP)

[BoostCamp AI Tech / P Stage 2] Day53 - Project Day 13

Comments powered by Disqus.