MarkusRosen / markusrosen.github.io

GNU General Public License v3.0
3 stars 0 forks source link

keras-regression-efficient-net/ #5

Open utterances-bot opened 2 years ago

utterances-bot commented 2 years ago

Transfer Learning with EfficientNet for Image Regression in Keras - Using Custom Data in Keras - Python Tutorials for Machine Learning, Deep Learning and Data Visualization

This tutorial teaches you how to use Keras for Image regression problems on a custom dataset with transfer learning.

https://rosenfelder.ai/keras-regression-efficient-net/

brunoisy commented 2 years ago

Thanks for the great tutorial! I was just surprised that it takes 5 epochs to reach better-than-baseline accuracy. It seems to me that if we set things up properly, the model should very quickly reach the baseline, since to do so it only needs to learn to return the mean output. The issue is with your output range, which is too large, and means you need 5 epochs and a pretty high learning rate just to get the model to output large enough values. To fix this, you can rescale the output to a more reasonable range (by dividing all prices by the mean price for the training data), and set a smaller learning rate (ex. 0.01), and you'll get better-than-baseline accuracy in just one epoch :) Cheers, Bruno

brunoisy commented 2 years ago

Also I don't think you should rescale the input with 1/255, since there's already a rescaling layer packaged into efficientNet that does just that. I'm surprised it worked despite the double rescaling, maybe the batch normalization makes it turn out ok (?)

ghost commented 2 years ago

This is a super helpful tutorial Markus ! I found your pipeline and code structure really useful. I also normalised my target feature to [0,1] for faster convergence as suggested by @brunoisy

Did you have any problem saving and loading your model? I repeatedly hit this error: TypeError: __init__() got an unexpected keyword argument 'reduction'

https://stackoverflow.com/questions/60530304/loading-custom-model-with-tensorflow-2-1 https://stackoverflow.com/questions/65014660/tensorflow-2-2-0-and-keras-save-model-load-model-problems

Which only went away when I removed the MeanAbsoluteError() and MeanAbsolutePercentageError() metrics in model.compile.

MarkusRosen commented 2 years ago

Thanks for the great tutorial! I was just surprised that it takes 5 epochs to reach better-than-baseline accuracy. It seems to me that if we set things up properly, the model should very quickly reach the baseline, since to do so it only needs to learn to return the mean output. The issue is with your output range, which is too large, and means you need 5 epochs and a pretty high learning rate just to get the model to output large enough values. To fix this, you can rescale the output to a more reasonable range (by dividing all prices by the mean price for the training data), and set a smaller learning rate (ex. 0.01), and you'll get better-than-baseline accuracy in just one epoch :) Cheers, Bruno

Thanks for your input! My tutorial was targeted as a basic example with no further optimizations, therefore your comments is really valuable!

MarkusRosen commented 2 years ago

This is a super helpful tutorial Markus ! I found your pipeline and code structure really useful. I also normalised my target feature to [0,1] for faster convergence as suggested by @brunoisy

Did you have any problem saving and loading your model? I repeatedly hit this error: TypeError: __init__() got an unexpected keyword argument 'reduction'

https://stackoverflow.com/questions/60530304/loading-custom-model-with-tensorflow-2-1 https://stackoverflow.com/questions/65014660/tensorflow-2-2-0-and-keras-save-model-load-model-problems

Which only went away when I removed the MeanAbsoluteError() and MeanAbsolutePercentageError() metrics in model.compile.

I did not get this error, but a possible workaround might be to save in the .h5 file format:


model_checkpoint_callback = ModelCheckpoint(
        "./data/models/" + model_name + ".h5", # change this line
        monitor="val_mean_absolute_percentage_error",
        verbose=0,
        save_best_only=True,  # save the best model
        mode="min",
        save_freq="epoch",  # save every epoch
    )  # saving eff_net takes quite a bit of time
evanhessler commented 2 years ago

Thank you Markus! This tutorial is a godsend for beginners like me. It explains many concepts that other tutorials gloss over.

It may be out of scope to include it in the tutorial, but one question I have is: how do I actually run a prediction with the model? Say you had an image saved locally and wanted to get the estimated price back.

MarkusRosen commented 2 years ago

Thank you Markus! This tutorial is a godsend for beginners like me. It explains many concepts that other tutorials gloss over.

It may be out of scope to include it in the tutorial, but one question I have is: how do I actually run a prediction with the model? Say you had an image saved locally and wanted to get the estimated price back.

Thank you for your nice comment! I added quite a bit of code to explain how you can use the trained model for inferencing on new data. See https://rosenfelder.ai/keras-regression-efficient-net/#inference-on-new-data

evanhessler commented 2 years ago

@NoBetterThanNoise

I encountered this error too

TypeError: init() got an unexpected keyword argument 'reduction'

And got it to load by using model.save(filepath, save_format='h5') and loading it with keras.models.load_model(filepath, compile=False)

ghost commented 2 years ago

@evanhessler @MarkusRosen thanks for your solutions. i eventually got passed it by changing the metric from MeanAbsoluteError() to 'mean_absolute_error'

evanhessler commented 2 years ago

Thank you for adding the inferring on new data section! I was able to get it to spit out numbers :)

I fed it all the data in processed_images and the output was between 603,000 - 607,000 for every single one. Is that the expected output or did something go awry?

MarkusRosen commented 2 years ago

Thank you for adding the inferring on new data section! I was able to get it to spit out numbers :)

I fed it all the data in processed_images and the output was between 603,000 - 607,000 for every single one. Is that the expected output or did something go awry?

In my small test of the code I got similar results. I suspect that the data itself is problematic and some of the preprocessing I performed. I removed a lot of outliers multiple times leading to a dataset that contains many observations around the mean values.

Since this was more of a basic programming tutorial for image regression with Keras, and not an actual in-depth analysis of real estate prices, I would leave it as is. I used pretty much the same code for another dataset and got overall good results.

evanhessler commented 2 years ago

I noticed in preprocess_dataframe.py you said "dataset has to be divisble by 0.8!". Is this related to the batch_size used?

MarkusRosen commented 2 years ago

I noticed in preprocess_dataframe.py you said "dataset has to be divisble by 0.8!". Is this related to the batch_size used?

As far as I remember, yes! But I wrote the preprocessing code quick&dirty, there are most likely way better solutions for this.

showkeyjar commented 2 years ago

thanks for your good article! It safe my time. I have one question to ask: I use face age dataset to train the regression model

mean_absolute_error: 0.6306 - mean_absolute_percentage_error: 22.9069

but the predict result is very strange, for example: label predicts 18 12.24 12 28.45 20 16.12 30 14.58

it that normal? or if I miss some predict operation?

I use result = model.predict(img) and print result[0][0] for predicts

showkeyjar commented 2 years ago

ok, I found problem: because I forgot add normalize operation when predict images.

EtagiBI commented 2 years ago

Great artcile indeed! What if I need to predict two numeric values from an image? Can I just change the last layer to outputs = layers.Dense(2, name="pred")(x) ? Or should I also change metrics and loss function?

ghost commented 2 years ago

@EtagiBI You'd need two prediction heads, each with a single unit in the final dense layer, and each with their own loss function and metrics that are suitable for a regression problem (e.g MAE, MSE, ..). Its quite straight forward to implement using Keras' Functional API. https://stackoverflow.com/questions/44036971/multiple-outputs-in-keras. Let me know if I've interpreted your question correctly.

EtagiBI commented 2 years ago

@NoBetterThanNoise thank you for the reply! Does it matter if two outputs affect each other? I'm trying to build a network that predicts pairs of coefficients of image transformation matrix (https://www.ncbi.nlm.nih.gov/pmc/articles/PMC7506918/). Each pair describes a certain type of image transormation. Will it be fine to use independent loss function and metric for every output in this task?

EtagiBI commented 2 years ago

@NoBetterThanNoise according to this article (https://machinelearningmastery.com/deep-learning-models-for-multi-output-regression/), there's no need to have multiple output heads with independent loss and metrics. The final layer is just model.add( Dense ( number_outputs ) ). I suppose it's expedient to have independent output heads for different kinds of outputs that can't share a single metric or loss function.

ghost commented 2 years ago

@EtagiBI Ah yes, thats a much better approach. You'd need two heads if it was classification and regression

frankemet commented 1 year ago

Thank you very much for your contribution, I found it very interesting. Would this structure work for, for example, an image ad CTR predictor (one column being the image file and another column being a ctr value (from 0 to 1)?

MarkusRosen commented 1 year ago

Thank you very much for your contribution, I found it very interesting. Would this structure work for, for example, an image ad CTR predictor (one column being the image file and another column being a ctr value (from 0 to 1)?

This is also possible, but the network architecture would need to be adapted for multiple inputs. A short introduction to multi-input Keras can be found here: https://keras.io/guides/functional_api/#models-with-multiple-inputs-and-outputs