Ошибка времени выполнения: несоответствие размера, m1: [4 x 784], м2: [4 x 784] в /pytorch/aten/src/TH/generic/THTensorMath.cpp:136 - PullRequest
0 голосов
/ 31 марта 2020

Я выполнил следующий код

   import matplotlib.pyplot as plt
   import torch
   import torch.nn as nn
   import torch.optim as optim
   from torch.autograd import Variable
   from torch.utils import data as t_data
   import torchvision.datasets as datasets
   from torchvision import transforms
   data_transforms = transforms.Compose([transforms.ToTensor()])
  mnist_trainset = datasets.MNIST(root='./data', train=True,    
                           download=True, transform=data_transforms)
batch_size=4
dataloader_mnist_train = t_data.DataLoader(mnist_trainset, 
                                           batch_size=batch_size,
                                           shuffle=True
                                           )

def make_some_noise():
    return torch.rand(batch_size,100)


class generator(nn.Module):

    def __init__(self, inp, out):

        super(generator, self).__init__()

        self.net = nn.Sequential(
                                 nn.Linear(inp,784),
                                 nn.ReLU(inplace=True),
                                 nn.Linear(784,1000),
                                 nn.ReLU(inplace=True),
                                 nn.Linear(1000,800),
                                 nn.ReLU(inplace=True),
                                 nn.Linear(800,out)
                                    )

    def forward(self, x):
        x = self.net(x)
        return x

class discriminator(nn.Module):

    def __init__(self, inp, out):

        super(discriminator, self).__init__()

        self.net = nn.Sequential(
                                 nn.Linear(inp,784),
                                 nn.ReLU(inplace=True),
                                 nn.Linear(784,784),
                                 nn.ReLU(inplace=True),
                                 nn.Linear(784,200),
                                 nn.ReLU(inplace=True),
                                 nn.Linear(200,out),
                                 nn.Sigmoid()
                                    )

    def forward(self, x):
        x = self.net(x)
        return x

def plot_img(array,number=None):
    array = array.detach()
    array = array.reshape(28,28)

    plt.imshow(array,cmap='binary')
    plt.xticks([])
    plt.yticks([])
    if number:
        plt.xlabel(number,fontsize='x-large')
    plt.show()

d_steps = 100
g_steps = 100

gen=generator(4,4)
dis=discriminator(4,4)

criteriond1 = nn.BCELoss()
optimizerd1 = optim.SGD(dis.parameters(), lr=0.001, momentum=0.9)

criteriond2 = nn.BCELoss()
optimizerd2 = optim.SGD(gen.parameters(), lr=0.001, momentum=0.9)

printing_steps = 20

epochs = 5

for epoch in range(epochs):

    print (epoch)

    # training discriminator
    for d_step in range(d_steps):
        dis.zero_grad()

        # training discriminator on real data
        for inp_real,_ in dataloader_mnist_train:
            inp_real_x = inp_real
            break

        inp_real_x = inp_real_x.reshape(batch_size,784)
        dis_real_out = dis(inp_real_x)
        dis_real_loss = criteriond1(dis_real_out,
                              Variable(torch.ones(batch_size,1)))
        dis_real_loss.backward()

        # training discriminator on data produced by generator
        inp_fake_x_gen = make_some_noise()
        #output from generator is generated        
        dis_inp_fake_x = gen(inp_fake_x_gen).detach()
        dis_fake_out = dis(dis_inp_fake_x)
        dis_fake_loss = criteriond1(dis_fake_out,
                                Variable(torch.zeros(batch_size,1)))
        dis_fake_loss.backward()

        optimizerd1.step()



    # training generator
    for g_step in range(g_steps):
        gen.zero_grad()

        #generating data for input for generator
        gen_inp = make_some_noise()

        gen_out = gen(gen_inp)
        dis_out_gen_training = dis(gen_out)
        gen_loss = criteriond2(dis_out_gen_training,
                               Variable(torch.ones(batch_size,1)))
        gen_loss.backward()

        optimizerd2.step()

    if epoch%printing_steps==0:
        plot_img(gen_out[0])
        plot_img(gen_out[1])
        plot_img(gen_out[2])
        plot_img(gen_out[3])
        print("\n\n")

При запуске кода отображается следующая ошибка

 File "mygan.py", line 105, in <module>
    dis_real_out = dis(inp_real_x)
    RuntimeError: size mismatch, m1: [4 x 784], m2: [4 x 784] at /pytorch/aten/src/TH/generic/THTensorMath.cpp:136

Как мне решить эту проблему?

Я получил код от https://blog.usejournal.com/train-your-first-gan-model-from-scratch-using-pytorch-9b72987fd2c0

1 Ответ

1 голос
/ 31 марта 2020

Ошибка намекает на то, что тензор, введенный вами в дискриминатор, имеет неправильную форму. Теперь давайте попытаемся выяснить, какова форма тензора и какая ожидаемая форма.

Сам тензор имеет форму [batch_size x 784] из-за операции переопределения, описанной выше. Сеть дискриминатора, с другой стороны, ожидает тензор с последним измерением 4. Это связано с тем, что первый уровень в сети дискриминатора равен nn.Linear(inp, 784), где inp = 4.

Линейный слой nn.Linear(input_size, output_size) ожидает, что конечный размер входного тензора будет равен input_size, и генерирует выходные данные с окончательным измерением, спроецированным на output_size. В этом случае он ожидает входной тензор формы [batch_size x 4] и выводит тензор формы [batch_size x 784].


А теперь к реальной проблеме: у заданного вами генератора и дискриминатора неверный размер. Похоже, вы изменили размер измерения 300 с поста в блоге на 784, который, как я полагаю, является размером вашего изображения (28 x 28 для MNIST). Однако 300 - это не входной размер, а скорее «размер скрытого состояния» - модель использует 300-мерный вектор для кодирования входного изображения.

Что вы здесь нужно установить размер ввода 784, а размер вывода 1, потому что дискриминатор делает двоичное суждение о fake (0) или real (1). Для генератора размер входного сигнала должен быть равен «входному шуму», который вы генерируете случайным образом, в данном случае 100. Размер вывода также должен быть 784, поскольку его выводом является сгенерированное изображение, размер которого должен быть таким же, как и у реальных данных.

Итак, вам нужно только внести следующие изменения в свой код, и он должен работать плавно:

gen = generator(100, 784)
dis = discriminator(784, 1)
...