Closed WMeixiang closed 5 years ago
(1) I am not used to Tensorflow or Keras, so is it difficult for me to help you. Especially since the paradigm is slightly different (where stuff runs in a session). Are you sure the two are on the same device ? The _device
variable seems different in your error message.
As you can see, the results of one_hot2dist
will be the same shape as its input. But you could add an assertion at the end just to be sure:
res = np.zeros_like(seg)
...
assert res.shape == seg.shape
return res
If this pass, you should also make sure that y_true
and y_pred
have the same shape (guess you will have to use tf.assert for that, don't know the details). Other than that, I think it would be a problem different than the shape. Perhaps because the y_pred are floats, while the distance maps are doubles (I think NumPy defaults to float64 and not float32 as many deep learning frameworks).
(2): Yes it is not obvious at first. I actually give a list of losses to the main script, which are then summed:
def setup(...):
...
losses = eval(args.losses)
loss_fns: List[Callable] = []
for loss_name, loss_params, _, _, fn, _ in losses:
loss_class = getattr(__import__('losses'), loss_name)
loss_fns.append(loss_class(**loss_params, fn=fn))
loss_weights: List[float] = map_(itemgetter(5), losses)
...
def do_epoch(...):
...
for j, data in enumerate(loader):
...
# Forward
pred_logits: Tensor = net(image)
pred_probs: Tensor = F.softmax(pred_logits, dim=1)
assert len(bounds) == len(loss_fns) == len(loss_weights)
ziped = zip(loss_fns, labels, loss_weights, bounds)
# Apply each loss, creating a list of loss values
losses = [w * loss_fn(pred_probs, label, bound) for loss_fn, label, w, bound in ziped]
# Then sum them
loss = reduce(add, losses)
assert loss.shape == (), loss.shape
# Backward
if optimizer:
loss.backward()
optimizer.step()
...
...
While this is more complicated at first, it gives much more flexibility then to experiment and avoid code duplication.
(3): I update the loss weights in the schedulers:
optimizer, loss_fns, loss_weights = scheduler(i, optimizer, loss_fns, loss_weights)
where scheduler is one of the strategies defined in the scheduler.py file. There is --schedule
, --scheduler
, and --scheduler_params
to define what you wan to use. Many examples of options can be found in the makefile
(4) Sigmoid or softmax, that is actually a hyper-parameter (just as the network architecture and the activation functions inside the network). So for some problem one will be better, and on other tasks it will be the opposite. The main difference will be wrt the gradient of the loss.
In addition, I define the SurfaceLoss by 'def ', rather than by 'class' . Is this different?
No, that is the same. I use a class (where I define the __call__
function) so I can easily add parameters to the loss (which is the case for some of my other projects). But in this case, and function and a callable object are effectively the same.
Thank you very much for your detailed reply. (1)Through experiments, I know that y_true is a placeholder, there is no specific value. So, Is the one_hot2dist function applied to the label data corresponding to image used to train? (2) If I use one_hot2dist in your code, applied to the imgs_mask_train, then it works, but I have an question,If I simply run the boundary loss, my metric [dice_coef] did not improve during training?instead,it decreased at first, then stabilize at a value. Besides, the value of the boundary loss fluctuated between 95 and 96, also did not decrease? I have no idea why? (3) I seriously read your main.py, You update the weights in each loop. Maybe the framework is different, I also try to use the loop to update the weights or write a custom callback, but it always report an error. (4) Since I don't have the data corresponding to your code, I could’t reproduce your results. I want to use your code to run my existing data. My data is also in numpy format. I don't know much about makefiles. I don't know how to modify the makefile to adapt to my data. Besides the makefile, is there necessary to modify other script? Could you help me?
Hey,
(1): Yes, we apply one_hot2dist to the labels of the image.
(2): The specifics (boundary loss weight, other loss to use if you want one, and other hyper-parameters) will be dependent of the task, as for many machine learning applications. You will have to experiment to see what fits your applications.
(3): Yeah that is how we do things in Pytorch, but I won't be able to help you on another framework. Usually they should work in a similar fashion.
(4): You can either get the data yourself (links in https://github.com/LIVIAETS/surface-loss/blob/master/data/wmh.lineage and https://github.com/LIVIAETS/surface-loss/blob/master/data/ISLES.lineage), or adapt to your data. Since the datasets used in the paper are multi-modal, I had to save the data as npy files, with the shape modality x width x height
for the image, and width x height
for the labels . So I think the main modification for you will be to replace the location of the data in the makefiles (you can do that with a search and replace, that is what I do when I use a new dataset). You can also refer to my other reply about makefiles https://github.com/LIVIAETS/surface-loss/issues/10#issuecomment-492269482
Take a look as well to the readme, where I describe how I structure the dataset folders (https://github.com/LIVIAETS/surface-loss section datascheme/dataset)
Currently, my code use the torch.tensor
and gt_transform
transforms for the image and labels, respectively:
# torch.tensor: simply copy the numpy data into a Tensor, without any modification
# gt_transform: go from class_number (shape wh) to one_hot encoding (shape cwh)
gt_transform = transforms.Compose([
lambda img: np.array(img)[np.newaxis, ...],
lambda nd: torch.tensor(nd, dtype=torch.int64),
partial(class2one_hot, C=n_class),
itemgetter(0)
])
If your data is different, you will either need to change the transform used, or to pre-process your data ; that is up to you.
Hope that helps.
Thank you very much for your reply. I will try again.
Best wishes,
Meixiang Huang
-----原始邮件----- 发件人:"Hoel KERVADEC" notifications@github.com 发送时间:2019-06-03 23:22:42 (星期一) 收件人: LIVIAETS/surface-loss surface-loss@noreply.github.com 抄送: WMeixiang 11735032@zju.edu.cn, Author author@noreply.github.com 主题: Re: [LIVIAETS/surface-loss] Question on SurfaceLoss (#11)
Hey,
(1): Yes, we apply one_hot2dist to the labels of the image.
(2): The specifics (boundary loss weight, other loss to use if you want one, and other hyper-parameters) will be dependent of the task, as for many machine learning applications. You will have to experiment to see what fits your applications.
(3): Yeah that is how we do things in Pytorch, but I won't be able to help you on another framework. Usually they should work in a similar fashion.
(4): You can either get the data yourself (links in https://github.com/LIVIAETS/surface-loss/blob/master/data/wmh.lineage and https://github.com/LIVIAETS/surface-loss/blob/master/data/ISLES.lineage), or adapt to your data. Since the datasets used in the paper are multi-modal, I had to save the data as npy files, with the shape modality x width x height for the image, and width x height for the labels . So I think the main modification for you will be to replace the location of the data in the makefiles (you can do that with a search and replace, that is what I do when I use a new dataset). You can also refer to my other reply about makefiles #10 (comment)
Take a look as well to the readme, where I describe how I structure the dataset folders (https://github.com/LIVIAETS/surface-loss section datascheme/dataset)
Currently, my code use the torch.tensor and gt_transform transforms for the image and labels, respectively:
partial(class2one_hot, C=n_class),
itemgetter(0)
])
If your data is different, you will either need to change the transform used, or to pre-process your data ; that is up to you.
Hope that helps.
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or mute the thread.
Thank you very much for your reply. I will try again. Best wishes, Meixiang Huang … -----原始邮件----- 发件人:"Hoel KERVADEC" notifications@github.com 发送时间:2019-06-03 23:22:42 (星期一) 收件人: LIVIAETS/surface-loss surface-loss@noreply.github.com 抄送: WMeixiang 11735032@zju.edu.cn, Author author@noreply.github.com 主题: Re: [LIVIAETS/surface-loss] Question on SurfaceLoss (#11) Hey, (1): Yes, we apply one_hot2dist to the labels of the image. (2): The specifics (boundary loss weight, other loss to use if you want one, and other hyper-parameters) will be dependent of the task, as for many machine learning applications. You will have to experiment to see what fits your applications. (3): Yeah that is how we do things in Pytorch, but I won't be able to help you on another framework. Usually they should work in a similar fashion. (4): You can either get the data yourself (links in https://github.com/LIVIAETS/surface-loss/blob/master/data/wmh.lineage and https://github.com/LIVIAETS/surface-loss/blob/master/data/ISLES.lineage), or adapt to your data. Since the datasets used in the paper are multi-modal, I had to save the data as npy files, with the shape modality x width x height for the image, and width x height for the labels . So I think the main modification for you will be to replace the location of the data in the makefiles (you can do that with a search and replace, that is what I do when I use a new dataset). You can also refer to my other reply about makefiles #10 (comment) Take a look as well to the readme, where I describe how I structure the dataset folders (https://github.com/LIVIAETS/surface-loss section datascheme/dataset) Currently, my code use the torch.tensor and gt_transform transforms for the image and labels, respectively: # torch.tensor: simply copy the numpy data into a Tensor, without any modification# gt_transform: go from class_number (shape wh) to one_hot encoding (shape cwh) gt_transform = transforms.Compose([ lambdaimg: np.array(img)[np.newaxis, ...], lambdand: torch.tensor(nd, dtype=torch.int64), partial(class2one_hot, C=n_class), itemgetter(0) ]) If your data is different, you will either need to change the transform used, or to pre-process your data ; that is up to you. Hope that helps. — You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or mute the thread.
Hi WMeixiang!
I'm interested in surface loss keras implementation too! Did you get it work??
Thank you very much in advance!
Hey, sorry for the late reply!
There may be something wrong with my code when I use surface loss. You could try to implement one_hot2dist() seriously with your data, this function is the key point.
2019-10-28 23:48:26"América Bueno Gómez" notifications@github.com写道:
Thank you very much for your reply. I will try again. Best wishes, Meixiang Huang … -----原始邮件----- 发件人:"Hoel KERVADEC" notifications@github.com 发送时间:2019-06-03 23:22:42 (星期一) 收件人: LIVIAETS/surface-loss surface-loss@noreply.github.com 抄送: WMeixiang 11735032@zju.edu.cn, Author author@noreply.github.com 主题: Re: [LIVIAETS/surface-loss] Question on SurfaceLoss (#11) Hey, (1): Yes, we apply one_hot2dist to the labels of the image. (2): The specifics (boundary loss weight, other loss to use if you want one, and other hyper-parameters) will be dependent of the task, as for many machine learning applications. You will have to experiment to see what fits your applications. (3): Yeah that is how we do things in Pytorch, but I won't be able to help you on another framework. Usually they should work in a similar fashion. (4): You can either get the data yourself (links in https://github.com/LIVIAETS/surface-loss/blob/master/data/wmh.lineage and https://github.com/LIVIAETS/surface-loss/blob/master/data/ISLES.lineage), or adapt to your data. Since the datasets used in the paper are multi-modal, I had to save the data as npy files, with the shape modality x width x height for the image, and width x height for the labels . So I think the main modification for you will be to replace the location of the data in the makefiles (you can do that with a search and replace, that is what I do when I use a new dataset). You can also refer to my other reply about makefiles #10 (comment) Take a look as well to the readme, where I describe how I structure the dataset folders (https://github.com/LIVIAETS/surface-loss section datascheme/dataset) Currently, my code use the torch.tensor and gt_transform transforms for the image and labels, respectively: # torch.tensor: simply copy the numpy data into a Tensor, without any modification# gt_transform: go from class_number (shape wh) to one_hot encoding (shape cwh) gt_transform = transforms.Compose([ lambdaimg: np.array(img)[np.newaxis, ...], lambdand: torch.tensor(nd, dtype=torch.int64), partial(class2one_hot, C=n_class), itemgetter(0) ]) If your data is different, you will either need to change the transform used, or to pre-process your data ; that is up to you. Hope that helps. — You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or mute the thread.
Hi WMeixiang!
I'm interested in surface loss keras implementation too! Did you get it work??
Thank you very much in advance!
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or unsubscribe.
Thanks for sharing a very good idea. I am interested in the surface loss function.
(1): In the SurfaceLoss(), the dist_maps is Tensor, while dist_maps is from
def one_hot2dist(seg: np.ndarray) -> np.ndarray:
, the format of input and output is ndarray, how to convert the format of data? This question confused me several days, I want to rewrite SurfaceLoss in keras, The following is the code I am rewriting:if I use generalized_dice_loss as cost, my code is ok, but if I use SurfaceLoss, there are some error:
---> I guess the problem is the dimension problem about output, I try to modify, but it always have this problem, could you help me?
(2): your final_loss is formula(6) in your paper midl, combine the generalized_dice_loss and surfaceloss, but I did not find final_loss in your main.py, how to operate?
(3): In formula(6), alpha is dynamic, is related to epoch, how to generate alpha? In your project, I didn't find the definition of function about alpha
(4): For two classifications, the activation function of final layer: softmax, sigmoid. what the difference between softmax and sigmoid? when I used generalized_dice_loss as cost in my code, the sigmoid function perform better than softmax, I have no idea why? Looking forward to your reply.