Instructions to use sirunchained/Food-101-image-classifier with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Keras
How to use sirunchained/Food-101-image-classifier with Keras:
# Available backend options are: "jax", "torch", "tensorflow". import os os.environ["KERAS_BACKEND"] = "jax" import keras model = keras.saving.load_model("hf://sirunchained/Food-101-image-classifier") - Notebooks
- Google Colab
- Kaggle
Update README.md
Browse files
README.md
CHANGED
|
@@ -1,3 +1,109 @@
|
|
| 1 |
-
-
|
| 2 |
-
|
| 3 |
-
--
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Food-101 Image Classifier
|
| 2 |
+
|
| 3 |
+
This is an image classification model capable of identifying 101 different food categories from the Food-101 dataset. The model leverages transfer learning using a pre-trained EfficientNetB0 as its base.
|
| 4 |
+
|
| 5 |
+
## Model Details
|
| 6 |
+
|
| 7 |
+
* **Architecture**: EfficientNetB0 (feature extractor) + Custom Dense Head
|
| 8 |
+
* **Task**: Image Classification
|
| 9 |
+
* **Dataset**: [Food-101](https://huggingface.co/datasets/ethz/food101)
|
| 10 |
+
* 101 food categories
|
| 11 |
+
* 101,000 images (750 training, 250 validation per class)
|
| 12 |
+
* Images rescaled to a maximum side length of 512 pixels in original dataset.
|
| 13 |
+
|
| 14 |
+
## Training Details
|
| 15 |
+
|
| 16 |
+
### Approach
|
| 17 |
+
The model was trained using **transfer learning (feature extraction)**. The pre-trained `EfficientNetB0` model, which was originally trained on the ImageNet dataset, had its layers frozen. A new custom output layer (a `GlobalAveragePooling2D` followed by a `Dense` layer with softmax activation) was added on top of the frozen EfficientNetB0 base. Only this new head was trained on the Food-101 dataset.
|
| 18 |
+
|
| 19 |
+
### Preprocessing
|
| 20 |
+
Images from the Food-101 dataset were preprocessed as follows:
|
| 21 |
+
1. Resized to `(256, 256)` pixels.
|
| 22 |
+
2. Pixel values cast to `tf.float32`.
|
| 23 |
+
|
| 24 |
+
### Training Configuration
|
| 25 |
+
* **Optimizer**: Adam
|
| 26 |
+
* **Loss Function**: SparseCategoricalCrossentropy (suitable for integer-encoded labels)
|
| 27 |
+
* **Metrics**: Accuracy
|
| 28 |
+
* **Epochs**: 5 (with EarlyStopping if validation loss did not improve for 3 epochs)
|
| 29 |
+
* **Batch Size**: 32
|
| 30 |
+
* **Mixed Precision**: Enabled (`mixed_float16`) for faster training on compatible GPUs.
|
| 31 |
+
|
| 32 |
+
### Performance
|
| 33 |
+
After 5 epochs of training, the model achieved the following performance on the validation set:
|
| 34 |
+
* **Validation Loss**: 0.9174
|
| 35 |
+
* **Validation Accuracy**: 0.7482
|
| 36 |
+
|
| 37 |
+
## How to Use
|
| 38 |
+
|
| 39 |
+
To use this model for prediction, you'll need TensorFlow and the corresponding `EfficientNetB0` application.
|
| 40 |
+
|
| 41 |
+
```python
|
| 42 |
+
import tensorflow as tf
|
| 43 |
+
import tensorflow_datasets as tfds
|
| 44 |
+
from PIL import Image
|
| 45 |
+
import numpy as np
|
| 46 |
+
|
| 47 |
+
# Define the image size used during training
|
| 48 |
+
IMAGE_SIZE = 256
|
| 49 |
+
|
| 50 |
+
# Load the trained model
|
| 51 |
+
# Make sure to replace 'path/to/your/model/effnetB0_food_model.keras' with the actual path
|
| 52 |
+
loaded_model = tf.keras.models.load_model('./models/effnetB0_food_model.keras')
|
| 53 |
+
|
| 54 |
+
# Get class names from the dataset info
|
| 55 |
+
# (Assuming dsInfo was loaded earlier)
|
| 56 |
+
# If you don't have dsInfo, you can manually create the list of class names
|
| 57 |
+
class_names = [
|
| 58 |
+
"apple_pie", "baby_back_ribs", "baklava", "beef_carpaccio", "beef_tartare",
|
| 59 |
+
"beet_salad", "beignets", "bibimbap", "bread_pudding", "breakfast_burrito",
|
| 60 |
+
"bruschetta", "caesar_salad", "cannoli", "caprese_salad", "carrot_cake",
|
| 61 |
+
"ceviche", "cheesecake", "cheese_plate", "chicken_curry", "chicken_quesadilla",
|
| 62 |
+
"chicken_wings", "chocolate_cake", "chocolate_mousse", "churros", "clam_chowder",
|
| 63 |
+
"club_sandwich", "crab_cakes", "creme_brulee", "croque_madame", "cup_cakes",
|
| 64 |
+
"deviled_eggs", "donuts", "dumplings", "edamame", "eggs_benedict",
|
| 65 |
+
"escargots", "falafel", "filet_mignon", "fish_and_chips", "foie_gras",
|
| 66 |
+
"french_fries", "french_onion_soup", "french_toast", "fried_calamari", "fried_rice",
|
| 67 |
+
"frozen_yogurt", "garlic_bread", "gnocchi", "greek_salad", "grilled_cheese_sandwich",
|
| 68 |
+
"grilled_salmon", "guacamole", "gyoza", "hamburger", "hot_and_sour_soup",
|
| 69 |
+
"hot_dog", "huevos_rancheros", "hummus", "ice_cream", "lasagna",
|
| 70 |
+
"lobster_bisque", "lobster_roll_sandwich", "macaroni_and_cheese", "macarons", "miso_soup",
|
| 71 |
+
"mussels", "nachos", "omelette", "onion_rings", "oysters",
|
| 72 |
+
"pad_thai", "paella", "pancakes", "panna_cotta", "peking_duck",
|
| 73 |
+
"pho", "pizza", "pork_chop", "poutine", "prime_rib",
|
| 74 |
+
"pulled_pork_sandwich", "ramen", "ravioli", "red_velvet_cake", "risotto",
|
| 75 |
+
"samosa", "sashimi", "scallops", "seaweed_salad", "shrimp_and_grits",
|
| 76 |
+
"spaghetti_bolognese", "spaghetti_carbonara", "spring_rolls", "steak", "strawberry_shortcake",
|
| 77 |
+
"sushi", "tacos", "takoyaki", "tiramisu", "tuna_tartare", "waffles"
|
| 78 |
+
]
|
| 79 |
+
|
| 80 |
+
def preprocess_image(image_path):
|
| 81 |
+
img = tf.io.read_file(image_path)
|
| 82 |
+
img = tf.image.decode_jpeg(img, channels=3)
|
| 83 |
+
img = tf.image.resize(img, [IMAGE_SIZE, IMAGE_SIZE])
|
| 84 |
+
img = tf.cast(img, tf.float32) # Already normalized implicitly by EfficientNet's internal preprocessing
|
| 85 |
+
img = tf.expand_dims(img, axis=0) # Add batch dimension
|
| 86 |
+
return img
|
| 87 |
+
|
| 88 |
+
# Example usage with a dummy image path (replace with your actual image)
|
| 89 |
+
# You might need to download a sample food image for testing
|
| 90 |
+
# For example, from the Food-101 dataset itself or any food image.
|
| 91 |
+
# dummy_image_path = tf.keras.utils.get_file('pizza.jpg', 'https://upload.wikimedia.org/wikipedia/commons/thumb/a/a3/Eq_pizza_italy_vs_us.jpg/640px-Eq_pizza_italy_vs_us.jpg')
|
| 92 |
+
|
| 93 |
+
# Preprocess the image
|
| 94 |
+
# preprocessed_image = preprocess_image(dummy_image_path)
|
| 95 |
+
|
| 96 |
+
# Make a prediction
|
| 97 |
+
# predictions = loaded_model.predict(preprocessed_image)
|
| 98 |
+
# predicted_class_index = np.argmax(predictions[0])
|
| 99 |
+
# predicted_class_name = class_names[predicted_class_index]
|
| 100 |
+
|
| 101 |
+
# print(f"The predicted food item is: {predicted_class_name}")
|
| 102 |
+
# print(f"Prediction probabilities: {predictions[0][predicted_class_index]:.4f}")
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
```
|
| 106 |
+
|
| 107 |
+
## License
|
| 108 |
+
|
| 109 |
+
[MIT]
|