Yes, I have used the multi class classification and find the CEL() function as my loss function. It solved my problem.
with small dataset go for agumentation process
hey bro , i want to ask one question to you , i have satellite image as a input which is [3,128,128] and mask image is [1,128,128] and i want to divide into 5 classs , and using softmax at output layer and want to use cross entropy loss , do i have to change anything on mask image or it is ok?
hello sir , i want to ask one question to you , i have satellite image as a input which is [3,128,128] and mask image is [1,128,128] and i want to divide into 5 classs , and using softmax at output layer and want to use cross entropy loss , do i have to change anything on mask image or it is ok?
If you are working on a multi-class segmentation use case, you could use nn.CrossEntropyLoss
and pass the model output in the shape [batch_size, nb_classes, height, width]
directly to the criterion without using a softmax layer.
The target should have the shape [batch_size, height, width]
and contain the class indices in the range [0, nb_classes-1]
.
Thank you so much sir, since i am very new on this concept , I am doing hit and trial of coding , i want to visulaize the results of testing image [1,5,128,128], could you suggest me something over this code for conversion of a tensor into mask image which is [1,128,128]
def predict_fundus_image(img_path,model):
img = Image.open(img_path)
transform = transforms.Compose([transforms.Resize((128,128)),
transforms.ToTensor()])
img_transformed = transform(img)
img_transformed = transform(img).unsqueeze_(0)
img_transformed = img_transformed.cpu()
model = model.cpu()
output = model(img_transformed)
output = torch.argmax(output,1)
return output
img = predict_fundus_image(r"E:\new_mission _data\test\testing1.x000.y000.png",model)
print(img)
sys.exit()
img = img.squeeze(0)
mapping = {(0, 0, 0): 0, (0, 0, 255): 1, (255, 0, 0): 2, (0,255,0):3,(255, 255, 255): 4}
rev_mapping = {mapping[k]: k for k in mapping}
pred = img
pred_image = torch.zeros(3, img.size(0), img.size(1), dtype=torch.uint8)
for k in rev_mapping:
print(k)
pred_image[:, pred==k] = torch.tensor(rev_mapping[k]).byte().view(3,1)
plt.imshow(pred_image.permute(1, 2,0).numpy())
The output
tensor would contain the class indices, since you’ve applied torch.argmax(output, 1)
on it, so you should be able to visualize it.
However, to create the mask colors, the reverse mapping would be needed from your second code snippet. Are you seeing any issues with it, i.e. is it creating an error or are you seeing unexpected results?
@ptrblck , how can we change the above script , if my y (target) data has 2 , 1 D tensors - one each for 2 targets.
You can compute two losses, sum them together, and call backward()
on the final loss.
@ptrblck your suggestion worked very well for me. I tried a quick and dirty model architecture and for my data , getting 80% of training accuracy, for testing it is little less…that i will be able to improve. I hope. wanted to share the basic architecture. I used.
class Net(nn.Module):
def __init__(self,n1,n2):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(3, 6, 5)
self.pool = nn.MaxPool2d(2, 2)
self.conv2 = nn.Conv2d(6, 16, 5)
self.fc1 = nn.Linear(16 * 13 *13, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, n1)
self.fc4= nn.Linear(84,n2)
def forward(self, x):
x = self.pool(F.relu(self.conv1(x)))
x = self.pool(F.relu(self.conv2(x)))
x = x.view(x.size(0), 16 * 13 *13)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x1 = self.fc3(x)
x2= self.fc4(x)
return x1,x2
net = Net(10,10)
Here 10 is number of classes in each of the labels in my input data.
wanted to take your feedback.
I used following for training .
loss_arr = []
loss_epoch_arr = []
max_epochs = 20
min_loss = 1000
best_model = None
for epoch in range(max_epochs): # loop over the dataset multiple times
for i, data in enumerate(train_loader, 0):
# get the inputs; data is a list of [inputs, labels]
inputs, in_labels = data
#labels_out = net(input)
_,v_actual = torch.max(in_labels[:,0,:].data,1)
_,c_actual = torch.max(in_labels[:,1,:].data,1)
# zero the parameter gradients
optimizer.zero_grad()
# forward + backward + optimize
v_out,c_out = net(inputs)
_,v_pred = torch.max(v_out,1)
_,c_pred =torch.max(c_out,1)
#outv= outputs[0]
#outc = outputs[1]
loss_v = criterion(v_out, v_actual) #loss in vowel
loss_c = criterion(c_out, c_actual) #loss in consonent
loss = torch.add(loss_v,loss_c)
loss.backward()
optimizer.step()
# print statistics
#running_loss += loss.item()
#if i % 200 == 199: # print every 2000 mini-batches
# print('[%d, %5d] loss: %.3f' %
# (epoch + 1, i + 1, running_loss / 200))
running_loss = 0.0
if min_loss > loss.item():
min_loss = loss.item()
best_model = copy.deepcopy(net.state_dict()) #create a fully independent clone of the original object and all of its children.
loss_arr.append(loss.item())
del inputs, in_labels, v_out, c_out
#torch.cuda.empty_cache() ##to empty the unused memory after processing each batch
loss_epoch_arr.append(loss.item())
print('Epoch: %d/%d, Test acc: %0.2f, Train acc: %0.2f' % (epoch, max_epochs, evaluation(validation_loader), evaluation(train_loader)))
net.load_state_dict(best_model) #Selecting the best model
plt.plot(loss_epoch_arr)
plt.show()
print(‘Finished Training’)
It’s useful!Thanks!!!
What would change if we have input as a 1D signal and each of these input files have a target in the fashion [0,1,2,2,1,0,3…].
Input: 1D array
Target/Input : [0,1,2,2,1,0,3…]
Any help would be great as my previous implementation does not yield any result.
Based on the target description this would be a multi-class classification and you could use e.g. nn.CrossEntropyLoss
.
I’m not sure, if “1D signal” means you are working with a temporal signal, but assuming it’s the case, the output of the model would have the shape [batch_size, nb_classes, time_steps]
and the target [batch_size, time_steps]
and would contain the class indices in the range [0, nb_classes-1]
.
@ptrblck Thanks a lot, Just wanted to confirm, if I am using the correct logic.
Thanks!
Maybe this method is ‘binary relevance’?
@ptrblck I perform multi-label classification for 50 different classes. I am using the torchmetrics
package. I struggle with torchmetrics.precision
, especially with the following:
#instantiate metric
num_classes=50
self.precision_macro = torchmetrics.Precision(num_classes=num_classes, threshold=0.5, average=‘macro’,multilabel=True)
#compute metric
prec_macro = self.precision_macro(y_pred, y_true)
#where y_pred is dtype=float and has shape (batch_size, num_classes): [0.53, 0.52, …0.48]
#where y_true is dtype=int and has shape (batch_size, num_classes): [1,0,…1]
If I compute the metric for a batch_size>1 I do not get an error. If I compute it for a batch_size=1 I get the following error:
~User/site-packages/torchmetrics/classification/checks.py in _check_num_classes_binary(num_classes, is_multiclass)
121 if num_classes > 2:
→ 122 raise ValueError(“Your data is binary, but num_classes
is larger than 2.”)
ValueError: Your data is binary, but num_classes
is larger than 2.
I am struggling understanding it and would really appreciate any help!
Based on this description I guess your single sample input might miss the batch dimension.
Could you check, if the batch dimension is still there and has a size of 1? Usually it’s the first dim (dim0
) of the tensor.
Thank you. Indeed it seems to miss the batch_size dim:
#batch_size=2
In [3]: y_pred.shape
Out[3]: torch.Size([2, 50])
#batch_size=1
In [4]: y_pred[0].shape
Out[4]: torch.Size([50])
Any idea of how to maintain the batch size as a tensor dimension in this case?
I manually validated the results for the batch_size=2 and the result of the metric seems to be correct. Interestingly, when using pytorch_lightning.metrics.classification.Precision
(which seems to be deprecated but computes the same metric), it does not throw an error for a batch_size=1.
Based on the posted code snippet it seems you are indexing y_pred
in the batch dimension, which will thus remove it.
You could either slice it via y_pred[0:1]
or add it back via y_pred[0].unsqueeze(0)
.
Thank you very much @ptrblck - this fixed the error and cleared up things.