I am working on MNIST dataset, using a multi-input network. I have split my dataset in 2 parts (one for the first net and the second for the second net) and each part is divided in train, val and test. When I do the training on train and test, there are no problems, instead when I do the training on validation, I have the error of title
IndexError: list idex out of range
I have no idea why only on val set.
This is the code:
# Define loaders
train_loader_a = DataLoader(train_set_a, batch_size=128, num_workers=0, shuffle=True, drop_last=True)
val_loader_a = DataLoader(val_set_a, batch_size=128, num_workers=0, shuffle=False, drop_last=False)
test_loader_a = DataLoader(test_set_a, batch_size=128, num_workers=0, shuffle=False, drop_last=False)
train_loader_b = DataLoader(train_set_b, batch_size=128, num_workers=0, shuffle=True, drop_last=True)
val_loader_b = DataLoader(val_set_b, batch_size=128, num_workers=0, shuffle=False, drop_last=False)
test_loader_b = DataLoader(test_set_b, batch_size=128, num_workers=0, shuffle=False, drop_last=False)
# Define dictionary of loaders
loaders_a = {"train": train_loader_a,
"val": val_loader_a,
"test": test_loader_a}
loaders_b = {"train": train_loader_b,
"val": val_loader_b,
"test": test_loader_b}
This is training function on train set:
def train(net, loaders, optimizer, criterion, epochs=20, dev=None, save_param=False, model_name="valerio"):
loaders_a, loaders_b = loaders
# try:
net = net.to(dev)
#print(net)
#summary(net,[(net.in_channels,net.in_width,net.in_height)]*2)
criterion.to(dev)
# Initialize history
history_loss = {"train": [], "val": [], "test": []}
history_accuracy_combo = {"train": [], "val": [], "test": []}
history_accuracy_a = {"train": [], "val": [], "test": []}
history_accuracy_b = {"train": [], "val": [], "test": []}
# Store the best val accuracy
best_val_accuracy = 0
# Process each epoch
for epoch in range(epochs):
# Initialize epoch variables
sum_loss = {"train": 0, "val": 0, "test": 0}
sum_accuracy_combo = {"train": 0, "val": 0, "test": 0}
sum_accuracy_a = {"train": 0, "val": 0, "test": 0}
sum_accuracy_b = {"train": 0, "val": 0, "test": 0}
progbar = None
# Process each split
net.train()
#widgets = [
#' [', pb.Timer(), '] '#,
#pb.Bar(),
#' [', pb.ETA(), '] ', pb.Variable('ta','[Train Acc: {formatted_value}]')
#]
#progbar = pb.ProgressBar(max_value=len(loaders_a[split]),widgets=widgets,redirect_stdout=True)
#net.eval()
#print("Evaluation")
# Process each batch
print("Pre-for")
#j=0
for j, ((input_a, labels_a), (input_b, labels_b)) in enumerate(zip(loaders_a["train"], loaders_b["train"])):
print("first print inside for")
labels_a = labels_a.unsqueeze(1).float()
labels_b = labels_b.unsqueeze(1).float()
input_a = input_a.to(dev)
labels_a = labels_a.to(dev)
input_b = input_b.to(dev)
labels_b = labels_b.to(dev)
# Reset gradients
optimizer.zero_grad()
# Compute output
pred = net(input_a,input_b)
loss = criterion(pred, [labels_a, labels_b])
# Update loss
sum_loss["train"] += loss.item()
# Check parameter update
#if split == "train":
# Compute gradients
loss.backward()
# Optimize
optimizer.step()
print("second print inside for")
# Compute accuracy
pred_labels = (pred[2] >= 0.0).long() # Binarize predictions to 0 and 1
pred_labels_a = (pred[0] >= 0.0).long() # Binarize predictions to 0 and 1
pred_labels_b = (pred[1] >= 0.0).long() # Binarize predictions to 0 and 1
#batch_accuracy_combo = (pred_labels == labels).sum().item() / len(labels)
batch_accuracy_a = (pred_labels_a == labels_a).sum().item() / len(labels_a)
batch_accuracy_b = (pred_labels_b == labels_b).sum().item() / len(labels_b)
# Update accurac
#sum_accuracy_combo["train"] += batch_accuracy_combo
sum_accuracy_a["train"] += batch_accuracy_a
sum_accuracy_b["train"] += batch_accuracy_b
#if (split=='train'):
#progbar.update(j, ta=batch_accuracy)
#progbar.update(j, ta=batch_accuracy_a)
#progbar.update(j, ta=batch_accuracy_b)
print("no progbar")
#j=j+1
#if (progbar is not None):
#progbar.finish()
# Compute epoch loss/accuracy
epoch_loss = sum_loss["train"] / (len(loaders_a["train"]) + len(loaders_b["train"]))
#epoch_accuracy_combo = sum_accuracy_combo["train"] / (len(loaders_a["train"]) + len(loaders_b["train"]))
epoch_accuracy_a = sum_accuracy_a["train"] / len(loaders_a["train"])
epoch_accuracy_b = sum_accuracy_b["train"] / len(loaders_b["train"])
# Store params at the best validation accuracy
if save_param and epoch_accuracy["val"] > best_val_accuracy:
# torch.save(net.state_dict(), f"{net.__class__.__name__}_best_val.pth")
torch.save(net.state_dict(), f"{model_name}_best_val.pth")
best_val_accuracy = epoch_accuracy["val"]
# Update history
history_loss["train"].append(epoch_loss)
#history_accuracy_combo["train"].append(epoch_accuracy_combo)
history_accuracy_a["train"].append(epoch_accuracy_a)
history_accuracy_b["train"].append(epoch_accuracy_b)
# Print info
print(f"Epoch {epoch + 1}:",
f"TrL for combo={epoch_loss:.4f},",)
print(f"Epoch {epoch + 1}:",
f"TrA for A={epoch_accuracy_a:.4f},")
print(f"Epoch {epoch + 1}:",
f"TrA for B={epoch_accuracy_b:.4f},")
And then this is the same function, but changing all the “train” in “val”
def train(net, loaders, optimizer, criterion, epochs=20, dev=None, save_param=False, model_name="valerio"):
loaders_a, loaders_b = loaders
# try:
net = net.to(dev)
#print(net)
#summary(net,[(net.in_channels,net.in_width,net.in_height)]*2)
criterion.to(dev)
# Initialize history
history_loss = {"train": [], "val": [], "test": []}
history_accuracy_combo = {"train": [], "val": [], "test": []}
history_accuracy_a = {"train": [], "val": [], "test": []}
history_accuracy_b = {"train": [], "val": [], "test": []}
# Store the best val accuracy
best_val_accuracy = 0
# Process each epoch
for epoch in range(epochs):
# Initialize epoch variables
sum_loss = {"train": 0, "val": 0, "test": 0}
sum_accuracy_combo = {"train": 0, "val": 0, "test": 0}
sum_accuracy_a = {"train": 0, "val": 0, "test": 0}
sum_accuracy_b = {"train": 0, "val": 0, "test": 0}
progbar = None
# Process each split
net.train()
#widgets = [
#' [', pb.Timer(), '] '#,
#pb.Bar(),
#' [', pb.ETA(), '] ', pb.Variable('ta','[Train Acc: {formatted_value}]')
#]
#progbar = pb.ProgressBar(max_value=len(loaders_a[split]),widgets=widgets,redirect_stdout=True)
#net.eval()
#print("Evaluation")
# Process each batch
print("Pre-for")
#j=0
for j, ((input_a, labels_a), (input_b, labels_b)) in enumerate(zip(loaders_a["val"], loaders_b["val"])):
print("first print inside for")
labels_a = labels_a.unsqueeze(1).float()
labels_b = labels_b.unsqueeze(1).float()
input_a = input_a.to(dev)
labels_a = labels_a.to(dev)
input_b = input_b.to(dev)
labels_b = labels_b.to(dev)
# Reset gradients
optimizer.zero_grad()
# Compute output
pred = net(input_a,input_b)
loss = criterion(pred, [labels_a, labels_b])
# Update loss
sum_loss["val"] += loss.item()
# Check parameter update
#if split == "train":
# Compute gradients
loss.backward()
# Optimize
optimizer.step()
print("second print inside for")
# Compute accuracy
#pred_labels = (pred[2] >= 0.0).long() # Binarize predictions to 0 and 1
pred_labels_a = (pred[0] >= 0.0).long() # Binarize predictions to 0 and 1
pred_labels_b = (pred[1] >= 0.0).long() # Binarize predictions to 0 and 1
#batch_accuracy = (pred_labels == labels).sum().item() / len(labels)
batch_accuracy_a = (pred_labels_a == labels_a).sum().item() / len(labels_a)
batch_accuracy_b = (pred_labels_b == labels_b).sum().item() / len(labels_b)
# Update accurac
#sum_accuracy[split] += batch_accuracy
sum_accuracy_a["val"] += batch_accuracy_a
sum_accuracy_b["val"] += batch_accuracy_b
#if (split=='train'):
#progbar.update(j, ta=batch_accuracy)
#progbar.update(j, ta=batch_accuracy_a)
#progbar.update(j, ta=batch_accuracy_b)
print("no progbar")
#j=j+1
#if (progbar is not None):
#progbar.finish()
# Compute epoch loss/accuracy
epoch_loss = sum_loss["val"] / (len(loaders_a["val"]) + len(loaders_b["val"]))
#epoch_accuracy = {split: sum_accuracy[split] / len(loaders[split]) for split in ["train", "val", "test"]}
epoch_accuracy_a = sum_accuracy_a["val"] / len(loaders_a["val"])
epoch_accuracy_b = sum_accuracy_b["val"] / len(loaders_b["val"])
# Store params at the best validation accuracy
if save_param and epoch_accuracy["val"] > best_val_accuracy:
# torch.save(net.state_dict(), f"{net.__class__.__name__}_best_val.pth")
torch.save(net.state_dict(), f"{model_name}_best_val.pth")
best_val_accuracy = epoch_accuracy["val"]
# Update history
history_loss["val"].append(epoch_loss)
history_accuracy_a["val"].append(epoch_accuracy_a)
history_accuracy_b["val"].append(epoch_accuracy_b)
# Print info
print(f"Epoch {epoch + 1}:",
f"VaL for combo={epoch_loss:.4f},")
print(f"Epoch {epoch + 1}:",
f"VaA for A={epoch_accuracy_a:.4f},")
print(f"Epoch {epoch + 1}:",
f"VaA for B={epoch_accuracy_b:.4f},")
And this is how I call the train function:
# Train model on val set train(combo, (loaders_a, loaders_b), optimizer, criterion, epochs=3, dev=dev)