I found a neat library for Astronomy datasets. AstroNN Is a collection of Keras-driven neural networks for astronomy data.

What it is for

The reason a dedicated astronomy package exists rather than plain Keras is that astronomical data does not look like the image sets deep learning tutorials are built on. Spectra are one-dimensional and enormous. Labels carry measurement uncertainty that you want the model to respect rather than ignore. And the datasets live in survey-specific formats at observatory archives rather than in a tidy folder of JPEGs. AstroNN wraps all of that: dataset loaders that fetch and cache from the archives, models that handle uncertainty in the loss, and a set of pretrained networks for stellar parameters from APOGEE spectra and for Gaia distances.

The example below uses Galaxy10, which is the friendly entry point: around 20,000 galaxy images in ten morphological classes, drawn from Galaxy Zoo labels over SDSS imagery. It is a plain image classification problem, so you can check the whole pipeline works before pointing it at spectra.

Getting Started

Install AstroNN

pip install astroNN matplotlib sklearn

Create a Jupyter notebook

jupyter notebook

Paste the following into the IN

%matplotlib inline
%config InlineBackend.figure_format='retina'

# import everything we need first
from tensorflow.keras import utils
import numpy as np
from sklearn.model_selection import train_test_split
import pylab as plt

from astroNN.models import Galaxy10CNN
from astroNN.datasets import galaxy10
from astroNN.datasets.galaxy10 import galaxy10cls_lookup, galaxy10_confusion

# To load images and labels (will download automatically at the first time)
# First time downloading location will be ~/.astroNN/datasets/
images, labels = galaxy10.load_data()

# To convert the labels to categorical 10 classes
labels = utils.to_categorical(labels, 10)

# Select 10 of the images to inspect
img = None
plt.ion()
print('===================Data Inspection===================')
for counter, i in enumerate(range(np.random.randint(0, labels.shape[0], size=10).shape[0])):
    img = plt.imshow(images[i])
    plt.title('Class {}: {} \n Random Demo images {} of 10'.format(np.argmax(labels[i]), galaxy10cls_lookup(labels[i]), counter+1))
    plt.draw()
    plt.pause(2.)
plt.close('all')
print('===============Data Inspection Finished===============')

# To convert to desirable type
labels = labels.astype(np.float32)
images = images.astype(np.float32)

# Split the dataset into training set and testing set
train_idx, test_idx = train_test_split(np.arange(labels.shape[0]), test_size=0.1)
train_images, train_labels, test_images, test_labels = images[train_idx], labels[train_idx], images[test_idx], labels[test_idx]

# To create a neural network instance
galaxy10net = Galaxy10CNN()

# set maximium epochs the neural network can run, set 5 to get quick result
galaxy10net.max_epochs = 5

# To train the nerual net
# astroNN will normalize the data by default
galaxy10net.train(train_images, train_labels)

# print model summary before training
galaxy10net.keras_model.summary()

# After the training, you can test the neural net performance
# Please notice predicted_labels are labels predicted from neural network. test_labels are ground truth from the dataset
predicted_labels = galaxy10net.test(test_images)

# Convert predicted_labels to class
prediction_class = np.argmax(predicted_labels, axis=1)

# Convert test_labels to class
test_class = np.argmax(test_labels, axis=1)

# Prepare a confusion matrix
confusion_matrix = np.zeros((10,10))

# create the confusion matrix
for counter, i in enumerate(prediction_class):
    confusion_matrix[i, test_class[counter]] += 1

# Plot the confusion matrix
galaxy10_confusion(confusion_matrix)

Reading the result

The confusion matrix at the end is the part worth sitting with. A plain accuracy number hides which classes the model is confusing, and in galaxy morphology the confusions are informative rather than random: edge-on spirals and smooth round galaxies get mixed up because at this resolution they do look alike, and the barred and unbarred spirals blur into each other for the same reason. A model that scores well overall while collapsing two neighbouring classes is telling you something about the imagery, not just about itself.

Two practical notes. The first run downloads the dataset into ~/.astroNN/datasets/ and it is a couple of gigabytes, so do not start it on a hotel connection. And five epochs is set here to get a quick result, not a good one; it is enough to prove the pipeline runs end to end, which is the point of a first notebook.