PyTorch, почему функция forward запускается несколько раз, и я могу изменить форму ввода? - PullRequest
0 голосов
/ 23 февраля 2019
import torch 
import torch.nn as nn
import torchvision.datasets as dsets
from skimage import transform
import torchvision.transforms as transforms
from torch.autograd import Variable
import pandas as pd;
import numpy as np;
from torch.utils.data import Dataset, DataLoader
import statistics

import random
import math

class FashionMNISTDataset(Dataset):
  '''Fashion MNIST Dataset'''
  def __init__(self, csv_file, transform=None):
    """
    Args:
        csv_file (string): Path to the csv file
        transform (callable): Optional transform to apply to sample
    """

    data = pd.read_csv(csv_file)
    self.X = np.array(data.iloc[:, 1:]).reshape(-1, 1, 28, 28)
    self.Y = np.array(data.iloc[:, 0])

    del data
    self.transform = transform

  def __len__(self):
    return len(self.X)

  def __getitem__(self, idx):
    item = self.X[idx]
    label = self.Y[idx]

    if self.transform:
        item = self.transform(item)

    return (item, label)

class CNN(nn.Module):
  def __init__(self):
    super(CNN, self).__init__()
    self.layer1 = nn.Sequential(
      nn.Linear(616,300),
      nn.ReLU())
    self.layer2 = nn.Sequential(
      nn.Linear(300,100),
      nn.ReLU())
    self.fc = nn.Linear(100, 10)

  def forward(self, x):
    print("x shape",x.shape)
    out = self.layer1(x)
    out = self.layer2(out)
    out = self.fc(out)
    return out

def run():

  device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
  num_epochs = 15
  batch_size = 100
  learning_rate = 0.0001

  train_dataset = FashionMNISTDataset(csv_file='fashion-mnist_train.csv')
  test_dataset = FashionMNISTDataset(csv_file='fashion-mnist_test.csv')

  train_loader = torch.utils.data.DataLoader(dataset=train_dataset,batch_size=batch_size,shuffle=True)
  test_loader = torch.utils.data.DataLoader(dataset=test_dataset,batch_size=batch_size,shuffle=True)

  #instance of the Conv Net
  cnn = CNN()
  cnn.to(device)

  #loss function and optimizer
  criterion = nn.CrossEntropyLoss()
  optimizer = torch.optim.Adam(cnn.parameters(), lr=learning_rate)


  losses = []
  for epoch in range(num_epochs):
    l = 0
    for i, (images, labels) in enumerate(train_loader):

      images = Variable(images.float())
      labels = Variable(labels)
      #print(images[0])
      images = images.to(device)
      labels = labels.to(device)
      print("img shape=",images.shape, "label shape=",labels.shape)
      images = images.resize_((100,616))

      print("img shape=",images.shape, "label shape=",labels.shape)
      # Forward + Backward + Optimize
      optimizer.zero_grad()
      outputs = cnn(images)

      loss = criterion(outputs, labels)
      #print(loss)
      loss.backward()
      optimizer.step()
      #print(loss.item())
      losses.append(loss.item())
      l = loss.item()

      cnn.eval()
      with torch.no_grad():
        val_loss = []
        for images, labels in test_loader:
          images = Variable(images.float()).to(device)
          labels = labels.to(device)
          outputs = cnn.forward(images)
          batch_loss = criterion(outputs, labels)
          val_loss.append(batch_loss.item())
        avgloss = statistics.mean(val_loss)
        if avgloss < min(losses):
          torch.save(cnn.state_dict(), 'model')
        cnn.train()
      if (i+1) % 100 == 0:
        print ('Epoch : %d/%d, Iter : %d/%d,  Loss: %.4f' 
              %(epoch+1, num_epochs, i+1, len(train_dataset)//batch_size, loss.item()))
    print(l)


  final_model = CNN()
  final_model.load_state_dict(torch.load('model'))
  final_model.eval()
  correct = 0
  total = 0
  for images, labels in test_loader:
      images = Variable(images.float()).to(device)
      outputs = final_model(images).to(device)
      labels.to(device)
      _, predicted = torch.max(outputs.data, 1)
      total += labels.size(0)
      correct += (predicted == labels).sum()
  print('Test Accuracy of the model on the 10000 test images: %.4f %%' % (100 * correct / total))



if __name__ == '__main__':
  run()

Я приложил весь код для целей тестирования.Но вот ошибка, которую я получаю

img shape = torch.Size ([100, 1, 28, 28]) форма этикетки = torch.Size ([100]) img shape = torch.Size([100, 616]) метка shape = torch.Size ([100]) x факел shape.Size ([100, 616]) x shape torch.Size ([100, 1, 28, 28]) Traceback (самая последняяпоследний вызов): файл «test.py», строка 145, в run () Файл «test.py», строка 115, в run output = cnn.forward (images) Файл «test.py», строка 56, в forwardout = self.layer1 (x) Файл "/usr/share/anaconda3/envs/DL/lib/python3.6/site-packages/torch/nn/modules/module.py", строка 489, в call result = self.forward (* input, ** kwargs) Файл "/usr/share/anaconda3/envs/DL/lib/python3.6/site-packages/torch/nn/modules/container.py",строка 92, в прямом вводе = файл модуля (ввода) "/usr/share/anaconda3/envs/DL/lib/python3.6/site-packages/torch/nn/modules/module.py", строка 489, в call result = self.forward (* input, ** kwargs) Файл "/usr/share/anaconda3/envs/DL/lib/python3.6/site-packages/torch/nn/modules/linear.py ", линия67, в обратном порядке F.linear (входной файл, self.weight, self.bias) Файл "/usr/share/anaconda3/envs/DL/lib/python3.6/site-packages/torch/nn/functional.py", строка 1354, в линейном выводе = input.matmul (weight.t ()) RuntimeError: несоответствие размера, m1: [2800 x 28], м2: [616 x 300] в / opt / conda / conda-bld / pytorch_1549630534704 /work / aten / src / THC / generic / THCTensorMathBlas.cu: 266

Проблема в том, что я хочу, чтобы все 616 пикселей подавались в качестве входных данных в нейронную сеть, но я не знаю, как это сделать,Я попытался изменить входные данные, чтобы решить проблему, но он дважды запускал model.forward, один раз с правильной формой, а затем с неправильной.

1 Ответ

0 голосов
/ 24 февраля 2019

Вы звоните forward дважды в run:

  1. Один раз для данных обучения
  2. Один раз для данных проверки

Однаковы не , по-видимому, применили следующее преобразование к вашим данным проверки:

images = images.resize_((100,616))

Возможно, рассмотрите возможность изменения размера в функции forward.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...