Skip to content

Commit 54e388a

Browse files
authored
Merge pull request #4 from codalab/new_codabench_example_comp
Mini MNIST bundle added
2 parents fd4e730 + dc6f220 commit 54e388a

276 files changed

Lines changed: 1044 additions & 2 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,5 +216,3 @@ pip-log.txt
216216

217217
#Mr Developer
218218
.mr.developer.cfg
219-
220-
*.zip
627 KB
Binary file not shown.
Lines changed: 42 additions & 0 deletions
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Mini-MNIST Challenge Bundle
2+
# Created by: Ihsan Ullah
3+
# Created on: Apr 05, 2026
4+
5+
version: 2
6+
title: Mini-MNIST Digit Classification
7+
description: A mini-MNIST challenge with 20 training images per class and 5 test images per class.
8+
image: logo.png
9+
registration_auto_approve: True
10+
docker_image: codalab/codalab-legacy:py39
11+
12+
terms: pages/terms.md
13+
pages:
14+
- title: Overview
15+
file: pages/overview.md
16+
- title: Evaluation
17+
file: pages/evaluation.md
18+
19+
phases:
20+
- index: 0
21+
name: Competition Phase
22+
description: Train on 20 images/class and predict on 5 images/class.
23+
start: 2026-01-01
24+
end: 2027-01-01
25+
tasks:
26+
- 0
27+
28+
tasks:
29+
- index: 0
30+
name: MNIST Classification Task
31+
description: Classify 50 handwritten digits (5 per class).
32+
input_data: input_data/
33+
reference_data: reference_data/
34+
scoring_program: scoring_program/
35+
ingestion_program: ingestion_program/
36+
37+
leaderboards:
38+
- index: 0
39+
title: Results
40+
key: main_leaderboard
41+
submission_rule: "Force_Latest_Multiple"
42+
columns:
43+
- index: 0
44+
title: Accuracy
45+
key: score
Lines changed: 24 additions & 0 deletions
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
# ------------------------------------------
2+
# Imports
3+
# ------------------------------------------
4+
import os
5+
import json
6+
import numpy as np
7+
import pandas as pd
8+
from PIL import Image
9+
from datetime import datetime as dt
10+
11+
12+
class Ingestion:
13+
"""
14+
Class for handling the ingestion process.
15+
16+
Args:
17+
None
18+
19+
Attributes:
20+
* start_time (datetime): The start time of the ingestion process.
21+
* end_time (datetime): The end time of the ingestion process.
22+
* model (object): The model object.
23+
* X_train (np.ndarray): The train images.
24+
* y_train (np.ndarray): The train labels.
25+
* X_test (np.ndarray): The test images.
26+
* y_pred (np.ndarray): The test predictions.
27+
* ingestion_result (dict): The ingestion result dict.
28+
"""
29+
30+
def __init__(self):
31+
"""
32+
Initialize the Ingestion class.
33+
"""
34+
self.start_time = None
35+
self.end_time = None
36+
self.model = None
37+
self.X_train = None
38+
self.y_train = None
39+
self.X_test = None
40+
self.y_pred = None
41+
self.ingestion_result = {}
42+
43+
def start_timer(self):
44+
"""
45+
Start the timer for the ingestion process.
46+
"""
47+
self.start_time = dt.now()
48+
49+
def stop_timer(self):
50+
"""
51+
Stop the timer for the ingestion process.
52+
"""
53+
self.end_time = dt.now()
54+
55+
def get_duration(self):
56+
"""
57+
Get the duration of the ingestion process.
58+
59+
Returns:
60+
timedelta: The duration of the ingestion process.
61+
"""
62+
if self.start_time is None:
63+
print("[-] Timer was never started. Returning None")
64+
return None
65+
66+
if self.end_time is None:
67+
print("[-] Timer was never stopped. Returning None")
68+
return None
69+
70+
return self.end_time - self.start_time
71+
72+
def load_train_and_test_data(self, input_dir):
73+
"""
74+
Load the training and testing data.
75+
76+
Args:
77+
input_dir (str): The input directory name.
78+
"""
79+
print("[*] Loading data")
80+
81+
# Load Training Data
82+
train_data_dir = os.path.join(input_dir, "train_data")
83+
train_labels_file = os.path.join(input_dir, "train_labels.csv")
84+
if os.path.exists(train_labels_file) and os.path.isdir(train_data_dir):
85+
df_train = pd.read_csv(train_labels_file)
86+
images = []
87+
for filename in df_train['filename']:
88+
img_path = os.path.join(train_data_dir, filename)
89+
img = Image.open(img_path)
90+
images.append(np.array(img))
91+
self.X_train = np.array(images)
92+
self.y_train = df_train['label'].values
93+
94+
# Load Test Data
95+
test_data_dir = os.path.join(input_dir, "test_data")
96+
if os.path.isdir(test_data_dir):
97+
# Sort files to ensure consistency with reference labels
98+
test_files = sorted([f for f in os.listdir(test_data_dir) if f.endswith('.png')])
99+
images = []
100+
for filename in test_files:
101+
img_path = os.path.join(test_data_dir, filename)
102+
img = Image.open(img_path)
103+
images.append(np.array(img))
104+
self.X_test = np.array(images)
105+
106+
def init_submission(self, Model):
107+
"""
108+
Initialize the submitted model.
109+
110+
Args:
111+
Model (object): The model class.
112+
"""
113+
print("[*] Initializing Submitted Model")
114+
self.model = Model()
115+
116+
def fit_submission(self):
117+
"""
118+
Fit the submitted model.
119+
"""
120+
print("[*] Fitting Submitted Model")
121+
if self.X_train is not None and self.y_train is not None:
122+
self.model.fit(self.X_train, self.y_train)
123+
124+
def predict_submission(self):
125+
"""
126+
Make predictions using the submitted model.
127+
"""
128+
print("[*] Predicting")
129+
if self.X_test is not None:
130+
self.y_pred = self.model.predict(self.X_test)
131+
132+
def save_predictions(self, output_dir=None):
133+
"""
134+
Save the ingestion result to files.
135+
136+
Args:
137+
output_dir (str): The output directory to save the result files.
138+
"""
139+
if self.y_pred is not None:
140+
prediction_file = os.path.join(output_dir, "predictions.npy")
141+
np.save(prediction_file, self.y_pred)
142+
print(f"[*] Saved predictions to {prediction_file}")
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
command: python3 run_ingestion.py --codabench
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# ------------------------------------------
2+
# Imports
3+
# ------------------------------------------
4+
import os
5+
import sys
6+
import argparse
7+
8+
# ------------------------------------------
9+
# Directories
10+
# ------------------------------------------
11+
module_dir = os.path.dirname(os.path.realpath(__file__))
12+
root_dir_name = os.path.dirname(module_dir)
13+
14+
# ------------------------------------------
15+
# Args
16+
# ------------------------------------------
17+
parser = argparse.ArgumentParser(
18+
description="This is script to run ingestion program for the competition"
19+
)
20+
parser.add_argument(
21+
"--codabench",
22+
help="True when running on Codabench",
23+
action="store_true",
24+
)
25+
26+
# ------------------------------------------
27+
# Main
28+
# ------------------------------------------
29+
if __name__ == "__main__":
30+
31+
print("\n----------------------------------------------")
32+
print("Ingestion Program started!")
33+
print("----------------------------------------------\n\n")
34+
35+
args = parser.parse_args()
36+
37+
if not args.codabench:
38+
# DO NOT CHANGE THESE PATHS UNLESS YOU CHANGE THE FOLDER NAMES IN THE BUNDLE
39+
input_dir = os.path.join(root_dir_name, "input_data")
40+
output_dir = os.path.join(root_dir_name, "sample_result_submission")
41+
program_dir = os.path.join(root_dir_name, "ingestion_program")
42+
submission_dir = os.path.join(root_dir_name, "sample_code_submission")
43+
else:
44+
# DO NOT CHANGE THESE PATHS. THESE ARE USED ON THE CODABENCH PLATFORM
45+
input_dir = "/app/input_data"
46+
output_dir = "/app/output"
47+
program_dir = "/app/program"
48+
submission_dir = "/app/ingested_program"
49+
50+
sys.path.append(input_dir)
51+
sys.path.append(output_dir)
52+
sys.path.append(program_dir)
53+
sys.path.append(submission_dir)
54+
55+
# Import ingestion class
56+
from ingestion import Ingestion
57+
# Import model from submission dir
58+
from model import Model
59+
60+
# Initialize Ingestions
61+
ingestion = Ingestion()
62+
63+
# Start timer
64+
ingestion.start_timer()
65+
66+
# Load train and test data
67+
ingestion.load_train_and_test_data(input_dir)
68+
69+
# initialize submission
70+
ingestion.init_submission(Model)
71+
72+
# fit submission
73+
ingestion.fit_submission()
74+
75+
# predict submission
76+
ingestion.predict_submission()
77+
78+
# save result
79+
ingestion.save_predictions(output_dir)
80+
81+
# Stop timer
82+
ingestion.stop_timer()
83+
84+
# Show duration
85+
print("\n------------------------------------")
86+
print(f"[✔] Total duration: {ingestion.get_duration()}")
87+
print("------------------------------------")
88+
89+
print("\n----------------------------------------------")
90+
print("[✔] Ingestion Program executed successfully!")
91+
print("----------------------------------------------\n\n")
296 Bytes
306 Bytes

0 commit comments

Comments
 (0)