DEV Community

Mate Technologies
Mate Technologies

Posted on

Build a Student Marks Prediction App with Python, Tkinter & ML

In this tutorial, we’ll create StudentMarks Sentinel, an AI-powered tool to predict student marks based on study hours, attendance, and previous scores. We’ll use Python, Tkinter for the GUI, and Scikit-Learn for machine learning.

You can clone the full code here: GitHub link

Step 1: Setup Your Project

First, create a new folder for your project and install the required packages:

pip install pandas numpy scikit-learn ttkbootstrap
Enter fullscreen mode Exit fullscreen mode

We’ll use:

pandas and numpy for data handling

scikit-learn for machine learning

ttkbootstrap to make a modern Tkinter UI

Step 2: Import Required Libraries

At the top of your Python script, import the libraries we’ll need:

import os, sys, threading
import tkinter as tk
from tkinter import filedialog, messagebox
from tkinter import ttk

import pandas as pd
import numpy as np

import ttkbootstrap as tb
from ttkbootstrap.constants import *

from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
Enter fullscreen mode Exit fullscreen mode

Explanation:

tkinter → GUI elements like windows, buttons, and labels

pandas → handles CSV datasets

sklearn → train ML models

ttkbootstrap → gives your app a modern theme

Step 3: Define a Helper Function

We’ll create a small utility to handle file paths, which is helpful if we package our app later:

def resource_path(file_name):
    base_path = getattr(sys, "_MEIPASS", os.path.dirname(os.path.abspath(__file__)))
    return os.path.join(base_path, file_name)
Enter fullscreen mode Exit fullscreen mode

Explanation:

Ensures your app can find files like icons whether it’s run normally or as an executable.

Step 4: Create the ML Worker

The ML worker will handle training the model in a separate thread to keep the UI responsive.

class MarksModelWorker:
    def __init__(self, csv_path, callbacks):
        self.csv_path = csv_path
        self.callbacks = callbacks
        self.model = LinearRegression()

    def run(self):
        try:
            df = pd.read_csv(self.csv_path)

            # Columns expected in CSV
            X = df[["StudyHours", "Attendance", "PreviousMarks"]]
            y = df["FinalMarks"]

            # Split data into training and testing
            X_train, X_test, y_train, y_test = train_test_split(
                X, y, test_size=0.2, random_state=42
            )

            self.model.fit(X_train, y_train)
            score = self.model.score(X_test, y_test)

            if "trained" in self.callbacks:
                self.callbacks["trained"](score, self.model)

        except Exception as e:
            if "error" in self.callbacks:
                self.callbacks["error"](str(e))
Enter fullscreen mode Exit fullscreen mode

Explanation:

LinearRegression → Predicts numeric marks

train_test_split → Splits data for testing accuracy

callbacks → Functions called after training or on error

Step 5: Build the GUI App

Now let’s start building the main app using Tkinter with ttkbootstrap:

class StudentMarksApp:
    APP_NAME = "StudentMarks Sentinel"
    APP_VERSION = "1.0"

    def __init__(self):
        self.root = tb.Window(themename="darkly")
        self.root.title(f"{self.APP_NAME} v{self.APP_VERSION}")
        self.root.minsize(1100, 650)

        try:
            self.root.iconbitmap(resource_path("logo.ico"))
        except:
            pass

        self.model = None
        self._build_ui()
Enter fullscreen mode Exit fullscreen mode

Explanation:

Creates a main window with a modern dark theme

Sets minimum size and optional icon

_build_ui() will add all buttons, labels, and inputs

Step 6: Create the UI

We break the UI into sections:

6.1 Header

main = tb.Frame(self.root, padding=10)
main.pack(fill=tk.BOTH, expand=True)

tb.Label(
    main,
    text="🎓 StudentMarks Sentinel",
    font=("Segoe UI", 22, "bold")
).pack(pady=(0, 4))

tb.Label(
    main,
    text="AI-Powered Student Marks Prediction",
    font=("Segoe UI", 10, "italic"),
    foreground="#9ca3af"
).pack(pady=(0, 20))
Enter fullscreen mode Exit fullscreen mode

Explanation:

Adds the title and subtitle

6.2 Dataset Loader

row1 = tb.Frame(main)
row1.pack(fill=tk.X, pady=6)

self.dataset_entry = tb.Entry(row1, width=90)
self.dataset_entry.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=(0, 6))
self.dataset_entry.insert(
    0,
    "Load CSV dataset (StudyHours, Attendance, PreviousMarks, FinalMarks)"
)

tb.Button(row1, text="📂 Load Dataset", bootstyle=INFO, command=self.load_dataset).pack(side=tk.LEFT, padx=3)
tb.Button(row1, text="🧠 Train Model", bootstyle=SUCCESS, command=self.train_model).pack(side=tk.LEFT, padx=3)
Enter fullscreen mode Exit fullscreen mode

Explanation:

Text input to select CSV file

Buttons to load CSV and train ML model

Step 7: Add Prediction Inputs

form = tb.Labelframe(main, text="Marks Prediction", padding=15)
form.pack(fill=tk.X, pady=10)

self.study_var = tk.DoubleVar()
self.attendance_var = tk.DoubleVar()
self.prev_marks_var = tk.DoubleVar()

tb.Label(form, text="Study Hours / Day").grid(row=0, column=0, padx=5, pady=5)
tb.Entry(form, textvariable=self.study_var).grid(row=0, column=1, padx=5)

tb.Label(form, text="Attendance (%)").grid(row=0, column=2, padx=5)
tb.Entry(form, textvariable=self.attendance_var).grid(row=0, column=3, padx=5)

tb.Label(form, text="Previous Marks").grid(row=0, column=4, padx=5)
tb.Entry(form, textvariable=self.prev_marks_var).grid(row=0, column=5, padx=5)

tb.Button(form, text="📊 Predict Marks", bootstyle=PRIMARY, command=self.predict_marks).grid(row=0, column=6, padx=10)
Enter fullscreen mode Exit fullscreen mode

Explanation:

Users can input their study hours, attendance, and previous marks

Press the button to predict final marks

Step 8: Implement Button Actions

def load_dataset(self):
    path = filedialog.askopenfilename(filetypes=[("CSV Files", "*.csv")])
    if path:
        self.dataset_entry.delete(0, tk.END)
        self.dataset_entry.insert(0, path)

def train_model(self):
    path = self.dataset_entry.get()
    if not os.path.isfile(path):
        messagebox.showerror("Error", "Invalid dataset path")
        return

    self.stats_label.config(text="Training model...")
    threading.Thread(target=self._train_worker, args=(path,), daemon=True).start()
Enter fullscreen mode Exit fullscreen mode

Explanation:

load_dataset() → Opens a file dialog to select CSV

train_model() → Starts training in a separate thread

Step 9: Make Predictions

def predict_marks(self):
    if not self.model:
        messagebox.showwarning("Model", "Train the model first")
        return

    X = pd.DataFrame([{
        "StudyHours": self.study_var.get(),
        "Attendance": self.attendance_var.get(),
        "PreviousMarks": self.prev_marks_var.get()
    }])

    marks = self.model.predict(X)[0]
    self.result_label.config(text=f"Predicted Final Marks: {marks:.2f}")
Enter fullscreen mode Exit fullscreen mode

Explanation:

Converts inputs into a DataFrame

Uses the trained model to predict marks

Updates label with predicted marks

Step 10: Run the App

Finally, add this to launch the app:

if __name__ == "__main__":
    app = StudentMarksApp()
    app.run()
Enter fullscreen mode Exit fullscreen mode

✅ Congratulations!
You now have a full Student Marks Prediction app with a modern Tkinter UI and ML backend.

Next Steps:

Experiment with different ML algorithms like RandomForest

Add data validation for inputs

Save predictions to a CSV for record-keeping

GitHub: Clone the full project

Top comments (0)