TorchEnsemble-Community / Ensemble-Pytorch

A unified ensemble framework for PyTorch to improve the performance and robustness of your deep learning model.
https://ensemble-pytorch.readthedocs.io
BSD 3-Clause "New" or "Revised" License
1.09k stars 95 forks source link

Allowing the use of alternative loss functions #82

Open by256 opened 3 years ago

by256 commented 3 years ago

Hi,

Thank you for this super useful library.

I've noticed that the ensemble modules are all restricted to either cross-entropy loss (in the case of classification) or mean squared error loss (in the case of regression). Is there a particular reason for this? It would be great if we could pass any objective function of our choosing to the ensemble modules, as this would provide much greater flexibility.

If there are no theoretical restrictions as to why we can't use alternative losses, I could potentially have a go at implementing this.

Batuhan

xuyxu commented 3 years ago

Hi Batuhan,

The use of cross entropy loss for classifier and mean squared error loss for regressor rooted in the early API design of torchensemble (following the same design of Scikit-Learn Ensemble). I agree with you that there should be no limitation on the specification of objective functions.


If there are no theoretical restrictions as to why we can't use alternative losses, I could potentially have a go at implementing this.

Sure, your contributions are highly welcomed. Here are some ideas coming from my mind:

Gradient boosting requires additional considerations, we could skip this ensemble first.

The ideas above are still very rough, feel free to comment below if you have better solutions. If you agree with this design, how about we start with Voting?

by256 commented 3 years ago

That makes sense.

Thanks for the suggestions. Starting with Voting seems like a reasonable idea. I'll take an in-depth look at the current API on Monday and see if I have any ideas. I'll keep you posted here if I run into any trouble.

xuyxu commented 3 years ago

Great!

by256 commented 3 years ago

Would it be simpler to just set the loss function as an instance variable with a set_criterion method, then access the method via a call to self.criterion in each ensemble module? For example:

model = VotingRegressor(
    estimator=MLP,
    n_estimators=10,
    cuda=True,
)

criterion = nn.L1Loss()
model.set_criterion(criterion)

I've tried this and it seems to work well for all of the ensemble modules except GradientBoosting. This would also circumvent the need to create additional custom classes for each ensemble module. Let me know what you think of this idea.

The additional considerations of GradientBoosting could potentially be addressed by calculating pseudo-residuals using torch.autograd.grad, although I may have missed something in the code that would not make this possible. What do you think?

xuyxu commented 3 years ago

Sorry for the late response @by256.

Would it be simpler to just set the loss function as an instance variable with a set_criterion method, then access the method via a call to self.criterion in each ensemble module?

Sure, this looks nice!

Meanwhile, I will also take a look at how to automatically calculate the first-order gradients with torch.autograd.grad ;-)