Ошибка времени выполнения: поддерживаются только пакеты пространственных целей (3D-тензоры), но есть цели размерности: 2

#python #machine-learning #deep-learning #pytorch

Вопрос:

Я занимаюсь обучением передаче набора данных DogsVsCats с помощью PyTorch

код работает правильно, когда я не использую обучение по передаче

является ли эта строка кода проблемой?

 self.training_data.append([np.array(img), np.eye(2)[self.LABELS[label]]])
 

разве мы не можем определить один такой горячий вектор?

 REBUILD_DATA = True
IMAGE_SIZE = 64
class DogsVSCats():
    IMAGE_SIZE = 64
    CATS = "PetImages/Cat"
    DOGS = "PetImages/Dog"
    TESTING = "PetImages/Testing"
    LABELS = {CATS: 0, DOGS: 1}
    
    training_data = []
    catcount = 0
    dogcount = 0
    
    def make_training_data(self):
        for label in self.LABELS:
            print (label)
            for f in tqdm(os.listdir(label)):
                if "jpg" in f:
                    try:
                        path = os.path.join(label, f)
                        img = cv2.imread(path, cv2.IMREAD_GRAYSCALE)
                        img = cv2.resize(img, (self.IMAGE_SIZE, self.IMAGE_SIZE))
                        self.training_data.append([np.array(img), np.eye(2)[self.LABELS[label]]])
                        #print(np.eye(2)[self.LABELS[label]])

                        if label == self.CATS:
                            self.catcount  = 1
                        #elif label == self.DOGS:
                        else:
                            self.dogcount  = 1

                    except Exception as e:
                        pass
        np.random.shuffle(self.training_data)
        np.save("training_data.npy", self.training_data)
        print("Cats:", self.catcount)
        print("Dogs:", self.dogcount)
if REBUILD_DATA:
    dogsvcats = DogsVSCats()
    dogsvcats.make_training_data()

training_data = np.load("training_data.npy",allow_pickle = True)
print(len(training_data))

X = torch.Tensor([i[0] for i in training_data]).view(-1,IMAGE_SIZE,IMAGE_SIZE)
X = X/255.0
y = torch.Tensor([i[1] for i in training_data]) 

VAL_PCT = 0.1
val_size = int(len(X)*VAL_PCT)
print(val_size)

train_X = X[:-val_size]
train_y = y[:-val_size]

test_X = X[-val_size:]
test_y = y[-val_size:]

print(len(train_X))
print(len(train_y))

print(len(test_X))
print(len(test_y))

model = torchvision.models.vgg16(pretrained = True)

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

num_classes = 2
learning_rate = 1e-3
batch_size = 8
num_epochs = 1

loss_function = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=learning_rate)

class Identity(nn.Module):
    def __init__(self):
        super(Identity, self).__init__()
        
    def forward(self, x):
        return x
            

for param in model.parameters():
    param.requires_grad = False
    
model.avgpool = Identity()
model.classifier = nn.Sequential(nn.Linear(512, 100), nn.ReLU(), nn.Linear(100, num_classes))
model.to(device)
net = Identity().to(device)

def fwd_pass (X, y, train = False):
    if train:
        net.zero_grad()
    outputs = net(X)
    matches = [torch.argmax(i) == torch.argmax(j) for i,j in zip(outputs, y)]
    acc = matches.count(True)/len(matches)
    loss = loss_function(outputs, y)
    
    if train:
        loss.backward()
        optimizer.step()
    
    return acc, loss

import time

MODEL_NAME = f"modle-{int(time.time())}"

def train(net):
    BATCH_SIZE = 64
    EPOCHS = 3
    
    with open("model.log","a") as f:
        for epoch in range(EPOCHS):
            for i in tqdm(range(0, len(train_X),BATCH_SIZE)):
                batch_X = train_X[i:i BATCH_SIZE].view(-1,1,IMAGE_SIZE,IMAGE_SIZE)
                batch_y = train_y[i:i BATCH_SIZE]

                batch_X, batch_y = batch_X.to(device), batch_y.to(device)

                acc, loss = fwd_pass(batch_X, batch_y, train = True)
                
                if i % 10 == 0:
                    val_acc, val_loss = test(size=100)

                    #print(f"Accuracy: {round(float(acc),2)} Loss: {round(float(loss),4)}")
                    #f.write(f"{MODEL_NAME},{int(time.time(),3)},{round(float(acc),2)},{round(float(loss),4)}{round(float(val_acc),2)},{round(float(val_loss),4)}n")
                    f.write(f"{MODEL_NAME},{round(time.time(),3)},{round(float(acc),2)},{round(float(loss), 4)},{round(float(val_acc),2)},{round(float(val_loss),4)}n")
train(net)

def test(size):
    X, y = test_X[:size], test_y[:size]
    X, y = test_X[:size], test_y[:size]
    val_acc, val_loss = fwd_pass(X.view(-1,1,IMAGE_SIZE,IMAGE_SIZE).to(device), y.to(device))
    return val_acc, val_loss

val_acc, val_loss = test(size=100)
print (val_acc, val_loss)


MODEL_NAME = f"modle-{int(time.time())}"


 

Ошибка, которую я получил, такова….

   0%|                                                                                          | 0/352 [00:00<?, ?it/s]
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-111-c243a447bb52> in <module>
     23                     #f.write(f"{MODEL_NAME},{int(time.time(),3)},{round(float(acc),2)},{round(float(loss),4)}{round(float(val_acc),2)},{round(float(val_loss),4)}n")
     24                     f.write(f"{MODEL_NAME},{round(time.time(),3)},{round(float(acc),2)},{round(float(loss), 4)},{round(float(val_acc),2)},{round(float(val_loss),4)}n")
---> 25 train(net)
     26 
     27 def test(size):

<ipython-input-111-c243a447bb52> in train(net)
     15                 batch_X, batch_y = batch_X.to(device), batch_y.to(device)
     16 
---> 17                 acc, loss = fwd_pass(batch_X, batch_y, train = True)
     18 
     19                 if i % 10 == 0:

<ipython-input-109-f74977a6e0a4> in fwd_pass(X, y, train)
      6     matches = [torch.argmax(i) == torch.argmax(j) for i,j in zip(outputs, y)]
      7     acc = matches.count(True)/len(matches)
----> 8     loss = loss_function(outputs, y)
      9 
     10     if train:

C:ProgramDataAnaconda3libsite-packagestorchnnmodulesmodule.py in _call_impl(self, *input, **kwargs)
    725             result = self._slow_forward(*input, **kwargs)
    726         else:
--> 727             result = self.forward(*input, **kwargs)
    728         for hook in itertools.chain(
    729                 _global_forward_hooks.values(),

C:ProgramDataAnaconda3libsite-packagestorchnnmodulesloss.py in forward(self, input, target)
    960     def forward(self, input: Tensor, target: Tensor) -> Tensor:
    961         return F.cross_entropy(input, target, weight=self.weight,
--> 962                                ignore_index=self.ignore_index, reduction=self.reduction)
    963 
    964 

C:ProgramDataAnaconda3libsite-packagestorchnnfunctional.py in cross_entropy(input, target, weight, size_average, ignore_index, reduce, reduction)
   2466     if size_average is not None or reduce is not None:
   2467         reduction = _Reduction.legacy_get_string(size_average, reduce)
-> 2468     return nll_loss(log_softmax(input, 1), target, weight, None, ignore_index, None, reduction)
   2469 
   2470 

C:ProgramDataAnaconda3libsite-packagestorchnnfunctional.py in nll_loss(input, target, weight, size_average, ignore_index, reduce, reduction)
   2264         ret = torch._C._nn.nll_loss(input, target, weight, _Reduction.get_enum(reduction), ignore_index)
   2265     elif dim == 4:
-> 2266         ret = torch._C._nn.nll_loss2d(input, target, weight, _Reduction.get_enum(reduction), ignore_index)
   2267     else:
   2268         # dim == 3 or dim > 4

RuntimeError: only batches of spatial targets supported (3D tensors) but got targets of dimension: 2
 

Комментарии:

1. Я получил решение, я преобразовывал изображение в оттенки серого и подавал модель с 3 каналами. Но я получаю постоянную точность проверки и потери. может кто-нибудь помочь мне с этим делом?