Skip to content

Latest commit

Β 

History

9 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Wine Quality Classification

πŸš€ Multiclass wine quality classification with leakage-free scikit-learn pipelines - compare 9 classifier variants and a majority-voting ensemble under stratified cross-validation

An end-to-end machine learning study on the Wine Quality dataset. Nine classifier variants β€” Decision Tree, k-NN and Random Forest, three hyperparameter settings each β€” are evaluated with stratified 5-fold cross-validation, alongside a VotingClassifier ensemble that aggregates all nine by majority vote.

The project is built around methodological rigour rather than leaderboard chasing: every scaler lives inside a Pipeline so it can never see a test fold, missing data aborts the run, a single seed drives every random component, and the exact library versions are written to disk with the results. A Streamlit walkthrough presents the study, the glossary, the LaTeX tables and the interactive charts.

Python scikit-learn pandas Plotly Streamlit License


🎯 Key Features

  • 🍷 Multiclass target β€” classifies the quality label (scores 3–8) on data/WineQT.csv, an intentionally imbalanced real-world distribution.
  • 🌳 Nine classifier variants β€” DecisionTreeClassifier, KNeighborsClassifier and RandomForestClassifier, three hyperparameter settings each, for a readable family-vs-family comparison.
  • πŸ—³οΈ Majority-voting ensemble β€” a VotingClassifier with voting="hard" over the same nine pipelines, evaluated under identical folds.
  • πŸ”’ Leakage-free by construction β€” MinMaxScaler sits inside a ColumnTransformer within each Pipeline, so it is fitted only on the training fold.
  • πŸ“ Two metrics, deliberately β€” accuracy plus balanced_accuracy (mean per-class recall), because accuracy alone flatters a model on imbalanced wine scores.
  • 🎲 Reproducible runs β€” one seed (RANDOM_STATE = 42) shared by every estimator and by StratifiedKFold, with library versions recorded per run.
  • πŸ“„ Publication-ready export β€” results are written as CSV and LaTeX (pandas.DataFrame.to_latex) for direct inclusion in a report.
  • πŸ“Š Interactive Streamlit app β€” four tabs covering the study description, requirements mapping, EDA and results, including a .tex preview.

πŸ“Š Results & Visualizations

Streamlit dashboard

The Streamlit dashboard showing the project description tab with the study goal, comparison scope and a glossary of terms

Captured from the container built by .tools/docker/docker-compose.yml.

All charts below are produced by python run_experiment.py and written to results/. Interactive Plotly versions of the same figures are saved as standalone HTML under results/wykresy/.

Class distribution Correlation matrix
Distribution of wine quality scores across classes 3-8, showing a strong imbalance toward mid-range scores Correlation matrix of the physicochemical wine features
Model comparison Family aggregates
Cross-validated accuracy and balanced accuracy for each of the nine classifier variants and the voting ensemble Mean and maximum metrics aggregated per model family: DecisionTree, kNN and RandomForest

Numeric results live in results/wyniki_szczegolowe.csv (per-model means and standard deviations) and results/wyniki_agregaty_rodzin.csv (per-family aggregates), with matching .tex tables beside them.


πŸ—οΈ Pipeline

Pipeline diagram: data loading and validation, feature/label split, MinMax scaling inside a Pipeline, stratified 5-fold cross-validation of nine variants plus the voting ensemble, and export of CSV, LaTeX and HTML artifacts

Protection against data leakage

All scaling operations are performed inside a scikit-learn Pipeline object:

Pipeline([
    ("preprocess", ColumnTransformer([("num", MinMaxScaler(), feature_cols)])),
    ("clf", classifier),
])

Thanks to this, MinMaxScaler is fitted exclusively on the training fold β€” it never "sees" the test data before evaluation. Passing a ready Pipeline to cross_validate guarantees this automatically for each of the 5 splits. Details: scikit-learn β€” Common pitfalls.

No missing data

The wczytaj_pelna_ramke function in src/experiment.py calls df.isna().any().any() and raises an exception if it finds missing values β€” the experiment will not run on an incomplete dataset.

Reproducibility

In line with the requirement scikit-learn β€” Getting reproducible results:

  • One fixed seed: RANDOM_STATE = 42 in src/config.py; passed to every classifier (random_state) and to StratifiedKFold(shuffle=True, random_state=RANDOM_STATE).
  • StratifiedKFold with shuffle=True requires a seed β€” without it the sample order after shuffling would differ on every run.
  • The same cv object is passed to each cross_validate call, which guarantees identical splits for all models.
  • The results/wersje_bibliotek.txt file records the versions of scikit-learn, numpy and pandas when the results are generated β€” making it possible to reproduce the environment.

🧩 Models Under Comparison

Family Variants Hyperparameters
DecisionTree dt_gleb_5, dt_gleb_15, dt_gleb_25 max_depth 5 / 15 / 25 with min_samples_leaf 2 / 5 / 10
kNN knn_k5, knn_k11, knn_k21 n_neighbors 5 / 11 / 21, weights uniform / distance / uniform
RandomForest rf_50, rf_100, rf_200 n_estimators 50 / 100 / 200 with max_depth 10 / 15 / 20
Ensemble majority_voting_9 VotingClassifier(voting="hard") over all nine pipelines above

Validation is identical for every row: StratifiedKFold(n_splits=5, shuffle=True, random_state=42), scored on accuracy and balanced_accuracy via cross_validate.


πŸ› οΈ Technology Stack

Machine Learning

  • scikit-learn (>=1.3,<2) β€” Pipeline, ColumnTransformer, MinMaxScaler, the three classifier families, VotingClassifier, StratifiedKFold, cross_validate
  • NumPy (>=1.24,<3) β€” numeric aggregation of fold scores

Data & Reporting

  • pandas (>=2.0,<3) β€” data loading, groupby aggregation, CSV export and to_latex table generation

Visualization & UI

  • Plotly (>=5.18,<6) β€” all four figures, exported as interactive standalone HTML
  • Streamlit (>=1.28,<2) β€” the four-tab study walkthrough

πŸš€ Getting Started

Prerequisites

  • Docker β€” for the containerised path below (recommended)

  • Python 3.10+ (recommended)

  • pip and the ability to create a virtual environment

Run with Docker (recommended)

The container installs the scientific stack, runs the experiment and serves the dashboard in one step β€” no local Python setup and no virtual environment:

docker compose -f .tools/docker/docker-compose.yml up --build

The dashboard is then available at http://localhost:8501.

Generated artefacts (results/, data/) are bind-mounted back to the host, so charts and metrics written inside the container survive it being removed. Stop the stack with:

docker compose -f .tools/docker/docker-compose.yml down

1. Clone the Repository

git clone https://github.com/dawidolko/WineQuality-Classifier-Python.git
cd WineQuality-Classifier-Python

2. Install Dependencies

pip install -r requirements.txt

3. Run

Run the experiment on its own β€” it writes CSV, .tex, wersje_bibliotek.txt and the HTML charts in results/wykresy/:

python run_experiment.py

Launch the Streamlit application:

streamlit run streamlit_app.py

One-command start scripts

The start.sh (Linux/macOS) and start.bat (Windows) scripts run, in order:

  1. venv + pip install -r requirements.txt
  2. python run_experiment.py
  3. streamlit run streamlit_app.py β†’ usually http://localhost:8501
chmod +x start.sh
./start.sh
start.bat

Application tabs

Tab Content
Project description Study goal, experiment flow (what β†’ why β†’ effect), glossary of terms, requirements compliance, LaTeX file preview
Requirements & methodology Table: requirement β†’ implementation in code / files
Dataset (EDA) quality class distribution, correlation matrix, data preview
Classification results CV metric charts, tables, preview and download of results

πŸ“ Project Structure

WineQuality-Classifier-Python/
β”œβ”€β”€ πŸ“Š data/
β”‚   └── WineQT.csv                     # Source dataset (Kaggle / yasserh)
β”œβ”€β”€ 🐍 src/
β”‚   β”œβ”€β”€ config.py                      # Paths, seed (RANDOM_STATE = 42)
β”‚   β”œβ”€β”€ experiment.py                  # Pipeline, CV, ensemble, CSV/LaTeX export
β”‚   └── wykresy.py                     # Plotly charts + HTML export
β”œβ”€β”€ πŸ“ˆ results/                        # Generated artifacts
β”‚   β”œβ”€β”€ img_rozkald.png                # Class distribution
β”‚   β”œβ”€β”€ img_korelacja.png              # Correlation matrix
β”‚   β”œβ”€β”€ img_modele.png                 # Model comparison
β”‚   β”œβ”€β”€ img_agregaty.png               # Family aggregates
β”‚   β”œβ”€β”€ wyniki_szczegolowe.csv/.tex    # Per-model results
β”‚   β”œβ”€β”€ wyniki_agregaty_rodzin.csv/.tex # Per-family aggregates
β”‚   β”œβ”€β”€ wersje_bibliotek.txt           # Library versions for reproducibility
β”‚   └── wykresy/                       # Interactive Plotly HTML charts
β”œβ”€β”€ πŸ“š docs/
β”‚   β”œβ”€β”€ diagrams/pipeline.svg          # Pipeline diagram
β”‚   β”œβ”€β”€ build_pptx.py                  # Presentation generator
β”‚   └── Wine_Quality_Prezentacja.pptx  # Generated presentation
β”œβ”€β”€ ▢️ run_experiment.py                # Command-line entry point
β”œβ”€β”€ πŸ–₯️ streamlit_app.py                 # Web application
β”œβ”€β”€ πŸš€ start.sh / start.bat             # Experiment + Streamlit
β”œβ”€β”€ πŸ“¦ requirements.txt
└── πŸ“– README.md

Repository structure reference

Path Description
data/WineQT.csv Source data
src/config.py Paths, seed
src/experiment.py Pipeline, CV, ensemble, CSV/LaTeX export, chart invocation
src/wykresy.py Plotly charts + HTML export
run_experiment.py Command-line entry point
streamlit_app.py Web application
start.sh / start.bat Experiment + Streamlit
results/ Generated results (CSV, TeX, wykresy/*.html, wersje_bibliotek.txt)

.gitignore

Ignored items include .venv/, Python cache, and IDE files. Generated files in results/ can optionally be added to the ignore list β€” .gitignore contains a ready, commented-out block with instructions.


πŸ“„ License

This project is open source and available under the terms described in the LICENSE file.


πŸ‘¨β€πŸ’» Author

Created by Dawid Olko

About

Comparison of DecisionTree, kNN, and Random Forest classifiers (3 hyperparameter variants each) with a Majority Voting ensemble on the Wine Quality dataset. Stratified 5-fold CV, MinMaxScaler via Pipeline (no data leakage), metrics: accuracy & balanced accuracy. Results exported to LaTeX.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages