Instructions to use MA29/astro-image-classifier with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Keras
How to use MA29/astro-image-classifier with Keras:
# !pip install -U keras tensorflow huggingface_hub # Keras needs TensorFlow installed to read "hf://" paths, so the tensorflow backend is selected here; # "jax" and "torch" also work for computation once TensorFlow is installed. import os os.environ["KERAS_BACKEND"] = "tensorflow" import keras model = keras.saving.load_model("hf://MA29/astro-image-classifier") - Notebooks
- Google Colab
- Kaggle
|
Download README.md from MA29/astro-image-classifier: direct link, hf CLI and curl.
- Browser
- Download file 4.43 kB
-
https://huggingface.co/MA29/astro-image-classifier/resolve/main/README.md
- Command line
-
hf download hf://MA29/astro-image-classifier/README.md
-
curl -L -o README.md https://huggingface.co/MA29/astro-image-classifier/resolve/main/README.md
4.43 kB
| license: mit | |
| library_name: keras | |
| pipeline_tag: image-classification | |
| tags: | |
| - image-classification | |
| - astronomy | |
| - tensorflow | |
| - keras | |
| - transfer-learning | |
| - ensemble | |
| # Astro Image Classifier | |
| An ensemble of two transfer-learned CNN branches that classifies astronomical | |
| images into 11 classes. | |
| - **Demo:** https://huggingface.co/spaces/MA29/astro-image-classifier | |
| - **Code:** https://github.com/Majd1029/Astro-Image-Classifier | |
| ## Architecture | |
| ``` | |
| vgg_ensemble_input [None,224,224,3] -> vgg_branch_model -> softmax(11) | |
| densenet_ensemble_input [None,224,224,3] -> densenet_branch_model -> softmax(11) | |
| -> Average | |
| ``` | |
| - VGG19 and DenseNet201 backbones, ImageNet-initialised and partially unfrozen | |
| - Custom heads: global average pooling, dense + batch norm, dropout | |
| - The VGG branch includes a data-augmentation block, inactive at inference | |
| - 40,056,982 parameters | |
| - Saved with Keras 3.10; optimizer state stripped, so this file is inference-only | |
| ## Classes | |
| `black_hole`, `earth`, `galaxy`, `jupiter`, `mars`, `mercury`, `neptune`, | |
| `pluto`, `saturn`, `uranus`, `venus` | |
| ## Usage | |
| **Both branches preprocess internally** — the densenet branch through a | |
| `Lambda(preprocess_input)`, the vgg branch through a channel-swap and | |
| mean-subtraction chain. Feed **raw 0-255 RGB**. Applying | |
| `vgg19.preprocess_input` or `densenet.preprocess_input` beforehand preprocesses | |
| twice and degrades predictions badly on some classes. | |
| `custom_objects` is required: the densenet Lambda is serialised under the name | |
| `preprocess_input`, and Keras resolves it by that name at load time. | |
| ```python | |
| import numpy as np, tensorflow as tf, keras | |
| from huggingface_hub import hf_hub_download | |
| from PIL import Image | |
| from tensorflow.keras.applications.densenet import preprocess_input | |
| keras.mixed_precision.set_global_policy("float32") # saved under mixed_float16 | |
| path = hf_hub_download("MA29/astro-image-classifier", "ensemble_model.keras") | |
| model = tf.keras.models.load_model( | |
| path, custom_objects={"preprocess_input": preprocess_input}, compile=False | |
| ) | |
| CLASSES = ["black_hole", "earth", "galaxy", "jupiter", "mars", "mercury", | |
| "neptune", "pluto", "saturn", "uranus", "venus"] | |
| img = Image.open("example.jpg").convert("RGB").resize((224, 224)) | |
| x = np.expand_dims(np.array(img, dtype="float32"), 0) # raw 0-255 | |
| names = [t.name.split(":")[0].split("/")[0] for t in model.inputs] | |
| probs = model.predict({n: x for n in names}, verbose=0)[0] | |
| print(CLASSES[int(np.argmax(probs))], probs.max()) | |
| ``` | |
| ## Evaluation | |
| Held-out test split: 446 images, reconstructed from the training notebook's | |
| `image_dataset_from_directory(validation_split=0.3, seed=42)` then | |
| `temp_ds.skip(14)`. Per-class supports match the notebook's own reports. | |
| | Model | Test accuracy | | |
| |---|---| | |
| | DenseNet201 branch alone | 0.9888 | | |
| | VGG19 branch alone | 0.9888 | | |
| | **Ensemble (this model)** | **0.9910** (442/446) | | |
| Macro F1 0.990, weighted F1 0.991, mean confidence 98.4%. | |
| | class | precision | recall | f1 | support | | |
| |---|---|---|---|---| | |
| | black_hole | 1.000 | 0.952 | 0.976 | 21 | | |
| | earth | 1.000 | 1.000 | 1.000 | 35 | | |
| | galaxy | 0.962 | 1.000 | 0.980 | 25 | | |
| | jupiter | 1.000 | 1.000 | 1.000 | 39 | | |
| | mars | 0.978 | 0.957 | 0.967 | 46 | | |
| | mercury | 1.000 | 1.000 | 1.000 | 50 | | |
| | neptune | 1.000 | 1.000 | 1.000 | 52 | | |
| | pluto | 1.000 | 1.000 | 1.000 | 37 | | |
| | saturn | 1.000 | 1.000 | 1.000 | 41 | | |
| | uranus | 1.000 | 1.000 | 1.000 | 48 | | |
| | venus | 0.962 | 0.981 | 0.971 | 52 | | |
| All four errors: three venus/mars confusions, and one black_hole predicted as | |
| galaxy at 100% confidence — worth knowing that high confidence is not a | |
| reliable correctness signal here. | |
| Note the test split is drawn from the same curated dataset as training, so this | |
| figure reflects in-distribution performance only. | |
| ## Limitations | |
| - Trained on a curated, fairly clean dataset of planet and deep-sky imagery; it | |
| has not been evaluated on telescope captures, noisy frames or unusual crops. | |
| - Closed-world over 11 classes — every input is forced into one of them. There | |
| is no "none of the above", so out-of-distribution images get confident and | |
| meaningless labels. | |
| - Several classes are visually similar under poor lighting or low resolution; | |
| treat single-image predictions as indicative. | |