def testIt():
    allAccuracy = []
    allWrongs = []
    allWrongNames = []
    for batch_idx, (data, target, batchNames) in enumerate(
            dataLoaderCuda(tensors,
                           batchSize,
                           randomAxis=True,
                           shuffle=False,
                           names=names)):
        data_temp = np.copy(data)
        data, target = Variable(data), Variable(target)
        data, target = data.cuda(), target.cuda()
        #data = data.view(-1, 24*24*24*6)
        data = data.permute(0, 4, 1, 2, 3)
        net_out = net(data)
        prediction = net_out.max(1)[1]
        selector = (prediction != target).cpu().numpy().astype(np.bool)
        wrongs = data_temp[selector]
        wrongNames = [batchNames[i] for i, j in enumerate(selector) if j]
        for wrong, n in zip(wrongs, wrongNames):
            pass
            # print(n)
        allAccuracy.extend(list((prediction == target).cpu().numpy()))
        allWrongs.extend(wrongs)
        allWrongNames.extend(wrongNames)
        #print(f"Test accuracy is {np.mean(allAccuracy)}")
    print(f"Test accuracy is {np.mean(allAccuracy)}")
    print("Wrong tensors:")
    for n in allWrongNames:
        print(n)
epochs = 1000
log_interval = 1
batchSize = 20
optimizer = optim.SGD(net.parameters(), lr=learning_rate, momentum=0.9)
optimizer = optim.Adam(net.parameters(), lr=learning_rate)

# criterion = nn.BCELoss()
# criterion = nn.MultiLabelSoftMarginLoss()
criterion = nn.NLLLoss()
test = tensors[:int(len(tensors)*0.2)]
train = tensors[int(len(tensors)*0.2):]

# Train the network
for epoch in range(epochs):
    epochAcc = []
    for batch_idx, (data, target, batchNames) in enumerate(dataLoaderCuda(train, batchSize, randomAxis=True, shuffle=False, names=names)):
        data, target = Variable(data), Variable(target)
        data, target = data, target.cuda()
        data = data.view(-1, 24*24*24*6)
        optimizer.zero_grad()
        net_out = net(data)
        prediction = net_out.max(1)[1]
        loss = criterion(net_out, target)
        #print(f"Loss is {loss}, accuracy is {np.mean((prediction == target).numpy())}")
        loss.backward()
        optimizer.step()
        currAcc = (prediction == target).cpu().numpy()
        if not sum(currAcc) == len(target):
            print(prediction.cpu().numpy()[currAcc == 0])
            print(target.cpu().numpy()[currAcc==0])
            print('\n'.join([batchNames[i] for i in np.where(currAcc == 0)[0]]))
def trainTest(epochs):
    for epoch in range(epochs):
        epochAcc = []
        for batch_idx, (data, target, batchNames) in enumerate(
                dataLoaderCuda(train,
                               batchSize,
                               randomAxis=True,
                               shuffle=False,
                               names=names)):
            data, target = Variable(data), Variable(target)
            data, target = data, target.cuda()
            #data = data.view(-1, 24*24*24*6)
            data = data.permute(0, 4, 1, 2, 3)
            optimizer.zero_grad()
            net_out = net(data)
            prediction = net_out.max(1)[1]
            loss = criterion(net_out, target)
            #print(f"Loss is {loss}, accuracy is {np.mean((prediction == target).numpy())}")
            loss.backward()
            optimizer.step()
            currAcc = (prediction == target).cpu().numpy()
            if not sum(currAcc) == len(target):
                print(prediction.cpu().numpy()[currAcc == 0])
                print(target.cpu().numpy()[currAcc == 0])
                print('\n'.join(
                    [batchNames[i] for i in np.where(currAcc == 0)[0]]))
            epochAcc.extend(list(currAcc))
            # if batch_idx % log_interval == 0:
        print(
            f"\nTrain epoch: {epoch}, loss is {loss.data.item()}, accuracy is {np.mean(epochAcc)}\n"
        )
        allAccuracy = []
        allWrongs = []
        allWrongNames = []
        for batch_idx, (data, target, batchNames) in enumerate(
                dataLoaderCuda(test,
                               batchSize,
                               randomAxis=True,
                               shuffle=False,
                               names=names)):
            data_temp = np.copy(data)
            data, target = Variable(data), Variable(target)
            data, target = data.cuda(), target.cuda()
            #data = data.view(-1, 24*24*24*6)
            data = data.permute(0, 4, 1, 2, 3)
            net_out = net(data)
            prediction = net_out.max(1)[1]
            selector = (prediction != target).cpu().numpy().astype(np.bool)
            wrongs = data_temp[selector]
            wrongNames = [batchNames[i] for i, j in enumerate(selector) if j]
            for wrong, n in zip(wrongs, wrongNames):
                pass
                # print(n)
            allAccuracy.extend(list((prediction == target).cpu().numpy()))
            allWrongs.extend(wrongs)
            allWrongNames.extend(wrongNames)
            #print(f"Test accuracy is {np.mean(allAccuracy)}")
        print(f"Test accuracy is {np.mean(allAccuracy)}")
        print("Wrong tensors:")
        for n in allWrongNames:
            print(n)
optimizer = optim.SGD(net.parameters(), lr=learning_rate, momentum=0.9)
optimizer = optim.Adam(net.parameters(), lr=learning_rate)

# criterion = nn.BCELoss()
# criterion = nn.MultiLabelSoftMarginLoss()
criterion = nn.NLLLoss()
test = tensors[:int(len(tensors) * 0.2)]
train = tensors[int(len(tensors) * 0.2):]

# Train the network
for epoch in range(epochs):
    epochAcc = []
    for batch_idx, (data, target, batchNames) in enumerate(
            dataLoaderCuda(train,
                           batchSize,
                           randomAxis=True,
                           shuffle=True,
                           names=names,
                           maxShift=6)):
        data, target = Variable(data), Variable(target)
        data, target = data, target.cuda()
        #data = data.view(-1, 24*24*24*6)
        data = data.permute(0, 4, 1, 2, 3)
        optimizer.zero_grad()
        net_out = net(data)
        prediction = net_out.max(1)[1]
        loss = criterion(net_out, target)
        #print(f"Loss is {loss}, accuracy is {np.mean((prediction == target).numpy())}")
        loss.backward()
        optimizer.step()
        currAcc = (prediction == target).cpu().numpy()
        if not sum(currAcc) == len(target):
optimizer = optim.SGD(net.parameters(), lr=learning_rate, momentum=0.9)
optimizer = optim.Adam(net.parameters(), lr=learning_rate)

# criterion = nn.BCELoss()
# criterion = nn.MultiLabelSoftMarginLoss()
criterion = nn.NLLLoss()
test = tensors[:int(len(tensors) * 0.2)]
train = tensors[int(len(tensors) * 0.2):]

# Train the network
for epoch in range(epochs):
    epochAcc = []
    for batch_idx, (data, target, batchNames) in enumerate(
            dataLoaderCuda(train,
                           batchSize,
                           randomAxis=True,
                           shuffle=False,
                           names=names)):
        data, target = Variable(data), Variable(target)
        data, target = data, target.cuda()
        #data = data.view(-1, 24*24*24*6)
        data = data.permute(0, 4, 1, 2, 3)
        optimizer.zero_grad()
        net_out = net(data)
        prediction = net_out.max(1)[1]
        loss = criterion(net_out, target)
        #print(f"Loss is {loss}, accuracy is {np.mean((prediction == target).numpy())}")
        loss.backward()
        optimizer.step()
        currAcc = (prediction == target).cpu().numpy()
        if not sum(currAcc) == len(target):