RuntimeError: stack expects a non-empty TensorList

def training_loop(gpu, training_dataloader, model, loss_fn, optimizer):
losses = []
correct = 0
batch_results = dict()
conf_mat = np.zeros((10,10))
for batch_n, batch in enumerate(training_dataloader): #batch[batch, pos, ptr, y]
batch_size = int(batch.batch.size()[0] / sample_points)
if dimensionality == 3:
# Input dim [:,3] for your geometry x,y,z
X = batch.pos.cuda(non_blocking=True).view(batch_size, sample_points, -1) + torch.normal(
torch.zeros(batch_size, sample_points, dimensionality), torch.full((batch_size, sample_points,
dimensionality), fill_value=0.1)).cuda(gpu)
else:
# Input dim [:,6] for your geometry x,y,z and normals nx,ny,nz
X = torch.cat((batch.pos.cuda(non_blocking=True), batch.normal.cuda(non_blocking=True)), 1).view(batch_size, sample_points, -1) + torch.normal(
torch.zeros(batch_size, sample_points, dimensionality), torch.full((batch_size, sample_points,
dimensionality), fill_value=0.1)).cuda(gpu)

    y = batch.y.cuda(non_blocking=True).flatten() #size (batch_size) --> torch.Size([8])
    
    # Compute predictions
    pred = model(None, X) #size (batch_size,classes) --> torch.Size([8, 10])
    
    if overall_classes_loss:
        # weighted CE Loss over all classes
        loss = loss_fn(pred, y)
    else:
        # weighted batchwise Loss
        sample_count = np.array([[x, batch.y.tolist().count(x)] for x in batch.y])[:,1]
        batch_weights = 1. / sample_count
        batch_weights = torch.from_numpy(batch_weights)
        batch_weights = batch_weights.double()
        loss = element_weighted_loss(pred, batch.y, batch_weights, gpu)
    
    correct += (pred.argmax(1) == y).type(torch.float).sum().item()
    print(f"Loss: {loss}")

    tensor_list_y =  [torch.ones_like(y) for _ in range(dist.get_world_size())]
    tensor_list_pred = [torch.ones_like(y) for _ in range(dist.get_world_size())]
    torch.distributed.all_gather(tensor_list_y, y, group=None, async_op=False)
    torch.distributed.all_gather(tensor_list_pred, pred.argmax(1), group=None, async_op=False)
    tensor_list_y = torch.cat(tensor_list_y)
    tensor_list_pred = torch.cat(tensor_list_pred)
    
    # Confusion Matrix
    conf_mat += confusion_matrix(tensor_list_y.cpu().detach().numpy(), tensor_list_pred.cpu().detach().numpy(), labels=np.arange(0,10))
    
    # Backpropagation
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    losses.append(loss.item())
    
    # Save batch predictions
    batch_results[batch_n] = {'true':tensor_list_y, 'pred':tensor_list_pred}
    
    if verbosity == True:
        print(f"\n\nTRAIN on GPU:{gpu}: True Label {y} - Prediction {pred.argmax(1)} - Loss {loss}")
        truevalue = '\t\t'.join(classes[items] for items in y.tolist())
        predvalues = '\t\t'.join(classes[items] for items in pred.argmax(1).tolist())
        print(f"INFO on GPU:{gpu}: TRAIN - True Value\t {truevalue}")
        print(f"INFO on GPU:{gpu}: TRAIN - Predictions\t {predvalues}")
    
    if batch_n % 25 == 0:
        torch.distributed.reduce(loss, 0)
        """if gpu == 0:
            # print predictions and true values
            #truevalue = '\t\t'.join(classes[items] for items in y.tolist())
            #predvalues = '\t\t'.join(classes[items] for items in pred.argmax(1).tolist())
            #print(f"\n\nINFO on GPU{gpu}: TRAIN - True Value\t {truevalue}")
            #print(f"INFO on GPU{gpu}: TRAIN - Predictions\t {predvalues}")
            #print("INFO: TRAIN - Correctness\t", pred.argmax(1) == y)
            #print(f"INFO: TRAIN - Single Batch Test Accuracy {correct * 100 / batch_size}\n\n")
            loss, current = loss.item(), batch_n * len(X)
            #print(f"loss: {loss:>7f}")"""
    #print(f"conf_mat: {conf_mat}")
    #print(f"batch_results: {batch_results}")

return torch.tensor(losses, device=f"cuda:{gpu}"), torch.tensor(correct, device=f"cuda:{gpu}"), batch_results, conf_mat

Test loop

def test_loop(gpu, test_dataloader, model, loss_fn):
test_losses = []
correct = 0
batch_results = dict()
conf_mat = np.zeros((10,10))
with torch.no_grad():
for batch_n, batch in enumerate(test_dataloader):
batch_size = int(batch.batch.size()[0] / sample_points)

        if dimensionality == 3:
            # Input dim [:,3] for your geometry x,y,z
            X = batch.pos.cuda(non_blocking=True).view(batch_size, sample_points, -1)
        else:
            # Input dim [:,6] for your geometry x,y,z and normals nx,ny,nz
            X = torch.cat((batch.pos.cuda(non_blocking=True), batch.normal.cuda(non_blocking=True)), 1).view(batch_size, sample_points, -1)
            
        y = batch.y.cuda(non_blocking=True).flatten()
        pred = model(None, X) #size (batch,classes) per batch_n
        
        if overall_classes_loss:
            # weighted CE Loss over all classes
            loss = loss_fn(pred, y)
        else:
            # weighted batchwise Loss
            sample_count = np.array([[x, batch.y.tolist().count(x)] for x in batch.y])[:,1]
            batch_weights = 1. / sample_count
            batch_weights = torch.from_numpy(batch_weights)
            batch_weights = batch_weights.double()
            loss = element_weighted_loss(pred, batch.y, batch_weights, gpu)
        
        test_losses.append(loss.item())
        correct += (pred.argmax(1) == y).type(torch.float).sum().item()
        print(f"Loss: {loss}")
    
        tensor_list_y =  [torch.ones_like(y) for _ in range(dist.get_world_size())]
        tensor_list_pred = [torch.ones_like(y) for _ in range(dist.get_world_size())]
        torch.distributed.all_gather(tensor_list_y, y, group=None, async_op=False)
        torch.distributed.all_gather(tensor_list_pred, pred.argmax(1), group=None, async_op=False)
        tensor_list_y = torch.cat(tensor_list_y)
        tensor_list_pred = torch.cat(tensor_list_pred)
        
        # Confusion Matrix
        conf_mat += confusion_matrix(tensor_list_y.cpu().detach().numpy(), tensor_list_pred.cpu().detach().numpy(), labels=np.arange(0,10))
        
        # Save batch predictions
        batch_results[batch_n] = {'true':tensor_list_y, 'pred':tensor_list_pred}
        
        if verbosity == True:
            print(f"\n\nTEST on GPU:{gpu}: True Label {y} - Prediction {pred.argmax(1)} - Loss {loss}")
            truevalue = '\t\t'.join(classes[items] for items in y.tolist())
            predvalues = '\t\t'.join(classes[items] for items in pred.argmax(1).tolist())
            print(f"INFO on GPU:{gpu}: TEST - True Value\t {truevalue}")
            print(f"INFO on GPU:{gpu}: TEST - Predictions\t {predvalues}")

test_loss = statistics.mean(test_losses)
return torch.tensor(correct, device=f"cuda:{gpu}"), torch.tensor(test_loss, device=f"cuda:{gpu}"), batch_results, conf_mat

def train_optimisation(gpu, gpus, training_dataloader, test_dataloader, model, loss_fn, optimizer, scheduler, dir_path, initial_epoch):
epoch_losses = []
training_accuracies = []
test_losses = []
test_accuracies = []
learning_rates = []
counter = 0 #early stopping counter
batchwise_results = dict()

# Learning Rate Scheduler
scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', patience=20)

for i in range(initial_epoch, initial_epoch + epochs):
    if gpu == 0:
        if initial_epoch > 0:
            print(f"\n\nEpoch {i}\n-------------------------------")
        else:
            print(f"\n\nEpoch {i + 1}\n-------------------------------")

    # TRAIN
    losses, training_accuracy, train_batch_result, train_conf_mat = training_loop(gpu, training_dataloader, model, loss_fn, optimizer)
    average_loss = torch.mean(losses)
    torch.distributed.reduce(average_loss, 0, torch.distributed.ReduceOp.SUM)
    torch.distributed.reduce(training_accuracy, 0, torch.distributed.ReduceOp.SUM)
    
    # TEST
    test_accuracy, test_loss, test_batch_result, test_conf_mat = test_loop(gpu, test_dataloader, model, loss_fn)
    torch.distributed.reduce(test_accuracy, 0, torch.distributed.ReduceOp.SUM)
    torch.distributed.reduce(test_loss, 0, torch.distributed.ReduceOp.SUM)
            
    # save results
    batchwise_results[i] = {'train':train_batch_result, 'test':test_batch_result}
    if gpu == 0:  # the following operations are performed only by the process running in the first gpu
        average_loss = average_loss / torch.tensor(gpus, dtype=torch.float)  # average loss among all gpus
        test_accuracy = test_accuracy / torch.tensor(len(test_dataloader.dataset),
                                                     dtype=torch.float) * torch.tensor(100.0)
        training_accuracy = training_accuracy / torch.tensor(len(training_dataloader.dataset),
                                                             dtype=torch.float) * torch.tensor(100.0)
        test_loss = test_loss / torch.tensor(gpus, dtype=torch.float)
        epoch_losses.append(average_loss.item())
        training_accuracies.append(training_accuracy.item())
        test_losses.append(test_loss.item())
        test_accuracies.append(test_accuracy.item())
        learning_rates.append((optimizer.param_groups[0])["lr"])
        print(f"\nBatch size: {batch_size * int(gpus)}")
        print(f"average Training Loss: {average_loss.item():.6f}")
        print(f"average Test Loss: {test_loss.item():.6f}")
        print(f"\naverage Training Acc: {training_accuracy.item():.6f}")
        print(f"average Test Acc: {test_accuracy.item():.6f}")
        printLearningRate(optimizer)
        scheduler.step(test_loss)
        
        """# stepwise learning rate decay
        if average_loss.item() <= 0.35:
            for param_group in optimizer.param_groups:
                print("Learning rate changed to 0.007")
                param_group['lr'] = 0.007
        if average_loss.item() <= 0.30:
            for param_group in optimizer.param_groups:
                print("Learning rate changed to 0.004")
                param_group['lr'] = 0.004"""
        
        # saving model checkpoint
        save_checkpoint(model, optimizer, scheduler, i, epoch_losses, training_accuracies, test_losses, test_accuracies, learning_rates,
                        os.path.join(dir_path, f"epoch{i}.pth"), {key: value for key, value in batchwise_results[i].items() if key == 'train'}, {key: value for key, value in batchwise_results[i].items() if key == 'test'}, train_conf_mat, test_conf_mat)
        #TODO: implement ONNX Export
        # early stopping scheduler
        if early_stopping(test_losses) == True:
            counter += 1
            print(f"Early Stopping counter: {counter} of {patience}")
        else:
            counter += 0                        
        if counter < patience:
            pass
        else:
            print("\n\nEarly Stopping activated")
            print(f"Training stopped at Epoch{i + 1}")
            dist.destroy_process_group()
            exit()

class DistributedWeightedSampler(Sampler):
def init(self, dataset, data_source: Optional[Sized], num_replicas: Optional[int] = None,
rank: Optional[int] = None, shuffle: bool = True, seed: int = 0, replacement: bool = True):
super().init(data_source)
if num_replicas is None:
if not dist.is_available():
raise RuntimeError(“Requires distributed package to be available”)
num_replicas = dist.get_world_size()
if rank is None:
if not dist.is_available():
raise RuntimeError(“Requires distributed package to be available”)
rank = dist.get_rank()
if rank >= num_replicas or rank < 0:
raise ValueError(“Invalid rank {}, rank should be in the interval [0, {}]”.format(rank, num_replicas - 1))
self.dataset = dataset
self.num_replicas = num_replicas
self.rank = rank
self.epoch = 0
self.num_samples = int(math.ceil(len(self.dataset) * 1.0 / self.num_replicas))
self.total_size = self.num_samples * self.num_replicas
self.shuffle = shuffle
self.seed = seed
self.replacement = replacement #sample can be drown again in that row if True

def calculate_weights(self, targets):
    class_sample_count = np.array([len(np.where(self.dataset.data.y == t)[0]) for t in np.unique(self.dataset.data.y)])
    weight = 1. / class_sample_count
    samples_weight = np.array([weight[t] for t in self.dataset.data.y])
    samples_weight = torch.from_numpy(samples_weight)
    samples_weigth = samples_weight.double()
    return samples_weigth

def __iter__(self):
    # deterministically shuffle based on epoch
    if self.shuffle:
        g = torch.Generator()
        g.manual_seed(self.seed + self.epoch)
        indices = torch.randperm(len(self.dataset), generator=g).tolist()
    else:
        indices = list(range(len(self.dataset)))

    # add extra samples to make it evenly divisible
    indices += indices[:(self.total_size - len(indices))]
    assert len(indices) == self.total_size

    # subsample
    indices = indices[self.rank:self.total_size:self.num_replicas]
    assert len(indices) == self.num_samples

    # get targets (you can alternatively pass them in __init__, if this op is expensive)
    # data.data.y == labels
    targets = self.dataset.data.y
    targets = targets[self.rank:self.total_size:self.num_replicas]
    #assert len(targets) == self.num_samples
    weights = self.calculate_weights(targets)
    weighted_indices = torch.multinomial(weights, self.num_samples, self.replacement).tolist()

    return iter(weighted_indices)

def __len__(self):
    return self.num_samples

def set_epoch(self, epoch):
    self.epoch = epoch

def train(gpu, gpus, world_size):
torch.manual_seed(0)
torch.cuda.set_device(gpu)
try:
#dist.init_process_group(backend=‘nccl’, world_size=world_size, rank=gpu) #for distributed GPU training
dist.init_process_group(backend=‘gloo’, world_size=world_size, rank=gpu) #as a fallback option
except RuntimeError:
print(“\n\nINFO:RuntimeError is raised >> Used gloo backend instead of nccl!\n”)
dist.init_process_group(backend=‘gloo’, world_size=world_size, rank=gpu) #as a fallback option

dir_path = None
if gpu == 0:
    dir_path = "stackgraphConvPool3DPnet"
    createdir(dir_path)
    training_number = next_training_number(dir_path)
    dir_path = os.path.join(dir_path, f"train{training_number}")
    createdir(dir_path)
    #save hyper-parameters in txt protocol file
    save_hyperparameters(dir_path, 'hyperparameters.txt')
    print("\nINFO: Protocol File saved successfully . . .")
    
    #copy crucial py-files in current train folder
    #shutil.copy2(os.path.basename('__file__'), dir_path)
    #shutil.copy2('stackGraphConvPool3DPnet.py', dir_path)
    #shutil.copy2('shrinkingunit.py', dir_path)
    #shutil.copy2('utilities.py', dir_path)
    #print("\nINFO: Script Files copied successfully . . .")

model = Classifier(shrinkingLayers, mlpClassifier)

torch.cuda.set_device(gpu)
model.cuda(gpu)

#setting up optimizer
if optimizer_str == "SGD":
    optimizer = torch.optim.SGD(model.parameters(), learning_rate, momentum=momentum, weight_decay=weight_decay)
elif optimizer_str == "RMSprop":
    optimizer = torch.optim.RMSprop(model.parameters(), learning_rate, weight_decay=weight_decay)
else:
    optimizer = torch.optim.Adam(model.parameters(), learning_rate, weight_decay=weight_decay)

# single-program multiple-data training paradigm (Distributed Data-Parallel Training)
model = DDP(model, device_ids=[gpu])

if dimensionality == 3:
    training_data = ModelNet("ModelNet10_train_data", transform=lambda x: NormalizeScale()(SamplePoints(num=sample_points)(x)))
else:
    training_data = ModelNet("ModelNet10_train_data", transform=lambda x: NormalizeScale()(NormalizeRotation()(SamplePoints(num=sample_points, remove_faces=True, include_normals=True)(x))))

training_sampler = DistributedWeightedSampler(training_data, data_source=None, num_replicas=world_size) #weight unbalanced classes by 1/cls_count
training_dataloader = DataLoader(dataset=training_data, batch_size=batch_size, shuffle=data_shuffle, num_workers=0,
                                      pin_memory=True, sampler=training_sampler)

if dimensionality == 3:
    test_data = ModelNet("ModelNet10_test_data", train=False, transform=lambda x: NormalizeScale()(SamplePoints(num=sample_points)(x)))
else:
    test_data = ModelNet("ModelNet10_test_data", train=False, transform=lambda x: NormalizeScale()(NormalizeRotation()(SamplePoints(num=sample_points, remove_faces=True, include_normals=True)(x))))

test_sampler = DistributedWeightedSampler(test_data,data_source=None, num_replicas=world_size) #weight unbalanced classes by 1/cls_count
test_dataloader = DataLoader(dataset=test_data, batch_size=batch_size, shuffle=data_shuffle, num_workers=0,
                                  pin_memory=True, sampler=test_sampler)

"""# save sampled data for later result visualisation
try:
    #export_path = os.path.join("stackgraphConvPool3DPnet", "train" + str(next_training_number("stackgraphConvPool3DPnet")-1))
    #export_sampled_data(training_dataloader, os.path.join(export_path, "train_sampledPoints.pth"))
    #export_sampled_data(test_dataloader, os.path.join(export_path, "test_sampledPoints.pth"))
    print("\nINFO: Sampled 3D data successfully saved . . .")
except Exception as e:
    print(f"\nERROR: Sampled 3D data could not saved successfully . . . - this process does not executed - caused by {e}")"""

# weighted CE Loss over all Classes C
class_sample_count = np.array([len(np.where(training_data.data.y == t)[0]) for t in np.unique(training_data.data.y)])
weight = 1. / class_sample_count
weight = torch.from_numpy(weight)
weight = weight.float()
loss_fn = nn.CrossEntropyLoss(weight=weight).cuda(gpu)

# continue training from certain checkpoint
continue_from_scratch = True if args.resume is None else False
if continue_from_scratch: 
    if gpu == 0:
        print("\nINFO: Train from scratch has started . . .")
    train_optimisation(gpu, gpus, training_dataloader, test_dataloader, model, loss_fn, optimizer, None, dir_path, 0)
else:
    checkpoint_path = "stackgraphConvPool3DPnet/" + args.resume
    if gpu == 0:
        print(f"\nINFO: Train has started from certain checkpoint {checkpoint_path.split('/')[2].split('.')[0]} in {checkpoint_path.split('/')[1]} . . .")
    model.load_state_dict(torch.load(checkpoint_path)['model_state_dict'], strict=False)
    optimizer.load_state_dict(torch.load(checkpoint_path)['optimizer_state_dict'])
    final_epoch = (torch.load("stackgraphConvPool3DPnet/" + args.resume)['epoch'])+1
    train_optimisation(gpu, gpus, training_dataloader, test_dataloader, model, loss_fn, optimizer, None, dir_path, final_epoch)

INFO: Train from scratch has started . . .

Epoch 1

Exception in thread Exception in thread Thread-8:
Traceback (most recent call last):
File “C:\ProgramData\Anaconda3\lib\threading.py”, line 973, in _bootstrap_inner
Thread-7:
Traceback (most recent call last):
File “C:\ProgramData\Anaconda3\lib\threading.py”, line 973, in _bootstrap_inner
self.run()
File “C:\ProgramData\Anaconda3\lib\threading.py”, line 910, in run
self.run()
File “C:\ProgramData\Anaconda3\lib\threading.py”, line 910, in run
self._target(*self._args, **self._kwargs)
File ~\Desktop\Forum\unit.py", line 615, in kmeansAppender
self._target(*self.args, **self.kwargs)
File ~\Desktop\Forum\unit.py", line 615, in kmeansAppender
x, y, z = module(input)
File “C:\ProgramData\Anaconda3\lib\site-packages\torch\nn\modules\module.py”, line 1130, in call_impl
x, y, z = module(input)
File “C:\ProgramData\Anaconda3\lib\site-packages\torch\nn\modules\module.py”, line 1130, in call_impl
return forward_call(input, **kwargs)
File ~\Desktop\Forum\unit.py", line 148, in forward
labels = np.apply_along_axis(lambda x: x + (i
self.k), axis=0, arr=kmeans.labels
)
AttributeError: ‘KMeans’ object has no attribute 'labels

return forward_call(input, **kwargs)
File ~\Desktop\Forum\unit.py", line 148, in forward
labels = np.apply_along_axis(lambda x: x + (i
self.k), axis=0, arr=kmeans.labels
)
AttributeError: ‘KMeans’ object has no attribute 'labels

RuntimeError Traceback (most recent call last)
Input In [1], in <cell line: 720>()
734 #change state
735 if args.train_state == True:
→ 736 train(args.local_rank, gpus, world_size)
737 else:
738 infer(args.local_rank, gpus, world_size, args.checkpoint, args.data)

Input In [1], in train(gpu, gpus, world_size)
672 if gpu == 0:
673 print(“\nINFO: Train from scratch has started . . .”)
→ 674 train_optimisation(gpu, gpus, training_dataloader, test_dataloader, model, loss_fn, optimizer, None, dir_path, 0)
675 else:
676 checkpoint_path = “stackgraphConvPool3DPnet/” + args.resume

Input In [1], in train_optimisation(gpu, gpus, training_dataloader, test_dataloader, model, loss_fn, optimizer, scheduler, dir_path, initial_epoch)
454 print(f"\n\nEpoch {i + 1}\n-------------------------------")
456 # TRAIN
→ 457 losses, training_accuracy, train_batch_result, train_conf_mat = training_loop(gpu, training_dataloader, model, loss_fn, optimizer)
458 average_loss = torch.mean(losses)
459 torch.distributed.reduce(average_loss, 0, torch.distributed.ReduceOp.SUM)

Input In [1], in training_loop(gpu, training_dataloader, model, loss_fn, optimizer)
249 y = batch.y.cuda(non_blocking=True).flatten() #size (batch_size) → torch.Size([8])
251 # Compute predictions
→ 252 pred = model(None, X) #size (batch_size,classes) → torch.Size([8, 10])
254 if overall_classes_loss:
255 # weighted CE Loss over all classes
256 loss = loss_fn(pred, y)

File C:\ProgramData\Anaconda3\lib\site-packages\torch\nn\modules\module.py:1130, in Module._call_impl(self, *input, **kwargs)
1126 # If we don’t have any hooks, we want to skip the rest of the logic in
1127 # this function, and just call forward.
1128 if not (self._backward_hooks or self._forward_hooks or self._forward_pre_hooks or _global_backward_hooks
1129 or _global_forward_hooks or _global_forward_pre_hooks):
→ 1130 return forward_call(*input, **kwargs)
1131 # Do not call functions when jit is used
1132 full_backward_hooks, non_full_backward_hooks = [], []

File C:\ProgramData\Anaconda3\lib\site-packages\torch\nn\parallel\distributed.py:1008, in DistributedDataParallel.forward(self, *inputs, **kwargs)
1004 if self._join_config.enable:
1005 # Notify joined ranks whether they should sync in backwards pass or not.
1006 self._check_global_requires_backward_grad_sync(is_joined_rank=False)
→ 1008 output = self._run_ddp_forward(*inputs, **kwargs)
1010 # sync params according to location (before/after forward) user
1011 # specified as part of hook, if hook was specified.
1012 if self._check_sync_bufs_post_fwd():

File C:\ProgramData\Anaconda3\lib\site-packages\torch\nn\parallel\distributed.py:969, in DistributedDataParallel._run_ddp_forward(self, *inputs, **kwargs)
962 if self.device_ids:
963 inputs, kwargs = _to_kwargs(
964 inputs,
965 kwargs,
966 self.device_ids[0],
967 self.use_side_stream_for_tensor_copies
968 )
→ 969 return module_to_run(*inputs[0], **kwargs[0])
970 else:
971 return module_to_run(*inputs, **kwargs)

File C:\ProgramData\Anaconda3\lib\site-packages\torch\nn\modules\module.py:1130, in Module._call_impl(self, *input, **kwargs)
1126 # If we don’t have any hooks, we want to skip the rest of the logic in
1127 # this function, and just call forward.
1128 if not (self._backward_hooks or self._forward_hooks or self._forward_pre_hooks or _global_backward_hooks
1129 or _global_forward_hooks or _global_forward_pre_hooks):
→ 1130 return forward_call(*input, **kwargs)
1131 # Do not call functions when jit is used
1132 full_backward_hooks, non_full_backward_hooks = [], []

File ~\Desktop\Forum\unit.py:657, in Classifier.forward(self, x, pos)
655 feature_matrix_batch = pos.unsqueeze(0)
656 # feature_matrix_batch size = (1,N,I,D) where N=batch number, I=members, D=member dimensionality
→ 657 output = self.neuralNet(feature_matrix_batch)
658 # output size = (S,N,D) where S= stack size, N=batch number, D’=member dimensionality
659 output = torch.mean(output, dim=0)

File C:\ProgramData\Anaconda3\lib\site-packages\torch\nn\modules\module.py:1130, in Module._call_impl(self, *input, **kwargs)
1126 # If we don’t have any hooks, we want to skip the rest of the logic in
1127 # this function, and just call forward.
1128 if not (self._backward_hooks or self._forward_hooks or self._forward_pre_hooks or _global_backward_hooks
1129 or _global_forward_hooks or _global_forward_pre_hooks):
→ 1130 return forward_call(*input, **kwargs)
1131 # Do not call functions when jit is used
1132 full_backward_hooks, non_full_backward_hooks = [], []

File C:\ProgramData\Anaconda3\lib\site-packages\torch\nn\modules\container.py:139, in Sequential.forward(self, input)
137 def forward(self, input):
138 for module in self:
→ 139 input = module(input)
140 return input

File C:\ProgramData\Anaconda3\lib\site-packages\torch\nn\modules\module.py:1130, in Module._call_impl(self, *input, **kwargs)
1126 # If we don’t have any hooks, we want to skip the rest of the logic in
1127 # this function, and just call forward.
1128 if not (self._backward_hooks or self._forward_hooks or self._forward_pre_hooks or _global_backward_hooks
1129 or _global_forward_hooks or _global_forward_pre_hooks):
→ 1130 return forward_call(*input, **kwargs)
1131 # Do not call functions when jit is used
1132 full_backward_hooks, non_full_backward_hooks = [], []

File ~\Desktop\Forum\unit.py:448, in ShrinkingUnitStack.forward(self, feature_matrix_batch)
446 feature_matrix_batch = self.selfCorrStack(feature_matrix_batch)
447 # feature_matrix_batch size = (S’,N,I,D) where S’=stack_size, N=batch number, I=members, D=member dimensionality
→ 448 feature_matrix_batch_, conv_feature_matrix_batch, cluster_index = self.kmeansConvStack(feature_matrix_batch)
449 feature_matrix_batch = self.localAdaptFeaAggreStack(feature_matrix_batch, conv_feature_matrix_batch)
450 output = self.graphMaxPoolStack(feature_matrix_batch, cluster_index)

File C:\ProgramData\Anaconda3\lib\site-packages\torch\nn\modules\module.py:1130, in Module._call_impl(self, *input, **kwargs)
1126 # If we don’t have any hooks, we want to skip the rest of the logic in
1127 # this function, and just call forward.
1128 if not (self._backward_hooks or self._forward_hooks or self._forward_pre_hooks or _global_backward_hooks
1129 or _global_forward_hooks or _global_forward_pre_hooks):
→ 1130 return forward_call(*input, **kwargs)
1131 # Do not call functions when jit is used
1132 full_backward_hooks, non_full_backward_hooks = [], []

File ~\Desktop\Forum\unit.py:519, in KMeansConvStack.forward(self, feature_matrix_batch)
517 def forward(self, feature_matrix_batch: torch.Tensor):
518 # feature_matrix_batch size = (S,N,I,D) where S=stack size, N=batch number, I=members, D=member dimensionality
→ 519 feature_matrix_batch, conv_feature_matrix_batch, cluster_index = kmeansConvThreader(self.kmeansConvStack,
520 feature_matrix_batch)
521 # feature_matrix_batch size = (S,N,I,D) where where S=stack_size, N=batch number, I=members, D=member dimensionality
522 # conv_feature_matrix_batch size = (S,N,I,D) where where S=stack_size, N=batch number, I=members, D=member dimensionality
523 # cluster_index size = (S,M) where S=stack_size, M=N*I
524 return feature_matrix_batch, conv_feature_matrix_batch, cluster_index

File ~\Desktop\Forum\unit.py:611, in kmeansConvThreader(modules, input_tensor)
609 list2_append = list(map(lambda x: x[1], list2_append))
610 list3_append = list(map(lambda x: x[1], list3_append))
→ 611 return torch.stack(list1_append), torch.stack(list2_append), torch.stack(list3_append)

RuntimeError: stack expects a non-empty TensorList

Your code is quite unreadable since you haven’t formatted it properly. However, it seems the first error is raised in:

AttributeError: ‘KMeans’ object has no attribute 'labels’

so try to fix it first.

Thanks for your help