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
File size: 4,431 Bytes
41bf89a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | ---
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.
|