DEV Community

Mate Technologies
Mate Technologies

Posted on

🍷 Building WineSense v1.0 – A Beginner-Friendly Machine Learning App in Python

In this step-by-step tutorial, we’ll build WineSense, a desktop application that predicts wine quality using Machine Learning and a clean Tkinter GUI.

This guide is written for beginners and breaks everything into small, easy-to-understand steps.

🚀 What You’ll Build

By the end of this tutorial, you will have:

A Machine Learning model trained on wine data

A desktop app with a modern dark UI

A button to train the model from a CSV file

A form to enter wine properties

Instant wine quality predictions

🧰 Technologies Used

Python

Pandas & NumPy

Scikit-learn (Random Forest)

Tkinter + ttkbootstrap

📁 Project Structure
Wine-quality-prediction-app/

├── app.py
├── winequality.csv
├── requirements.txt
📦 Step 1: Install Dependencies

Create a virtual environment (optional but recommended), then install dependencies:

pip install pandas numpy scikit-learn ttkbootstrap
🧠 Step 2: Creating the Machine Learning Model

We start by defining a class that will:

Load a CSV file

Train a model

Make predictions

2.1 Import Required Libraries

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
Enter fullscreen mode Exit fullscreen mode

2.2 Define the Model Class

class WineQualityModel:
    def __init__(self):
        self.model = RandomForestClassifier(n_estimators=200, random_state=42)
        self.trained = False
        self.accuracy = 0.0
        self.feature_names = []

Enter fullscreen mode Exit fullscreen mode

🔍 Explanation:

RandomForestClassifier is robust and beginner-friendly

trained ensures predictions aren’t made before training

2.3 Training the Model

    def train(self, csv_path):
        data = pd.read_csv(csv_path)


        if 'quality' not in data.columns:
            raise ValueError("CSV must contain a 'quality' column")


        self.feature_names = [c for c in data.columns if c != 'quality']
        X = data[self.feature_names]
        y = data['quality']


        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)
        preds = self.model.predict(X_test)
        self.accuracy = accuracy_score(y_test, preds)
        self.trained = True
Enter fullscreen mode Exit fullscreen mode

📌 What’s happening here?

Load CSV

Separate features and labels

Train the model

Measure accuracy

2.4 Making Predictions

    def predict(self, features):
        if not self.trained:
            raise RuntimeError("Model not trained")


        X = pd.DataFrame([features], columns=self.feature_names)
        return int(self.model.predict(X)[0])
Enter fullscreen mode Exit fullscreen mode

✅ We wrap inputs in a DataFrame so Scikit-learn understands feature names.

🖥 Step 3: Building the GUI (Tkinter + ttkbootstrap)
3.1 Create the App Window

import ttkbootstrap as tb
from ttkbootstrap.constants import *


class WineSenseApp:
    def __init__(self):
        self.root = tb.Window(themename="darkly")
        self.root.title("WineSense v1.0")
        self.root.minsize(900, 600)


        self.model = WineQualityModel()
        self.feature_vars = {}
        self._build_ui()
Enter fullscreen mode Exit fullscreen mode

🎨 ttkbootstrap gives us a modern dark theme with no extra styling effort.

3.2 App Header

tb.Label(
    main,
    text="🍷 WineSense - Quality Prediction",
    font=("Segoe UI", 22, "bold")
).pack(pady=(0, 5))
Enter fullscreen mode Exit fullscreen mode

This creates a bold title at the top of the app.

📊 Step 4: Training the Model from the UI
4.1 Training Button

tb.Button(
    train_frame,
    text="📊 Load Wine CSV & Train Model",
    bootstyle=SUCCESS,
    command=self.train_model
).pack(side=LEFT, padx=5)
Enter fullscreen mode Exit fullscreen mode

4.2 Training Logic (Threaded)

import threading
from tkinter import filedialog


    def train_model(self):
        path = filedialog.askopenfilename(filetypes=[("CSV Files", "*.csv")])
        if not path:
            return


        threading.Thread(target=self._train_thread, args=(path,), daemon=True).start()
Enter fullscreen mode Exit fullscreen mode

🧵 Why threading? So the UI doesn’t freeze while training.

🧪 Step 5: Input Wine Features

We define the wine properties expected by the dataset:

self.features = [
    "fixed acidity",
    "volatile acidity",
    "citric acid",
    "residual sugar",
    "chlorides",
    "free sulfur dioxide",
    "total sulfur dioxide",
    "density",
    "pH",
    "sulphates",
    "alcohol",
]
Enter fullscreen mode Exit fullscreen mode

Each feature gets an input field using DoubleVar().

🔮 Step 6: Predict Wine Quality

    def predict_quality(self):
        if not self.model.trained:
            messagebox.showwarning("Model", "Please train the model first")
            return


        features = [self.feature_vars[f].get() for f in self.features]
        quality = self.model.predict(features)
        self.result_label.config(text=f"Quality: {quality}")
Enter fullscreen mode Exit fullscreen mode

🎯 Enter values → Click Predict → Get instant results.

▶ Step 7: Run the App

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

🧠 What You Learned

✔ How to train an ML model in Python ✔ How to connect ML with a GUI ✔ How to handle CSV input ✔ How to build a real desktop ML app

🔗 Source Code

GitHub Repository: https://github.com/rogers-cyber/python-tiny-tools/tree/main/Wine-quality-prediction-app

🙌 Final Thoughts

This project is perfect for:

Beginners learning Machine Learning

Python developers exploring GUIs

Students building portfolio projects

Happy coding & cheers to smart wine 🍷

I’ve created a Dev.to–style, step-by-step beginner tutorial in the canvas 📘

What this version does well

Breaks the project into clear learning stages

Uses small, focused code blocks instead of dumping the full script

Explains what and why after each block

Written in a friendly Dev.to tone suitable for beginners

Ready to publish with minimal editing

Top comments (0)