nn.transformer 결과값이 생각한대로 안나옵니다.

import torch
import torch.nn as nn
import matplotlib.pyplot as plt

class Net(nn.Module):
  def __init__(self):
    super().__init__()
    self.embedding = nn.Embedding(10, 20)  #수정
    self.transformer = nn.Transformer(20, 5,dropout = 0) #수정
  def forward(self, src, tgt):
    tgt_mask=self.transformer.generate_square_subsequent_mask(tgt.shape[1])
    src =  self.embedding(src)
    src=src.permute(1,0,2)
    tgt = tgt.permute(1,0,2)
    out = self.transformer(src, tgt, tgt_mask=tgt_mask)
    out = out.permute(1,0, 2)
    return out

critic = nn.L1Loss()
model = Net()
optim = torch.optim.Adam(model.parameters(), 3e-4)

src = torch.randint(1, 10, (50, 10)) #수정

tgt = torch.rand((50, 10, 20))#수정
tgt_input = torch.cat((torch.zeros((50, 1, 20)), tgt[:, :-1, :]), 1)  #수정

epoch = 0

model.train()
for epoch in range(10000):  #계속 돌리기 위해 수정
  optim.zero_grad()
  out=model(src, tgt_input)
  loss=critic(out, tgt)
  
  loss.backward()
  optim.step()
  if epoch%100 == 0:
    fig, (ax0, ax1)=plt.subplots(2, 1)
    ax0.pcolor(out[0].to('cpu').detach().numpy())
    ax1.pcolor(tgt[0].to('cpu').detach().numpy())
    plt.show()

  epoch +=1

model.eval()
tgt_input = torch.zeros((50, 1, 20))
with torch.no_grad():
  for _ in range(10):
    out=model(src, tgt_input)
    tgt_input = torch.cat((tgt_input, out[:, -1:, :]), 1)
  
  fig, (ax0, ax1)=plt.subplots(2, 1)
  ax0.pcolor(out[0].to('cpu').detach().numpy())
  ax1.pcolor(tgt[0].to('cpu').detach().numpy())
  plt.show()

train시 마지막 결과 그림은 다음과 같습니다.
image

eval시 결과그림은 다음과 같습니다.
image

다음과 같이 eval시 trian시의 결과값처럼 도출이 안되는데 되게하는 방법이 없을까요?

학습과 동일한 입력를 넣으셨다면 동일한 결과를 얻으실 수 있을 것 같습니다.
model.eval()
tgt_input = torch.cat((torch.zeros((50, 1, 20)), tgt[:, :-1, :]), 1) #수정
with torch.no_grad():
out=model(src, tgt_input)
fig, (ax0, ax1)=plt.subplots(2, 1)
ax0.pcolor(out[0].to(‘cpu’).detach().numpy())
ax1.pcolor(tgt[0].to(‘cpu’).detach().numpy())
plt.show()

seq2seq처럼 eval부분에서 inital데이터를 넣어서 스택처럼 쌓아 결과값을 보려고 한 것인데요.
사실 transformer tts를 nn.transformer로 되지 않를까해서 해본건데 안되더군요.

import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
import matplotlib.pyplot as plt
class Net(nn.Module):
    def __init__(self):
        super().__init__()
        self.transformer = nn.Transformer(30, 5, 3, 3, batch_first=True, dropout=0)
    def forward(self, x, y):
        tgt_mask=self.transformer.generate_square_subsequent_mask(y.shape[1]).to('cuda')
        out = self.transformer(x, y, tgt_mask=tgt_mask)
        return out
    def inference(self, x, y):
        y = torch.zeros((y.shape[0], 1, y.shape[2])).to('cuda')
        for i in range(10):
          tgt_mask=self.transformer.generate_square_subsequent_mask(y.shape[1]).to('cuda')
          out=self.transformer(x, y, tgt_mask=tgt_mask)
          y = torch.cat((y, out[:, -1:, :]), dim=1)
        return y[:, 1:, :]
x = torch.rand((50, 10, 30)).to('cuda')
y = torch.rand((50, 10, 30)).to('cuda')

model = Net().to('cuda')
optimizer = optim.Adam(model.parameters())
critic = nn.MSELoss()

i = 0
while True:
    model.train()
    optimizer.zero_grad()
    out=model(x, torch.cat((torch.zeros((y.shape[0], 1, y.shape[2])).to('cuda'), y[:, 1:, :]), dim=1))

    loss=critic(out, y)
    loss.backward()
    optimizer.step()
    if i%100 ==0:
      plt.close('all')
      print(loss.item())
      fig, (ax0, ax1, ax2) = plt.subplots(3, 1)

      p0=ax0.pcolor(out[0].detach().to('cpu').numpy())
      fig.colorbar(p0, ax=ax0)
      p1=ax1.pcolor(y[0].detach().to('cpu').numpy())
      fig.colorbar(p1, ax=ax1)


      model.eval()
      with torch.no_grad():
        in_out=model.inference(x, y)
        p2=ax2.pcolor(in_out[0].detach().to('cpu').numpy())
        fig.colorbar(p2, ax=ax2)
      plt.pause(1)
    i+=1

image

이런 코드도 한번 만들어 봤었는데 … inference로 도출된 값이 그라디언트처럼 보이는지, 왜이런 문제가 생기는 지도 모르겠습니다. nn.multiheadattention를 공부해서 encoder decoder부분을 직접 제작해 봐야하는건지…
아직도 해결책을 모르것습니다.

취미로하는 코딩이라 시간이 별로 없어서 진전이 없네요 ㅜㅜ.

transformer tts 를 한번 공부해봐야 하는 걸까요?

이거 positional encoding 문제인지 뭔지 누가 좀 알려주실 수 있나요 ㅜㅜ.
transformer를 잘못 이해하고 있는건 아닌듯 한데 작동이 안되다니 ㅜㅜ

nn.transformer가 stack처럼 쌓는 방식이 안되더군요. github에서 다른 transformer 모델을 복사해서 고쳐서 해본 결과 잘 됩니다…

2개의 좋아요

안되던게 아니었어요. 잘 해보니깐. 단지 random batch가 너무 많아서 였어요… 이상하긴 했네요. batch를 10개 이하로 해서 확인해 보니 잘 되더군요.

3개의 좋아요