Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
244 changes: 120 additions & 124 deletions examples/quantum/classification.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,13 @@

from hdlib.model import ClassificationModel, QuantumClassificationModel

# Qiskit imports below are only required for the QSVC and VQC baselines,
# which are currently disabled. Re-enable them together with the QSVC/VQC
# code blocks if you want to compare against those models again.
# from qiskit_algorithms.optimizers import COBYLA
# from qiskit.circuit.library import ZFeatureMap, ZZFeatureMap, RealAmplitudes
# from qiskit_machine_learning.algorithms.classifiers import VQC, QSVC
# from qiskit_machine_learning.state_fidelities import ComputeUncompute
# from qiskit_machine_learning.kernels import FidelityQuantumKernel
# from qiskit.primitives import StatevectorSampler
# Qiskit imports required for the QSVC and VQC baselines.
from qiskit_algorithms.optimizers import COBYLA
from qiskit.circuit.library import ZFeatureMap, ZZFeatureMap, RealAmplitudes
from qiskit_machine_learning.algorithms.classifiers import VQC, QSVC
from qiskit_machine_learning.state_fidelities import ComputeUncompute
from qiskit_machine_learning.kernels import FidelityQuantumKernel
from qiskit.primitives import StatevectorSampler


# Configuration for Hardware (Optional)
Expand Down Expand Up @@ -255,64 +253,64 @@ def _run_fold_body(fold_num, train_index, test_index, X_cv_pool, y_cv_pool,

n_features = X_train_fold_np.shape[1]

# --- QSVC Model (QSVM) --- (disabled)
# print("\nTraining QSVC Model (QSVM)...")
# start_time_qsvc = time.perf_counter()
#
# feature_map_qsvc = ZZFeatureMap(feature_dimension=n_features, reps=1, entanglement='linear')
#
# sampler = StatevectorSampler()
# fidelity = ComputeUncompute(sampler=sampler)
# qsvc_kernel = FidelityQuantumKernel(fidelity=fidelity, feature_map=feature_map_qsvc)
#
# qsvc = QSVC(quantum_kernel=qsvc_kernel)
# qsvc.fit(X_train_fold_np, y_train_fold_np)
#
# print("Evaluating QSVC Model...")
# y_pred_qsvc = qsvc.predict(X_test_fold_np)
# scores_qsvc = qsvc.decision_function(X_test_fold_np)
#
# end_time_qsvc = time.perf_counter()
#
# fold_time_qsvc = end_time_qsvc - start_time_qsvc
# fold_report_qsvc = classification_report(y_test_fold, y_pred_qsvc, target_names=["Digit 6", "Digit 3"], output_dict=True, zero_division=0)
# fold_matrix_qsvc = confusion_matrix(y_test_fold, y_pred_qsvc, labels=[0, 1])
#
# scores_qsvc_list = scores_qsvc.tolist()
# fold_roc_data_qsvc = []
# for true_label, score_for_class_1 in zip(y_test_fold, scores_qsvc_list):
# fold_roc_data_qsvc.append((true_label, float(score_for_class_1)))

# --- VQC Model (QNN) --- (disabled)
# print("\nTraining VQC Model (QNN)...")
# start_time_vqc = time.perf_counter()
#
# feature_map_vqc = ZFeatureMap(feature_dimension=n_features, reps=1)
# ansatz_vqc = RealAmplitudes(num_qubits=n_features, reps=3)
# optimizer_vqc = COBYLA(maxiter=100)
#
# vqc = VQC(
# feature_map=feature_map_vqc,
# ansatz=ansatz_vqc,
# optimizer=optimizer_vqc
# )
#
# vqc.fit(X_train_fold_np, y_train_fold_np)
#
# print("Evaluating VQC Model...")
# y_pred_vqc = vqc.predict(X_test_fold_np)
# scores_vqc_raw = vqc.neural_network.forward(X_test_fold_np, vqc.weights)
#
# end_time_vqc = time.perf_counter()
#
# fold_time_vqc = end_time_vqc - start_time_vqc
# fold_report_vqc = classification_report(y_test_fold, y_pred_vqc, target_names=["Digit 6", "Digit 3"], output_dict=True, zero_division=0)
# fold_matrix_vqc = confusion_matrix(y_test_fold, y_pred_vqc, labels=[0, 1])
#
# scores_vqc_class1 = [prob[1] for prob in scores_vqc_raw.tolist()]
# fold_roc_data_vqc = []
# for true_label, score_for_class_1 in zip(y_test_fold, scores_vqc_class1):
# fold_roc_data_vqc.append((true_label, float(score_for_class_1)))
# --- QSVC Model (QSVM) ---
print("\nTraining QSVC Model (QSVM)...")
start_time_qsvc = time.perf_counter()

feature_map_qsvc = ZZFeatureMap(feature_dimension=n_features, reps=1, entanglement='linear')

sampler = StatevectorSampler()
fidelity = ComputeUncompute(sampler=sampler)
qsvc_kernel = FidelityQuantumKernel(fidelity=fidelity, feature_map=feature_map_qsvc)

qsvc = QSVC(quantum_kernel=qsvc_kernel)
qsvc.fit(X_train_fold_np, y_train_fold_np)

print("Evaluating QSVC Model...")
y_pred_qsvc = qsvc.predict(X_test_fold_np)
scores_qsvc = qsvc.decision_function(X_test_fold_np)

end_time_qsvc = time.perf_counter()

fold_time_qsvc = end_time_qsvc - start_time_qsvc
fold_report_qsvc = classification_report(y_test_fold, y_pred_qsvc, target_names=["Digit 6", "Digit 3"], output_dict=True, zero_division=0)
fold_matrix_qsvc = confusion_matrix(y_test_fold, y_pred_qsvc, labels=[0, 1])

scores_qsvc_list = scores_qsvc.tolist()
fold_roc_data_qsvc = []
for true_label, score_for_class_1 in zip(y_test_fold, scores_qsvc_list):
fold_roc_data_qsvc.append((true_label, float(score_for_class_1)))

# --- VQC Model (QNN) ---
print("\nTraining VQC Model (QNN)...")
start_time_vqc = time.perf_counter()

feature_map_vqc = ZFeatureMap(feature_dimension=n_features, reps=1)
ansatz_vqc = RealAmplitudes(num_qubits=n_features, reps=3)
optimizer_vqc = COBYLA(maxiter=100)

vqc = VQC(
feature_map=feature_map_vqc,
ansatz=ansatz_vqc,
optimizer=optimizer_vqc
)

vqc.fit(X_train_fold_np, y_train_fold_np)

print("Evaluating VQC Model...")
y_pred_vqc = vqc.predict(X_test_fold_np)
scores_vqc_raw = vqc.neural_network.forward(X_test_fold_np, vqc.weights)

end_time_vqc = time.perf_counter()

fold_time_vqc = end_time_vqc - start_time_vqc
fold_report_vqc = classification_report(y_test_fold, y_pred_vqc, target_names=["Digit 6", "Digit 3"], output_dict=True, zero_division=0)
fold_matrix_vqc = confusion_matrix(y_test_fold, y_pred_vqc, labels=[0, 1])

scores_vqc_class1 = [prob[1] for prob in scores_vqc_raw.tolist()]
fold_roc_data_vqc = []
for true_label, score_for_class_1 in zip(y_test_fold, scores_vqc_class1):
fold_roc_data_vqc.append((true_label, float(score_for_class_1)))

# --- Checkpoint Saving ---
fold_data = {
Expand All @@ -334,17 +332,15 @@ def _run_fold_body(fold_num, train_index, test_index, X_cv_pool, y_cv_pool,
'q_final_epoch': int(epochs),
'q_final_error': float(error_rate),

# VQC/QSVC entries are disabled; re-enable together with the
# corresponding model blocks above.
# 'vqc_report': fold_report_vqc,
# 'vqc_matrix': fold_matrix_vqc.tolist(),
# 'vqc_time': fold_time_vqc,
# 'vqc_roc_data': fold_roc_data_vqc,
#
# 'qsvc_report': fold_report_qsvc,
# 'qsvc_matrix': fold_matrix_qsvc.tolist(),
# 'qsvc_time': fold_time_qsvc,
# 'qsvc_roc_data': fold_roc_data_qsvc,
'vqc_report': fold_report_vqc,
'vqc_matrix': fold_matrix_vqc.tolist(),
'vqc_time': fold_time_vqc,
'vqc_roc_data': fold_roc_data_vqc,

'qsvc_report': fold_report_qsvc,
'qsvc_matrix': fold_matrix_qsvc.tolist(),
'qsvc_time': fold_time_qsvc,
'qsvc_roc_data': fold_roc_data_qsvc,
}

with open(checkpoint_file, 'w') as f:
Expand Down Expand Up @@ -481,24 +477,24 @@ def remove_contradicting(Xs, ys):
classical_matrices = list()
quantum_reports = list()
quantum_matrices = list()
# vqc_reports = list()
# vqc_matrices = list()
# qsvc_reports = list()
# qsvc_matrices = list()
vqc_reports = list()
vqc_matrices = list()
qsvc_reports = list()
qsvc_matrices = list()

# Lists to store timing for each fold
classical_10k_times = list()
classical_times = list()
quantum_times = list()
# vqc_times = list()
# qsvc_times = list()
vqc_times = list()
qsvc_times = list()

# New lists to store (true_label, score) tuples for ROC curve data
classical_10k_roc_data = list()
classical_roc_data = list()
quantum_roc_data = list()
# vqc_roc_data = list()
# qsvc_roc_data = list()
vqc_roc_data = list()
qsvc_roc_data = list()

dimensionality = 32

Expand Down Expand Up @@ -566,24 +562,24 @@ def _render_progress(completed, total, width=40):
quantum_times.append(fold_data['q_time'])
quantum_roc_data.extend(fold_data['q_roc_data'])

# vqc_reports.append(fold_data['vqc_report'])
# vqc_matrices.append(np.array(fold_data['vqc_matrix']))
# vqc_times.append(fold_data['vqc_time'])
# vqc_roc_data.extend(fold_data['vqc_roc_data'])
vqc_reports.append(fold_data['vqc_report'])
vqc_matrices.append(np.array(fold_data['vqc_matrix']))
vqc_times.append(fold_data['vqc_time'])
vqc_roc_data.extend(fold_data['vqc_roc_data'])

# qsvc_reports.append(fold_data['qsvc_report'])
# qsvc_matrices.append(np.array(fold_data['qsvc_matrix']))
# qsvc_times.append(fold_data['qsvc_time'])
# qsvc_roc_data.extend(fold_data['qsvc_roc_data'])
qsvc_reports.append(fold_data['qsvc_report'])
qsvc_matrices.append(np.array(fold_data['qsvc_matrix']))
qsvc_times.append(fold_data['qsvc_time'])
qsvc_roc_data.extend(fold_data['qsvc_roc_data'])

# --- 5. Cross-Validation Results Summary ---
print("\n--- 5. Cross-Validation Results Summary ---")

print_cv_summary("Classical Model (D=10000)", classical_10k_reports, classical_10k_matrices, classical_10k_times, N_SPLITS)
print_cv_summary(f"Classical Model (D={dimensionality})", classical_reports, classical_matrices, classical_times, N_SPLITS)
print_cv_summary(f"Quantum Model (D={dimensionality})", quantum_reports, quantum_matrices, quantum_times, N_SPLITS)
# print_cv_summary("VQC Model (QNN)", vqc_reports, vqc_matrices, vqc_times, N_SPLITS)
# print_cv_summary("QSVC Model (QSVM)", qsvc_reports, qsvc_matrices, qsvc_times, N_SPLITS)
print_cv_summary("VQC Model (QNN)", vqc_reports, vqc_matrices, vqc_times, N_SPLITS)
print_cv_summary("QSVC Model (QSVM)", qsvc_reports, qsvc_matrices, qsvc_times, N_SPLITS)

# --- 6. ROC Curve Data Points ---
print("\n--- 6. ROC Curve Data Points (True Label, Score) ---")
Expand All @@ -600,13 +596,13 @@ def _render_progress(completed, total, width=40):
print("[(True Label, Score for Class 1), ...]")
print(quantum_roc_data)

# print(f"\nVQC Model (QNN) ROC Data ({len(vqc_roc_data)} points):")
# print("[(True Label, Score for Class 1), ...]")
# print(vqc_roc_data)
#
# print(f"\nQSVC Model (QSVM) ROC Data ({len(qsvc_roc_data)} points):")
# print("[(True Label, Score for Class 1), ...]")
# print(qsvc_roc_data)
print(f"\nVQC Model (QNN) ROC Data ({len(vqc_roc_data)} points):")
print("[(True Label, Score for Class 1), ...]")
print(vqc_roc_data)

print(f"\nQSVC Model (QSVM) ROC Data ({len(qsvc_roc_data)} points):")
print("[(True Label, Score for Class 1), ...]")
print(qsvc_roc_data)

# --- 7. Calculate Exact ROC Plotting Points ---
print("\n--- 7. Exact (FPR, TPR) Points for Plotting ---")
Expand Down Expand Up @@ -651,27 +647,27 @@ def _render_progress(completed, total, width=40):
print("[(FPR, TPR), ...]")
print(roc_points_q)

# --- VQC Model (QNN) --- (disabled)
# if vqc_roc_data:
# y_true_vqc = [item[0] for item in vqc_roc_data]
# y_scores_vqc = [item[1] for item in vqc_roc_data]
# fpr_vqc, tpr_vqc, _ = roc_curve(y_true_vqc, y_scores_vqc)
# roc_points_vqc = list(zip(fpr_vqc, tpr_vqc))
#
# print(f"\nVQC Model (QNN) ROC Plot Points ({len(roc_points_vqc)} points):")
# print("[(FPR, TPR), ...]")
# print(roc_points_vqc)

# --- QSVC Model (QSVM) --- (disabled)
# if qsvc_roc_data:
# y_true_qsvc = [item[0] for item in qsvc_roc_data]
# y_scores_qsvc = [item[1] for item in qsvc_roc_data]
# fpr_qsvc, tpr_qsvc, _ = roc_curve(y_true_qsvc, y_scores_qsvc)
# roc_points_qsvc = list(zip(fpr_qsvc, tpr_qsvc))
#
# print(f"\nQSVC Model (QSVM) ROC Plot Points ({len(roc_points_qsvc)} points):")
# print("[(FPR, TPR), ...]")
# print(roc_points_qsvc)
# --- VQC Model (QNN) ---
if vqc_roc_data:
y_true_vqc = [item[0] for item in vqc_roc_data]
y_scores_vqc = [item[1] for item in vqc_roc_data]
fpr_vqc, tpr_vqc, _ = roc_curve(y_true_vqc, y_scores_vqc)
roc_points_vqc = list(zip(fpr_vqc, tpr_vqc))

print(f"\nVQC Model (QNN) ROC Plot Points ({len(roc_points_vqc)} points):")
print("[(FPR, TPR), ...]")
print(roc_points_vqc)

# --- QSVC Model (QSVM) ---
if qsvc_roc_data:
y_true_qsvc = [item[0] for item in qsvc_roc_data]
y_scores_qsvc = [item[1] for item in qsvc_roc_data]
fpr_qsvc, tpr_qsvc, _ = roc_curve(y_true_qsvc, y_scores_qsvc)
roc_points_qsvc = list(zip(fpr_qsvc, tpr_qsvc))

print(f"\nQSVC Model (QSVM) ROC Plot Points ({len(roc_points_qsvc)} points):")
print("[(FPR, TPR), ...]")
print(roc_points_qsvc)

except Exception as e:
print(f"\nCould not calculate ROC curve points: {e}")
Expand Down