张量 a (3) 的大小必须与非单维 1 处的张量 b (32) 的大小匹配
The size of tensor a (3) must match the size of tensor b (32) at non-singleton dimension 1
我正在训练一个深度学习模型,但我在训练时也遇到了类似张量 a (3) 的大小必须与非单一维数 1.And 的张量 b (32) 的大小相匹配的错误准确度高于 1 的数据意味着我得到的准确度是 1.04、1.06 之类的。
下面是训练代码
def train(model,criterion,optimizer,iters):
epoch = iters
train_loss = []
validaion_loss = []
train_acc = []
validation_acc = []
states = ['Train','Valid']
for epoch in range(epochs):
print("epoch : {}/{}".format(epoch+1,epochs))
for phase in states:
if phase == 'Train':
model.train()
dataload = train_data_loader
else:
model.eval()
dataload = valid_data_loader
run_loss,run_acc = 0,0
for data in dataload:
inputs,labels = data
#print("Inputs:",inputs.shape)
#print("Labels:",labels.shape)
inputs = inputs.to(device)
labels = labels.to(device)
labels = labels.byte()
optimizer.zero_grad()
with torch.set_grad_enabled(phase == 'Train'):
outputs = model(inputs)
print("Outputs",outputs.shape)
loss = criterion(outputs,labels)
predict = outputs>=0.5
#print("Predict",predict.shape)
if phase == 'Train':
loss.backward()
optimizer.step()
acc = torch.sum(predict == labels.data)
run_loss+=loss.item()
#print("Running_Loss",run_loss)
run_acc+=acc.item()/len(labels)
#print("Running_Acc",run_acc)
if phase == 'Train':
epoch_loss = run_loss/len(train_data_loader)
train_loss.append(epoch_loss)
epoch_acc = run_acc/len(train_data_loader)
train_acc.append(epoch_acc)
else:
epoch_loss = run_loss/len(valid_data_loader)
validaion_loss.append(epoch_loss)
epoch_acc = run_acc/len(valid_data_loader)
validation_acc.append(epoch_acc)
print("{}, loss :{},accuracy:{}".format(phase,epoch_loss,epoch_acc))
history = {'Train_loss':train_loss,'Train_accuracy':train_acc,
'Validation_loss':validaion_loss,'Validation_Accuracy':validation_acc}
return model,history
下面是基础模型的代码
model = models.resnet34(pretrained = True)
for param in model.parameters():
param.requires_grad = False
model.fc = nn.Sequential(nn.Linear(model.fc.in_features,out_features = 1024),nn.ReLU(),
nn.Linear(in_features = 1024,out_features = 512),nn.ReLU(),
nn.Dropout(0.3),
nn.Linear(in_features=512,out_features=256),nn.ReLU(),
nn.Linear(in_features = 256,out_features = 3),nn.LogSoftmax(dim = 1))
device = torch.device("cuda" if cuda.is_available() else "cpu")
print(device)
model.to(device)
optimizer = optim.Adam(model.parameters(),lr = 0.00001)
criterion = nn.CrossEntropyLoss()
我尝试使用 predict == labels.unsqueeze(1) 它没有引发任何错误,但准确度超过 1。请问我必须更改代码的位置。
你的 output
张量大小 [32,3] 32 是 mini-batches 的数量,3 是你的神经网络的输出,例如
[[0.25, 0.45, 0.3],
[0.45, 0.15, 0.4],
....
....
[0.2, 0.15, 0.65]]
当你比较 output
>= 0.5 时,结果是 predict
张量,但它是 bool
张量,输出 [32,3] 的大小相同,如下所示:
[[False, False, False],
[False, False, False],
....
....
[False, False, True]]
和 Labels
是具有 32 个值的 0D 张量,例如
[0,2,...,0]
问题的原因在这里:要比较predicts
和labels
,你应该select每一行的最大概率索引predicts
这样的张量:
predicts = predicts.argmax(1)
# output
[0,0,...,2]
但是predicts
是bool
张量,不能直接将argmax
应用于bool
张量。因此,您收到了评论中指出的错误消息。要解决这个问题,你只需要做到以下几点:
predicts = (output >= 0.5)*1
现在您可以比较两个张量 predicts, labels
,因为它们的大小相同。
简而言之,您应该使用:
predicts = (output >= 0.5)*1
acc = torch.sum(predicts.argmax(1) == Labels)
你的问题解决了,但是逻辑上的准确性不正确
因此,如果您想使用带有 multi-classification 问题的 sigmoid,请小心,因为您使用 output >= 0.5
但是,输出中有 3 类。这是不正确的,因为假设您在输出中有 [0.15,0.45,0.4]。您的 predict
将是 [0, 0, 0] 然后 argmax(1)
将 select 第一个索引,如果有相同的数字,但是,第二个索引应该是 selected在这种情况下,因为它的概率最大。如果遇到 multi-classification 问题,最好的方法是使用 softmax
而不是 sigmoid (>= 0.5)
.
顺便说一句,如果你回到你的模型结构(最后一行),你会发现你已经使用了 nn.LogSoftmax
。您只需要删除此行 predicts = (outputs >= 0.5)
并直接使用:
#before the for loop
num_corrects = 0
# inside the for loop
num_corrects = num_corrects + torch.sum(outputs.argmax(1) == Labels)
#outside the loop
train_accuracy = (100. * num_corrects / len(train_loader.dataset))
我正在训练一个深度学习模型,但我在训练时也遇到了类似张量 a (3) 的大小必须与非单一维数 1.And 的张量 b (32) 的大小相匹配的错误准确度高于 1 的数据意味着我得到的准确度是 1.04、1.06 之类的。 下面是训练代码
def train(model,criterion,optimizer,iters):
epoch = iters
train_loss = []
validaion_loss = []
train_acc = []
validation_acc = []
states = ['Train','Valid']
for epoch in range(epochs):
print("epoch : {}/{}".format(epoch+1,epochs))
for phase in states:
if phase == 'Train':
model.train()
dataload = train_data_loader
else:
model.eval()
dataload = valid_data_loader
run_loss,run_acc = 0,0
for data in dataload:
inputs,labels = data
#print("Inputs:",inputs.shape)
#print("Labels:",labels.shape)
inputs = inputs.to(device)
labels = labels.to(device)
labels = labels.byte()
optimizer.zero_grad()
with torch.set_grad_enabled(phase == 'Train'):
outputs = model(inputs)
print("Outputs",outputs.shape)
loss = criterion(outputs,labels)
predict = outputs>=0.5
#print("Predict",predict.shape)
if phase == 'Train':
loss.backward()
optimizer.step()
acc = torch.sum(predict == labels.data)
run_loss+=loss.item()
#print("Running_Loss",run_loss)
run_acc+=acc.item()/len(labels)
#print("Running_Acc",run_acc)
if phase == 'Train':
epoch_loss = run_loss/len(train_data_loader)
train_loss.append(epoch_loss)
epoch_acc = run_acc/len(train_data_loader)
train_acc.append(epoch_acc)
else:
epoch_loss = run_loss/len(valid_data_loader)
validaion_loss.append(epoch_loss)
epoch_acc = run_acc/len(valid_data_loader)
validation_acc.append(epoch_acc)
print("{}, loss :{},accuracy:{}".format(phase,epoch_loss,epoch_acc))
history = {'Train_loss':train_loss,'Train_accuracy':train_acc,
'Validation_loss':validaion_loss,'Validation_Accuracy':validation_acc}
return model,history
下面是基础模型的代码
model = models.resnet34(pretrained = True)
for param in model.parameters():
param.requires_grad = False
model.fc = nn.Sequential(nn.Linear(model.fc.in_features,out_features = 1024),nn.ReLU(),
nn.Linear(in_features = 1024,out_features = 512),nn.ReLU(),
nn.Dropout(0.3),
nn.Linear(in_features=512,out_features=256),nn.ReLU(),
nn.Linear(in_features = 256,out_features = 3),nn.LogSoftmax(dim = 1))
device = torch.device("cuda" if cuda.is_available() else "cpu")
print(device)
model.to(device)
optimizer = optim.Adam(model.parameters(),lr = 0.00001)
criterion = nn.CrossEntropyLoss()
我尝试使用 predict == labels.unsqueeze(1) 它没有引发任何错误,但准确度超过 1。请问我必须更改代码的位置。
你的 output
张量大小 [32,3] 32 是 mini-batches 的数量,3 是你的神经网络的输出,例如
[[0.25, 0.45, 0.3],
[0.45, 0.15, 0.4],
....
....
[0.2, 0.15, 0.65]]
当你比较 output
>= 0.5 时,结果是 predict
张量,但它是 bool
张量,输出 [32,3] 的大小相同,如下所示:
[[False, False, False],
[False, False, False],
....
....
[False, False, True]]
和 Labels
是具有 32 个值的 0D 张量,例如
[0,2,...,0]
问题的原因在这里:要比较predicts
和labels
,你应该select每一行的最大概率索引predicts
这样的张量:
predicts = predicts.argmax(1)
# output
[0,0,...,2]
但是predicts
是bool
张量,不能直接将argmax
应用于bool
张量。因此,您收到了评论中指出的错误消息。要解决这个问题,你只需要做到以下几点:
predicts = (output >= 0.5)*1
现在您可以比较两个张量 predicts, labels
,因为它们的大小相同。
简而言之,您应该使用:
predicts = (output >= 0.5)*1
acc = torch.sum(predicts.argmax(1) == Labels)
你的问题解决了,但是逻辑上的准确性不正确
因此,如果您想使用带有 multi-classification 问题的 sigmoid,请小心,因为您使用 output >= 0.5
但是,输出中有 3 类。这是不正确的,因为假设您在输出中有 [0.15,0.45,0.4]。您的 predict
将是 [0, 0, 0] 然后 argmax(1)
将 select 第一个索引,如果有相同的数字,但是,第二个索引应该是 selected在这种情况下,因为它的概率最大。如果遇到 multi-classification 问题,最好的方法是使用 softmax
而不是 sigmoid (>= 0.5)
.
顺便说一句,如果你回到你的模型结构(最后一行),你会发现你已经使用了 nn.LogSoftmax
。您只需要删除此行 predicts = (outputs >= 0.5)
并直接使用:
#before the for loop
num_corrects = 0
# inside the for loop
num_corrects = num_corrects + torch.sum(outputs.argmax(1) == Labels)
#outside the loop
train_accuracy = (100. * num_corrects / len(train_loader.dataset))