Programming in Python II Due: 24.06.
2026, 23:59 pm
Final Project: Predicting Satellite Images with CNN and PyTorch
Data Set
The data set for this project consists of satellite images and their corresponding labels. Each image
is a 64×64 pixel RGB image, and the labels indicate the type of terrain depicted in the image. There
are 10 classes:
• AnnualCrop • PermanentCrop
• Forest • Residential
• HerbaceousVegetation • River
• Highway • SeaLake
• Pasture • Industrial
The data set consists of 10000 images. The folder structure of the data set is as follows:
data/
+-- AnnualCrop/
+-- Forest/
+-- HerbaceousVegetation/
+-- Highway/
+-- Industrial/
+-- Pasture/
+-- PermanentCrop/
+-- Residential/
+-- River/
+-- SeaLake/
Each of the subfolders contains the images corresponding to that class. For example, the AnnualCrop
folder contains all the images labeled as AnnualCrop.
Task
Your task is to build an end-to-end machine learning pipline that
• Pre-processes a real-world data set of satellite images,
• Conducts exploratory data analysis (EDA) to understand the data,
• Implements a convolutional neural network (CNN) using PyTorch to classify the satellite
images into their respective classes,
• Evaluates the performance of the model on the validation set and analyzes the results and
• Presents the results in a shiny web application that allows users to upload their own satellite
images and see the predicted class.
To implement this, follow the steps outlined below.
1
Programming in Python II Due: 24.06.2026, 23:59 pm
Data handling and pre-processing (4 points)
Write a function preprocess(data_folder: str) -> tuple[[Link], dict] that returns:
• A DataFrame that holds the file path, file name and a numeric label for every image.
• A dictionary that maps the numeric labels to the class names.
Example output DataFrame:
folder file_name label
0 EuroSAT_RGB/HerbaceousVegetation HerbaceousVegetation_2752.jpg 0
1 EuroSAT_RGB/HerbaceousVegetation HerbaceousVegetation_2892.jpg 0
2 EuroSAT_RGB/HerbaceousVegetation HerbaceousVegetation_2542.jpg 0
3 EuroSAT_RGB/HerbaceousVegetation HerbaceousVegetation_1165.jpg 0
4 EuroSAT_RGB/HerbaceousVegetation HerbaceousVegetation_404.jpg 0
5 EuroSAT_RGB/HerbaceousVegetation HerbaceousVegetation_94.jpg 0
6 EuroSAT_RGB/HerbaceousVegetation HerbaceousVegetation_390.jpg 0
7 EuroSAT_RGB/HerbaceousVegetation HerbaceousVegetation_1899.jpg 0
8 EuroSAT_RGB/HerbaceousVegetation HerbaceousVegetation_2221.jpg 0
9 EuroSAT_RGB/HerbaceousVegetation HerbaceousVegetation_1826.jpg 0
...
Example output label dictionary:
{’HerbaceousVegetation’: 0,
’AnnualCrop’: 1,
’Residential’: 2,
’Pasture’: 3,
’Industrial’: 4,
’River’: 5,
’Highway’: 6,
’Forest’: 7,
’PermanentCrop’: 8,
’SeaLake’: 9}
You also need to split the data set into training and validation sets. The percentage split is up to
you, but a common split is 80% for training and 20% for validation, or 90% for training and 10%
for validation.
Ensure that the split is stratified, meaning that each class is represented proportionally in both sets.
Also ensure that the split is random, so that the training and validation sets are not biased. You
can use the train_test_split function from the sklearn.model_selection module to perform
the split. Do not forget to set a random seed for reproducibility!
2
Programming in Python II Due: 24.06.2026, 23:59 pm
Exploratory Data Analysis (EDA) (9 points)
Write a function show_samples(df: [Link], num_samples: int = 5) -> None that ran-
domly selects num_samples images from the DataFrame and displays them in a grid. The plot should
be shown in the notebook but at the same time also saved in a directory assets/plots under the
name random_samples.png.
Sample output:
Additionally write a function average_pixel_plot(df: [Link]) -> None that creates a
plot that shows the distribution of the average pixel values in the three color channels in the training
set. Again, plot should be shown in the notebook but at the same time also saved in a directory
assets/plots under the file name average_pixel_distribution.png.
Sample output:
Finally also create a function average_brightness_per_class(df: [Link]) -> None that
creates a boxplot that shows the distribution of the average brightness (average pixel value across all
three color channels) for each class in the training set. Again, the plot should be shown and at the
same time also saved in a directory assets/plots under the file name average_brightness.png.
The exact formatting is up to you, but ensure that the plot is clear and easy to read.
3
Programming in Python II Due: 24.06.2026, 23:59 pm
Sample output:
CNN Implementation and Training (20 points)
How you define the Dataset class, the Data Loaders, Model Architecture and the training loop is up
to you. However, you might want to consider the following points:
• For the Dataset class, you can use the DataFrame created in the pre-processing step to
load the images and their corresponding labels. You can use the PIL library to load the
images and apply any necessary transformations (e.g., augmentation, normalization) using
[Link]. Also note that you might need to differentiate depending on
whether the image is used for training or validation/testing.
• For the Data Loaders, ensure that you use appropriate batch sizes and shuffling for the training
set. Also, note that you can make use of the num_workers parameter in the DataLoader to
speed up data loading by using multiple subprocesses.
• For the Model Architecture, you can design your own CNN architecture. Do not use a pre-
trained model or transfer learning for this task. Consider using a combination of convolutional
layers, pooling layers, and fully connected layers. You can also experiment with different
activation functions, dropout, and batch normalization to improve the performance of your
model.
• For the training loop, ensure that you implement the standard training procedure, includ-
ing forward pass, loss calculation, backward pass, and optimizer step. You can use the
[Link] as the loss function for multi-class classification and an ap-
propriate optimizer (e.g., [Link] or [Link]). Consider implementing
a learning rate scheduler to adjust the learning rate during training for better convergence.
Also, ensure that you track the training and validation loss and accuracy during training to
monitor the performance of your model (and plot the loss and accuracy curves later) and to
prevent overfitting. Also consider implementing early stopping.
• You must save the best model (the model that achieves the highest accuracy on the validation
4
Programming in Python II Due: 24.06.2026, 23:59 pm
set) during training. You can use the [Link] function to save the model weights. Save
the model in assets/weights.
• Optimize the hyperparameters of your model (e.g., learning rate, batch size, architecture design
choices) to achieve the best possible performance on the validation set.
Model evaluation and analysis (7 points)
Create three plots:
• A plot that shows the training and validation loss curves over epochs, and a second plot that
shows the development of the validation accuaracy. Both plots should be shown side by side
in one figure.
• A confusion matrix that shows the performance of your model on the validation set.
• A plot that shows 5 misclassified samples. It should look similar to what the show_samples
function creates, but in addition to the true label as a caption, it should also show the predicted
label.
Also evaluate your model on the supplied test set. Note that the test set does not have a sub-
folder structure, the directory just contains the images. The file names are just numbered (e.g.,
[Link], [Link], etc.). Create a preprocess_test(data_folder: str) -> [Link] function
(or modify the existing preprocess function to accomodate the desired functionality) that returns
a DataFrame with the file paths and file names of the test images:
folder file_name
0 test_data [Link]
1 test_data [Link]
2 test_data [Link]
3 test_data [Link]
4 test_data [Link]
Then create the data loader for the test set and use your trained model to predict the classes for the
test images. Also, create a submission file [Link] in the format specified by the challenge
server, which should contain the file names and the predicted class labels (as text, not as numeric
labels, no headers).
Sample content of the [Link] file:
[Link],HerbaceousVegetation
[Link],SeaLake
[Link],Industrial
[Link],AnnualCrop
[Link],Residential
[Link],SeaLake
[Link],AnnualCrop
...
5
Programming in Python II Due: 24.06.2026, 23:59 pm
Shiny web application (10 points)
Create a shiny web application that allows the user to upload a satellite image and see the predicted
class along with the confidence score (probability) of the class. Consider the following guidelines for
the web application:
• The web application should have a file upload component that allows the user to upload an
image file.
• Once the image is uploaded, the application should use the trained CNN model to predict the
class of the image and display the predicted class along with the confidence score (probability)
of the prediction.
• The predicted class and confidence score should be displayed in a clear and user-friendly
manner. You can use a card or a box to display this information prominently on the page.
• Additionally, the application should also display the uploaded image so that the user can see
what image they uploaded and compare it with the predicted class.
• A probability table that shows the predicted probabilities for all classes also has to be included
in the application to provide more insights into the model’s predictions.
• You can assume that the file upload is done correctly and that the user uploads a valid 64×64
image file. You do not need to implement error handling for invalid file uploads (if you like
you can do so however).
• Use shiny express for your web application – do not use shiny core.
• In the first line of the [Link] file include a comment with your name and student ID.
• Create a directory app that contains your [Link] and all additional files that might be neces-
sary to run the app.
A few useful hints:
• You will need to load your trained model in the web application. There is one small stumble
block to be aware of:
state_dict = [Link](MODEL_PATH, map_location=DEVICE)
_ = model.load_state_dict(state_dict)
_ = [Link]()
load_state dict() and eval() have return values that will cause issues with shiny – make
sure to assign the return values to _ as shown in the code snippet above.
• Any transformations that you applied to the training data (e.g., normalization) also need to
be applied to the uploaded image before passing it to the model for prediction. You can define
a transformation pipeline using [Link] and apply it to the uploaded image
in the web application.
• Your model expects batched inputs, so make sure to add a batch dimension to the tensor of
the image data.
• Your model outputs raw logits, so you will need to apply the softmax function to get proba-
bilites.
6
Programming in Python II Due: 24.06.2026, 23:59 pm
Sample screenshot:
Submission
Moodle submission
Use the provided Jupyter notebook template to create your solution. Ensure that all code cells are
executed and the notebook runs without errors. If evaluation by the tutors results in an error, you
will receive 0 points. Make sure to test your notebook thoroughly before submission. Also make sure
to rename the notebook as specified therein (i.e., k[studentID].ipynb, e.g., [Link]).
Separately from the notebook, create a directory app that contains the [Link] file for the shiny app
and other files that might be necessary for execution.
Create a zip file that contains the Jupyter notebook and the app directory, and submit it through
Moodle. The zip file should be named as follows: k[studentID]_final_project.zip (for example
k12345678_final_project.zip).
Challenge Server
The [Link] file that you create in your notebook you do not need up include in the zip
file. Instead, upload it to the challenge server to check your final model performance.
Your login credentials are:
• username: K + Student ID (e.g. K1234567, with leading zeros, like in the student email)
• password: same as username (initial, set a custom one asap)
Log in to the challenge server at [Link] and you will find the chal-
lenge listed:
7
Programming in Python II Due: 24.06.2026, 23:59 pm
Click on the title of the challenge and in the top bar on ‘Submissions’, you can upload your csv file
there:
Your result will then be listed below and you can also check the public leaderboard, so see how you
fare against the models of your colleagues. Note that the leaderboard only shows the performance
of the best submission of each participant, so if you make multiple submissions, only the one with
the highest accuracy will be listed on the leaderboard.
Important: You have three attempts to evaluate your model on the challenge server, so make sure
to use them wisely. Your best submission counts.
Depending on the task scheduling of the challenge server, it can take some time for your predictions
to be evaluated and for the accuracy to be displayed on the leaderboard. Therefore, do not wait until
the last minute to submit your predictions to the challenge server, as you might not have enough
time to check if everything is working correctly and to make any necessary adjustments before the
submission deadline.
Submission Deadline
The submission deadline for the notebook on Moodle as well as the challenge server is Wednesday,
24th of June 2026, 23:59 pm. Late submissions are strictly not accepted, so make sure to submit
your work on time.
8
Programming in Python II Due: 24.06.2026, 23:59 pm
Grading Criteria
Your submission will be graded based on the following criteria:
• Jupyter Notebook submission on Moodle: correctness and completeness of the pre-processing,
CNN implementation, training process and analysis (50 points)
Criterion Weight Points
Data handling and pre-processing 8% 4 points
Exploratory Data Analysis (EDA) 18% 9 points
CNN Implementation and Training 40% 20 points
Model evaluation and analysis 14% 7 points
Shiny web application 20% 10 points
Total 100% 50 points
• Accuracy on the test set on the challenge server (20 points)
– A minimum accuracy of 91% on the test set is required to receive any points for this
criterion. If your model achieves 90% accuracy or less on the test set, you will receive 0
points for this criterion.
– If your model achieves between 91% and 95%, you will receive 4 points for every percentage
point (up to the full 5*4 = 20 points for 95% accuracy).
– For every percentage point greater than 95%, you will receive an additional 2 points as
bonus. For example, if your model achieves 97% accuracy on the test set, you will receive
20 points for the first 5 percentage points above 90% (from 91% to 95%) and an additional
4 points for the 2 percentage points above 95%, resulting in a total of 24 points for this
criterion.
Correction is done manually by the tutors. Therefore ensure that your code is well-structured,
commented, and follows good coding practices to facilitate the grading process. Expect 2-3 weeks
for the grading after the submission deadline. If you need early grading, please indicate this on
Moodle.
Notes on Reproducibility and Plagiarism
• Only use the provided data set for training and validation. Do not use any external data. Do
not tamper or modify the data sets in any way. During grading, the tutors will evaluate your
model on a separate (secret) test set, that is distinct from the one on the challenge server. If
significant deviations in performance are detected between the test set on the challenge server
and the secret test set used for grading, this will be considered as an indication of potential data
tampering or overfitting to the public test set, and will result in 0 points for the assignment.
• Your model needs to be reproducible. Therefore always set the random number seed whenever
randomness is involved (data set splits, model initialization, training loop, etc.). We will run
your provided script and compare the result of your model to the accuracies on the challenge
server. If they are not within a reasonable margin, you will also receive 0 points.
• Do not plagiarize code from the internet, from other students, AI tools, etc. Plagiarism will
result in a score of 0 points for the assignment. Ensure that all code is your own individual
work and properly cited if you use any external resources for reference.