In [1]:
import numpy as np
In [2]:
# %%
class QSVCWineClassifier:
"""Quantum Support Vector Classifier for wine quality classification"""
def __init__(self, num_features=4, feature_map='ZZ', reps=2):
self.num_features = num_features
self.reps = reps
self.feature_map_type = feature_map
self.model = None
self.quantum_kernel = None
self.scaler = StandardScaler()
self.label_encoder = LabelEncoder()
self.pca = PCA(n_components=num_features)
self.original_features = 11 # Number of original features
# Quantum components
self.feature_map = None
self.sampler = Sampler()
self._setup_quantum_components()
print(f"QSVC classifier initialized with {num_features} features")
def predict(self, X):
"""Prediction using QSVC or VQC"""
if self.model is None:
raise ValueError("Model is not trained! Call fit() first.")
# If we have 11 features (original), transform them
if X.shape[1] == self.original_features:
X_scaled = self.scaler.transform(X)
X_reduced = self.pca.transform(X_scaled)
else:
X_reduced = X
y_pred_encoded = self.model.predict(X_reduced)
# Ensure correct format
y_pred_encoded = np.atleast_1d(y_pred_encoded)
# Clip predictions to valid class range
y_pred_encoded = np.clip(y_pred_encoded, 0, len(self.label_encoder.classes_) - 1)
try:
y_pred = self.label_encoder.inverse_transform(y_pred_encoded.astype(int))
except ValueError as e:
print(f"Warning: Prediction issue - {e}")
# Fallback - return most frequent class
y_pred = np.array([self.label_encoder.classes_[0]])
return y_pred
def score(self, X, y):
"""Calculate accuracy score"""
y_pred = self.predict(X)
return accuracy_score(y, y_pred)
In [3]:
import pickle
import ipywidgets as widgets
from IPython.display import display, clear_output
import warnings
warnings.filterwarnings('ignore')
print("Loading model...")
# Load model
loaded_qwc = None
try:
with open('qsvc_wine_model.pkl', 'rb') as f:
loaded_data = pickle.load(f)
loaded_qwc = loaded_data['quantum_classifier']
print("Model successfully loaded!")
except FileNotFoundError:
print("File 'qsvc_wine_model.pkl' not found!")
except Exception as e:
print(f"Error loading model: {e}")
print()
print("=" * 50)
print(" WINE QUALITY CLASSIFIER")
print("=" * 50)
print()
# Create sliders
fixed_acidity_slider = widgets.FloatSlider(
value=7.4, min=4.6, max=15.0, step=0.1,
description='Fixed Acidity (g/L):',
style={'description_width': '170px'}
)
volatile_acidity_slider = widgets.FloatSlider(
value=0.7, min=0.21, max=1.33, step=0.01,
description='Volatile Acidity (g/L):',
style={'description_width': '170px'}
)
citric_acid_slider = widgets.FloatSlider(
value=0.0, min=0.0, max=1.0, step=0.01,
description='Citric Acid (g/L):',
style={'description_width': '170px'}
)
residual_sugar_slider = widgets.FloatSlider(
value=1.9, min=1.2, max=10.7, step=0.1,
description='Residual Sugar (g/L):',
style={'description_width': '170px'}
)
chlorides_slider = widgets.FloatSlider(
value=0.076, min=0.039, max=0.610, step=0.001,
description='Chlorides (g/L):',
style={'description_width': '170px'}
)
free_sulfur_dioxide_slider = widgets.FloatSlider(
value=11.0, min=3.0, max=52.0, step=1.0,
description='Free SO₂ (mg/L):',
style={'description_width': '170px'}
)
total_sulfur_dioxide_slider = widgets.FloatSlider(
value=34.0, min=8.0, max=153.0, step=1.0,
description='Total SO₂ (mg/L):',
style={'description_width': '170px'}
)
density_slider = widgets.FloatSlider(
value=0.9978, min=0.992, max=1.000, step=0.0001,
description='Density (g/cm³):',
style={'description_width': '170px'}
)
pH_slider = widgets.FloatSlider(
value=3.51, min=2.74, max=3.90, step=0.01,
description='pH (-):',
style={'description_width': '170px'}
)
sulphates_slider = widgets.FloatSlider(
value=0.56, min=0.33, max=2.0, step=0.01,
description='Sulphates (g/L):',
style={'description_width': '170px'}
)
alcohol_slider = widgets.FloatSlider(
value=12.0, min=9.0, max=14.0, step=0.1,
description='Alcohol (% vol):',
style={'description_width': '170px'}
)
# Buttons
predict_button = widgets.Button(
description='Evaluate Wine Quality',
button_style='danger',
layout=widgets.Layout(width='200px', height='40px')
)
reset_button = widgets.Button(
description='Reset to Default',
button_style='info',
layout=widgets.Layout(width='150px', height='40px')
)
# Output for results
output = widgets.Output()
def predict_wine_quality(button):
"""Function for wine quality prediction"""
with output:
clear_output(wait=True)
if loaded_qwc is None:
print("Model is not loaded!")
return
# Get values from all sliders
test_sample = [
fixed_acidity_slider.value,
volatile_acidity_slider.value,
citric_acid_slider.value,
residual_sugar_slider.value,
chlorides_slider.value,
free_sulfur_dioxide_slider.value,
total_sulfur_dioxide_slider.value,
density_slider.value,
pH_slider.value,
sulphates_slider.value,
alcohol_slider.value
]
try:
# Prediction
prediction = loaded_qwc.predict(np.array([test_sample]))
quality_score = prediction[0]
print("=" * 50)
print(f" WINE QUALITY: {quality_score} points")
# Interpretation
if quality_score >= 8:
print(" EXCELLENT QUALITY!")
rating = "★★★★★"
desc = "This wine is truly exceptional!"
elif quality_score >= 7:
print(" VERY GOOD QUALITY!")
rating = "★★★★☆"
desc = "High-quality wine with excellent characteristics"
elif quality_score >= 6:
print(" GOOD QUALITY")
rating = "★★★☆☆"
desc = "Solid wine with pleasant properties"
elif quality_score >= 5:
print(" AVERAGE QUALITY")
rating = "★★☆☆☆"
desc = "Standard wine for everyday consumption"
elif quality_score >= 4:
print(" BELOW AVERAGE QUALITY")
rating = "★☆☆☆☆"
desc = "Wine with some deficiencies"
else:
print(" POOR QUALITY")
rating = "☆☆☆☆☆"
desc = "Wine with significant problems"
print(f" {rating}")
print(f" {desc}")
print("=" * 50)
print()
print("Input parameters:")
print(f" Fixed Acidity: {test_sample[0]:.2f}")
print(f" Volatile Acidity: {test_sample[1]:.3f}")
print(f" Citric Acid: {test_sample[2]:.3f}")
print(f" Residual Sugar: {test_sample[3]:.1f}")
print(f" Chlorides: {test_sample[4]:.3f}")
print(f" Free SO₂: {test_sample[5]:.0f}")
print(f" Total SO₂: {test_sample[6]:.0f}")
print(f" Density: {test_sample[7]:.4f}")
print(f" pH: {test_sample[8]:.2f}")
print(f" Sulphates: {test_sample[9]:.2f}")
print(f" Alcohol: {test_sample[10]:.1f}%")
except Exception as e:
print(f"ERROR: {e}")
def reset_values(button):
"""Reset to original values"""
with output:
clear_output(wait=True)
print("Resetting to default values...")
# Set original values from test_sample
fixed_acidity_slider.value = 7.4
volatile_acidity_slider.value = 0.7
citric_acid_slider.value = 0.0
residual_sugar_slider.value = 1.9
chlorides_slider.value = 0.076
free_sulfur_dioxide_slider.value = 11.0
total_sulfur_dioxide_slider.value = 34.0
density_slider.value = 0.9978
pH_slider.value = 3.51
sulphates_slider.value = 0.56
alcohol_slider.value = 12.0
# Connect functions to buttons
predict_button.on_click(predict_wine_quality)
reset_button.on_click(reset_values)
# Display interface
print("Set parameters and click 'Evaluate Wine Quality':")
print()
# Display sliders in groups
print("Acidity:")
display(fixed_acidity_slider)
display(volatile_acidity_slider)
display(citric_acid_slider)
display(pH_slider)
print()
print("Sugar and Salts:")
display(residual_sugar_slider)
display(chlorides_slider)
display(sulphates_slider)
print()
print("Sulfur Dioxide:")
display(free_sulfur_dioxide_slider)
display(total_sulfur_dioxide_slider)
print()
print("Physical Properties:")
display(density_slider)
display(alcohol_slider)
print()
print("Controls:")
display(widgets.HBox([predict_button, reset_button]))
print()
print("Results:")
display(output)
# Initial message
with output:
print("Wine classifier is ready!")
print("Adjust slider values and click 'Evaluate Wine Quality'")
if loaded_qwc is not None:
print("Model is loaded and functional")
else:
print("WARNING: Model was not loaded!")
print()
print("Wine classifier is ready to use!")
Loading model...
Model successfully loaded!
==================================================
WINE QUALITY CLASSIFIER
==================================================
Set parameters and click 'Evaluate Wine Quality':
Acidity:
FloatSlider(value=7.4, description='Fixed Acidity (g/L):', max=15.0, min=4.6, style=SliderStyle(description_wi…
FloatSlider(value=0.7, description='Volatile Acidity (g/L):', max=1.33, min=0.21, step=0.01, style=SliderStyle…
FloatSlider(value=0.0, description='Citric Acid (g/L):', max=1.0, step=0.01, style=SliderStyle(description_wid…
FloatSlider(value=3.51, description='pH (-):', max=3.9, min=2.74, step=0.01, style=SliderStyle(description_wid…
Sugar and Salts:
FloatSlider(value=1.9, description='Residual Sugar (g/L):', max=10.7, min=1.2, style=SliderStyle(description_w…
FloatSlider(value=0.076, description='Chlorides (g/L):', max=0.61, min=0.039, step=0.001, style=SliderStyle(de…
FloatSlider(value=0.56, description='Sulphates (g/L):', max=2.0, min=0.33, step=0.01, style=SliderStyle(descri…
Sulfur Dioxide:
FloatSlider(value=11.0, description='Free SO₂ (mg/L):', max=52.0, min=3.0, step=1.0, style=SliderStyle(descrip…
FloatSlider(value=34.0, description='Total SO₂ (mg/L):', max=153.0, min=8.0, step=1.0, style=SliderStyle(descr…
Physical Properties:
FloatSlider(value=0.9978, description='Density (g/cm³):', max=1.0, min=0.992, step=0.0001, style=SliderStyle(d…
FloatSlider(value=12.0, description='Alcohol (% vol):', max=14.0, min=9.0, style=SliderStyle(description_width…
Controls:
HBox(children=(Button(button_style='danger', description='Evaluate Wine Quality', layout=Layout(height='40px',…
Results:
Output()
Wine classifier is ready to use!
In [5]:
#with ipywidgets like this
from IPython.display import Image
Image(url='https://raw.githubusercontent.com/bluemoondom/quantum_qsvc_train_red_wine_classifier/refs/heads/main/wine_classifier.png')
Out[5]:
In [ ]: