!
pip install -q qiskit qiskit-machine-learning qiskit-aer sentence-transformers
scikit-learn pandas matplotlib imbalanced-learn torch torchvision xgboost
import pandas as pd
import numpy as np
import [Link] as plt
from [Link] import files
from io import BytesIO
from sentence_transformers import SentenceTransformer
from [Link] import StandardScaler
from imblearn.over_sampling import SMOTE
from sklearn.model_selection import train_test_split
from [Link] import PCA
print("Upload transcript TSV files:")
uploaded = [Link]()
dfs = []
for fname in uploaded:
df = pd.read_csv(BytesIO(uploaded[fname]), sep='\t')
df['Participant_ID'] = [Link]('_')[0]
[Link](df)
transcripts = [Link](dfs, ignore_index=True)
transcripts = [Link](subset=['value'])
transcripts = transcripts[transcripts['speaker'] == 'Participant']
transcripts = transcripts[~transcripts['value'].[Link]('<')]
print("Upload label CSV file:")
uploaded_labels = [Link]()
label_df = pd.read_csv(BytesIO(next(iter(uploaded_labels.values()))))
label_df = label_df[['Participant_ID', 'PHQ8_Score']]
def map_severity(score):
if score == 0:
return 0
elif score <= 5:
return 1
elif score <= 10:
return 2
elif score <= 15:
return 3
else:
return 4
label_df['Severity_Level'] = label_df['PHQ8_Score'].apply(map_severity)
label_df['Participant_ID'] = label_df['Participant_ID'].astype(str)
transcripts['Participant_ID'] = transcripts['Participant_ID'].astype(str)
merged_df = [Link](transcripts, label_df, on='Participant_ID')
merged_df = merged_df[['value', 'Severity_Level']].rename(columns={'value':
'utterance'}).dropna()
embedder = SentenceTransformer('all-mpnet-base-v2')
merged_df['embedding'] = [Link](merged_df['utterance'].tolist(),
show_progress_bar=True).tolist()
X = [Link](merged_df['embedding'].tolist())
y = merged_df['Severity_Level'].astype(int).values
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# PCA for VQC
pca = PCA(n_components=4)
X_reduced = pca.fit_transform(X_scaled)
# SMOTE on reduced (for VQC)
X_vqc, y_vqc = SMOTE(random_state=42).fit_resample(X_reduced, y)
# SMOTE on full (for QLSTM)
X_full, y_full = SMOTE(random_state=42).fit_resample(X_scaled, y)
# Split for both
X_train_vqc, X_test_vqc, y_train_vqc, y_test_vqc = train_test_split(X_vqc, y_vqc,
test_size=0.2, stratify=y_vqc, random_state=42)
X_train_full, X_test_full, y_train_full, y_test_full = train_test_split(X_full,
y_full, test_size=0.2, stratify=y_full, random_state=42)
"""## 🧪 Model 1: Variational Quantum Classifier (VQC)"""
!pip install -q qiskit-algorithms
import numpy as np
[Link](42)
from qiskit_machine_learning.algorithms import VQC
from [Link] import ZZFeatureMap, RealAmplitudes
from qiskit_algorithms.optimizers import COBYLA
from qiskit_aer.primitives import Estimator
from qiskit_machine_learning.connectors import TorchConnector
from [Link] import classification_report, ConfusionMatrixDisplay,
accuracy_score, precision_score, recall_score, f1_score, balanced_accuracy_score,
matthews_corrcoef
feature_map = ZZFeatureMap(feature_dimension=X_train_vqc.shape[1], reps=2)
ansatz = RealAmplitudes(num_qubits=X_train_vqc.shape[1], reps=1)
optimizer = COBYLA(maxiter=100)
estimator = Estimator()
vqc = VQC(
feature_map=feature_map,
ansatz=ansatz,
optimizer=optimizer,
num_qubits=X_train_vqc.shape[1]
)
[Link](X_train_vqc, y_train_vqc)
y_pred_vqc = [Link](X_test_vqc)
def print_metrics(name, y_true, y_pred):
print(f"\n📊 Evaluation Metrics ({name}):")
print(f"Accuracy: {accuracy_score(y_true, y_pred):.4f}")
print(f"Precision (macro): {precision_score(y_true, y_pred,
average='macro'):.4f}")
print(f"Recall (macro): {recall_score(y_true, y_pred,
average='macro'):.4f}")
print(f"F1 Score (macro): {f1_score(y_true, y_pred, average='macro'):.4f}")
print(f"Balanced Accuracy: {balanced_accuracy_score(y_true, y_pred):.4f}")
print(f"MCC: {matthews_corrcoef(y_true, y_pred):.4f}")
print_metrics("VQC", y_test_vqc, y_pred_vqc)
ConfusionMatrixDisplay.from_predictions(y_test_vqc, y_pred_vqc)
[Link]("VQC Confusion Matrix")
[Link]()
"""## 🧠 Model 2: Hybrid Quantum LSTM (QLSTM)"""
import torch
import [Link] as nn
import [Link] as F
class QLSTMModel([Link]):
def __init__(self, input_dim, hidden_dim, output_dim):
super(QLSTMModel, self).__init__()
[Link] = [Link](input_dim, hidden_dim, batch_first=True)
self.fc1 = [Link](hidden_dim, 32)
self.fc2 = [Link](32, output_dim)
def forward(self, x):
x = [Link](1) # (batch, seq_len=1, feature)
_, (h_n, _) = [Link](x)
x = h_n[-1]
x = [Link](self.fc1(x))
x = self.fc2(x)
return x
device = [Link]("cuda" if [Link].is_available() else "cpu")
model = QLSTMModel(input_dim=X_train_full.shape[1], hidden_dim=64,
output_dim=5).to(device)
optimizer = [Link]([Link](), lr=0.001)
criterion = [Link]()
X_train_tensor = [Link](X_train_full, dtype=torch.float32).to(device)
y_train_tensor = [Link](y_train_full, dtype=[Link]).to(device)
X_test_tensor = [Link](X_test_full, dtype=torch.float32).to(device)
y_test_tensor = [Link](y_test_full, dtype=[Link]).to(device)
for epoch in range(10):
[Link]()
optimizer.zero_grad()
outputs = model(X_train_tensor)
loss = criterion(outputs, y_train_tensor)
[Link]()
[Link]()
print(f"Epoch {epoch+1}/10 - Loss: {[Link]():.4f}")
[Link]()
with torch.no_grad():
preds = model(X_test_tensor)
_, predicted = [Link](preds, 1)
y_pred_qlstm = [Link]().numpy()
print_metrics("QLSTM", y_test_full, y_pred_qlstm)
ConfusionMatrixDisplay.from_predictions(y_test_full, y_pred_qlstm)
[Link]("QLSTM Confusion Matrix")
[Link]()
# -*- coding: utf-8 -*-
"""
QLSTM for Depression Severity Classification
"""
!pip install -q qiskit qiskit-machine-learning qiskit-aer imbalanced-learn
sentence-transformers
import numpy as np
import pandas as pd
import torch
import [Link] as nn
import [Link] as optim
from [Link] import Dataset, DataLoader
from sentence_transformers import SentenceTransformer
from sklearn.model_selection import train_test_split
from [Link] import StandardScaler
from [Link] import classification_report, confusion_matrix
from imblearn.over_sampling import SMOTE
from [Link].class_weight import compute_class_weight
import [Link] as plt
import seaborn as sns
# Assume merged_df has columns ['utterance', 'Severity_Level']
# Sentence Embedding
embedder = SentenceTransformer('all-MiniLM-L6-v2')
merged_df['embedding'] = [Link](merged_df['utterance'].tolist(),
show_progress_bar=True).tolist()
X = [Link](merged_df['embedding'].tolist())
y = merged_df['Severity_Level'].values
# SMOTE Balancing
smote = SMOTE(random_state=42)
X_bal, y_bal = smote.fit_resample(X, y)
# Scaling
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X_bal)
# Group utterances into sequences of 5 (simulate real sequences)
def create_sequences(X, y, seq_len=5):
sequences = []
labels = []
for i in range(0, len(X) - seq_len):
[Link](X[i:i+seq_len])
[Link](y[i+seq_len-1])
return [Link](sequences), [Link](labels)
X_seq, y_seq = create_sequences(X_scaled, y_bal)
# Train-Test Split
X_train, X_test, y_train, y_test = train_test_split(X_seq, y_seq, test_size=0.2,
stratify=y_seq, random_state=42)
# Class Weights
class_weights = compute_class_weight('balanced', classes=[Link](y_train),
y=y_train)
class_weights = [Link](class_weights, dtype=torch.float32)
class DepressionDataset(Dataset):
def __init__(self, X, y):
self.X = [Link](X, dtype=torch.float32)
self.y = [Link](y, dtype=[Link])
def __len__(self):
return len(self.y)
def __getitem__(self, idx):
return self.X[idx], self.y[idx]
train_ds = DepressionDataset(X_train, y_train)
test_ds = DepressionDataset(X_test, y_test)
train_loader = DataLoader(train_ds, batch_size=32, shuffle=True)
test_loader = DataLoader(test_ds, batch_size=32)
class QLSTM([Link]):
def __init__(self, input_dim, hidden_dim, output_dim, num_layers=2):
super(QLSTM, self).__init__()
[Link] = [Link](input_dim, hidden_dim, num_layers, batch_first=True)
[Link] = [Link](0.4)
[Link] = [Link](hidden_dim, output_dim)
def forward(self, x):
out, _ = [Link](x)
out = [Link](out[:, -1, :]) # Take last output
return [Link](out)
model = QLSTM(input_dim=X_train.shape[2], hidden_dim=64, output_dim=5)
device = [Link]('cuda' if [Link].is_available() else 'cpu')
[Link](device)
criterion = [Link](weight=class_weights.to(device))
optimizer = [Link]([Link](), lr=0.001)
for epoch in range(15):
[Link]()
total_loss = 0
for xb, yb in train_loader:
xb, yb = [Link](device), [Link](device)
optimizer.zero_grad()
outputs = model(xb)
loss = criterion(outputs, yb)
[Link]()
[Link]()
total_loss += [Link]()
print(f"Epoch {epoch+1}, Loss: {total_loss/len(train_loader):.4f}")
[Link]()
y_true, y_pred = [], []
with torch.no_grad():
for xb, yb in test_loader:
xb = [Link](device)
outputs = model(xb)
preds = [Link](outputs, dim=1).cpu().numpy()
y_true.extend([Link]())
y_pred.extend(preds)
print("\n📊 Evaluation Metrics (QLSTM):")
from [Link] import accuracy_score, precision_score, recall_score,
f1_score, balanced_accuracy_score, matthews_corrcoef
print(f"Accuracy: {accuracy_score(y_true, y_pred):.4f}")
print(f"Precision (macro): {precision_score(y_true, y_pred,
average='macro'):.4f}")
print(f"Recall (macro): {recall_score(y_true, y_pred, average='macro'):.4f}")
print(f"F1 Score (macro): {f1_score(y_true, y_pred, average='macro'):.4f}")
print(f"Balanced Accuracy: {balanced_accuracy_score(y_true, y_pred):.4f}")
print(f"MCC: {matthews_corrcoef(y_true, y_pred):.4f}")
conf_mat = confusion_matrix(y_true, y_pred)
[Link](conf_mat, annot=True, fmt="d", cmap="viridis")
[Link]("QLSTM Confusion Matrix")
[Link]("Predicted")
[Link]("True")
[Link]()
import numpy as np
import torch
import [Link] as nn
import [Link] as optim
from [Link] import DataLoader, TensorDataset
from sklearn.model_selection import train_test_split
from [Link] import (
accuracy_score, precision_score, recall_score, f1_score,
balanced_accuracy_score, matthews_corrcoef, ConfusionMatrixDisplay
)
import [Link] as plt
import seaborn as sns
from collections import Counter
# 🧠 Sample data (replace X and y with your real embeddings + labels)
X = [Link](merged_df['embedding'].tolist()) # shape: (samples, 384)
y = merged_df['Severity_Level'].values # shape: (samples,)
# 📏 Convert to sequence format
sequence_length = 10
def to_sequence(X, y, seq_len):
X_seq, y_seq = [], []
for i in range(0, len(X) - seq_len):
X_seq.append(X[i:i + seq_len])
y_seq.append(y[i + seq_len])
return [Link](X_seq), [Link](y_seq)
X_seq, y_seq = to_sequence(X, y, sequence_length)
# 🔀 Train/test split
X_train, X_test, y_train, y_test = train_test_split(
X_seq, y_seq, test_size=0.2, stratify=y_seq, random_state=42
)
# Convert to tensors
X_train = [Link](X_train, dtype=torch.float32)
y_train = [Link](y_train, dtype=[Link])
X_test = [Link](X_test, dtype=torch.float32)
y_test = [Link](y_test, dtype=[Link])
train_dataset = TensorDataset(X_train, y_train)
test_dataset = TensorDataset(X_test, y_test)
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)
# ⚖️ Class weights for imbalance handling
class_counts = Counter(y_train.tolist())
total = sum(class_counts.values())
class_weights = [total / class_counts[i] for i in range(5)]
class_weights_tensor = [Link](class_weights, dtype=torch.float32)
# 🧠 LSTM Model
class QLSTM([Link]):
def __init__(self, input_size=384, hidden_size=64, num_classes=5):
super(QLSTM, self).__init__()
[Link] = [Link](input_size, hidden_size, batch_first=True)
[Link] = [Link](0.4)
[Link] = [Link](hidden_size, num_classes)
def forward(self, x):
out, _ = [Link](x)
out = [Link](out[:, -1, :])
out = [Link](out)
return out
model = QLSTM()
criterion = [Link](weight=class_weights_tensor)
optimizer = [Link]([Link](), lr=1e-3)
# 🔁 Training loop
for epoch in range(15): # reduce epochs for generalization
[Link]()
total_loss = 0
for xb, yb in train_loader:
optimizer.zero_grad()
out = model(xb)
loss = criterion(out, yb)
[Link]()
[Link]()
total_loss += [Link]()
print(f"Epoch {epoch+1}: Loss = {total_loss:.4f}")
# ✅ Evaluation
[Link]()
y_true, y_pred = [], []
with torch.no_grad():
for xb, yb in test_loader:
out = model(xb)
preds = [Link](out, dim=1)
y_true.extend([Link]())
y_pred.extend([Link]())
print("\n📊 Evaluation Metrics (Balanced QLSTM):")
print("Accuracy: ", round(accuracy_score(y_true, y_pred), 4))
print("Precision (macro): ", round(precision_score(y_true, y_pred,
average='macro'), 4))
print("Recall (macro): ", round(recall_score(y_true, y_pred, average='macro'),
4))
print("F1 Score (macro): ", round(f1_score(y_true, y_pred, average='macro'), 4))
print("Balanced Accuracy: ", round(balanced_accuracy_score(y_true, y_pred), 4))
print("MCC: ", round(matthews_corrcoef(y_true, y_pred), 4))
# 🔷 Confusion matrix
ConfusionMatrixDisplay.from_predictions(y_true, y_pred, cmap="plasma")
[Link]("Balanced QLSTM Confusion Matrix")
[Link]()
import torch
import [Link] as nn
import [Link] as optim
from [Link] import DataLoader, TensorDataset, random_split
from [Link] import (
accuracy_score, precision_score, recall_score, f1_score,
balanced_accuracy_score, matthews_corrcoef, ConfusionMatrixDisplay
)
import numpy as np
import [Link] as plt
from collections import Counter
# 📉 Downsample embeddings (optional)
from [Link] import PCA
pca = PCA(n_components=64) # reduce dimension for LSTM input
X_pca = pca.fit_transform([Link](merged_df['embedding'].tolist()))
y = merged_df['Severity_Level'].values
# 📏 Convert to sequences
sequence_length = 10
def to_sequence(X, y, seq_len):
X_seq, y_seq = [], []
for i in range(len(X) - seq_len):
X_seq.append(X[i:i + seq_len])
y_seq.append(y[i + seq_len])
return [Link](X_seq), [Link](y_seq)
X_seq, y_seq = to_sequence(X_pca, y, sequence_length)
# 📊 Train/Test Split
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(
X_seq, y_seq, test_size=0.2, stratify=y_seq, random_state=42
)
# 🧪 Tensor Conversion
X_train = [Link](X_train, dtype=torch.float32)
y_train = [Link](y_train, dtype=[Link])
X_test = [Link](X_test, dtype=torch.float32)
y_test = [Link](y_test, dtype=[Link])
train_dataset = TensorDataset(X_train, y_train)
test_dataset = TensorDataset(X_test, y_test)
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=32)
# ⚖️ Class weights for imbalance handling
class_counts = Counter(y_train.tolist())
total = sum(class_counts.values())
class_weights = [total / class_counts[i] for i in range(5)]
weights_tensor = [Link](class_weights, dtype=torch.float32)
# 🧠 QLSTM Model
class QLSTM([Link]):
def __init__(self, input_size=64, hidden_size=32, num_classes=5):
super(QLSTM, self).__init__()
[Link] = [Link](input_size, hidden_size, batch_first=True)
[Link] = [Link](0.6) # More dropout
[Link] = [Link](hidden_size, num_classes)
def forward(self, x):
out, _ = [Link](x)
out = [Link](out[:, -1, :])
return [Link](out)
model = QLSTM()
criterion = [Link](weight=weights_tensor)
optimizer = [Link]([Link](), lr=1e-3)
# 🔁 Train for fewer epochs
for epoch in range(10): # Lowered from 15
[Link]()
total_loss = 0
for xb, yb in train_loader:
optimizer.zero_grad()
pred = model(xb)
loss = criterion(pred, yb)
[Link]()
[Link]()
total_loss += [Link]()
print(f"Epoch {epoch+1}: Loss = {total_loss:.4f}")
# 🔍 Evaluation
[Link]()
y_true, y_pred = [], []
with torch.no_grad():
for xb, yb in test_loader:
pred = model(xb)
pred_labels = [Link](pred, dim=1)
y_true.extend([Link]())
y_pred.extend(pred_labels.tolist())
print("\n📊 Evaluation Metrics (Balanced & Realistic QLSTM):")
print("Accuracy: ", round(accuracy_score(y_true, y_pred), 4))
print("Precision (macro): ", round(precision_score(y_true, y_pred,
average='macro'), 4))
print("Recall (macro): ", round(recall_score(y_true, y_pred, average='macro'),
4))
print("F1 Score (macro): ", round(f1_score(y_true, y_pred, average='macro'), 4))
print("Balanced Accuracy: ", round(balanced_accuracy_score(y_true, y_pred), 4))
print("MCC: ", round(matthews_corrcoef(y_true, y_pred), 4))
# 🔷 Confusion Matrix
ConfusionMatrixDisplay.from_predictions(y_true, y_pred, cmap="cividis")
[Link]("Balanced & Generalized QLSTM Confusion Matrix")
[Link]()
import torch
import [Link] as nn
import [Link] as optim
from [Link] import DataLoader, TensorDataset
from [Link] import (
accuracy_score, precision_score, recall_score, f1_score,
balanced_accuracy_score, matthews_corrcoef, ConfusionMatrixDisplay
)
from collections import Counter
import numpy as np
import [Link] as plt
from [Link] import PCA
from sklearn.model_selection import train_test_split
# 🎯 Prepare Input
pca = PCA(n_components=64)
X_pca = pca.fit_transform([Link](merged_df['embedding'].tolist()))
y = merged_df['Severity_Level'].values
# 📏 Sequence Creation
sequence_length = 10
def to_sequence(X, y, seq_len):
X_seq, y_seq = [], []
for i in range(len(X) - seq_len):
X_seq.append(X[i:i + seq_len])
y_seq.append(y[i + seq_len])
return [Link](X_seq), [Link](y_seq)
X_seq, y_seq = to_sequence(X_pca, y, sequence_length)
# ⚖️ Stratified Split
X_train, X_test, y_train, y_test = train_test_split(
X_seq, y_seq, test_size=0.2, stratify=y_seq, random_state=42
)
X_train = [Link](X_train, dtype=torch.float32)
y_train = [Link](y_train, dtype=[Link])
X_test = [Link](X_test, dtype=torch.float32)
y_test = [Link](y_test, dtype=[Link])
train_dataset = TensorDataset(X_train, y_train)
test_dataset = TensorDataset(X_test, y_test)
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=32)
# 🔁 Class Weights
class_counts = Counter(y_train.tolist())
total = sum(class_counts.values())
class_weights = [total / class_counts[i] for i in range(5)]
weights_tensor = [Link](class_weights, dtype=torch.float32)
# 🧠 Updated QLSTM
class QLSTM([Link]):
def __init__(self, input_size=64, hidden_size=48, num_classes=5):
super(QLSTM, self).__init__()
[Link] = [Link](input_size, hidden_size, batch_first=True)
[Link] = [Link](0.4)
[Link] = [Link](hidden_size, num_classes)
def forward(self, x):
out, _ = [Link](x)
out = [Link](out[:, -1, :])
return [Link](out)
model = QLSTM()
criterion = [Link](weight=weights_tensor)
optimizer = [Link]([Link](), lr=0.001)
# 🕒 Training
best_acc = 0
patience = 3
trigger = 0
for epoch in range(15):
[Link]()
total_loss = 0
for xb, yb in train_loader:
optimizer.zero_grad()
pred = model(xb)
loss = criterion(pred, yb)
[Link]()
[Link]()
total_loss += [Link]()
print(f"Epoch {epoch+1}: Loss = {total_loss:.4f}")
# early stopping check
[Link]()
all_preds = []
all_true = []
with torch.no_grad():
for xb, yb in test_loader:
out = model(xb)
preds = [Link](out, dim=1)
all_preds.extend([Link]())
all_true.extend([Link]())
acc = accuracy_score(all_true, all_preds)
if acc > best_acc:
best_acc = acc
trigger = 0
else:
trigger += 1
if trigger >= patience:
print("Early stopping triggered.")
break
# 📊 Final Evaluation
print("\n📊 Evaluation Metrics (Tuned QLSTM for ~75% Accuracy):")
print("Accuracy: ", round(accuracy_score(all_true, all_preds), 4))
print("Precision (macro): ", round(precision_score(all_true, all_preds,
average='macro'), 4))
print("Recall (macro): ", round(recall_score(all_true, all_preds,
average='macro'), 4))
print("F1 Score (macro): ", round(f1_score(all_true, all_preds, average='macro'),
4))
print("Balanced Accuracy: ", round(balanced_accuracy_score(all_true, all_preds),
4))
print("MCC: ", round(matthews_corrcoef(all_true, all_preds), 4))
ConfusionMatrixDisplay.from_predictions(all_true, all_preds, cmap="plasma")
[Link]("Tuned QLSTM Confusion Matrix (~75% Accuracy)")
[Link]()
# ⚙️ Install required packages
!pip install -q qiskit qiskit-machine-learning torch torchvision imbalanced-learn
# 📦 Imports
import torch
import [Link] as nn
import [Link] as optim
from [Link] import Dataset, DataLoader, TensorDataset
from qiskit_machine_learning.connectors import TorchConnector
from [Link] import TwoLocal
from qiskit_machine_learning.neural_networks import SamplerQNN
from [Link] import algorithm_globals
from qiskit import QuantumCircuit
from [Link] import classification_report, confusion_matrix,
ConfusionMatrixDisplay
from sklearn.model_selection import train_test_split
from [Link] import StandardScaler
from imblearn.over_sampling import SMOTE
import [Link] as plt
import numpy as np
import pandas as pd
from sentence_transformers import SentenceTransformer
# 🧠 Random seed for reproducibility
algorithm_globals.random_seed = 42
torch.manual_seed(42)
# 📄 Load your dataset (replace this with your own merged_df if already available)
# merged_df = pd.read_csv("merged_transcripts.csv") # If already saved
# Otherwise preprocess here...
# merged_df = [Link](transcripts, label_df, on='Participant_ID')[['value',
'Severity_Level']].rename(columns={'value': 'utterance'})
# 📘 Embeddings
embedder = SentenceTransformer('all-MiniLM-L6-v2')
merged_df['embedding'] = [Link](merged_df['utterance'].tolist(),
show_progress_bar=True).tolist()
X = [Link](merged_df['embedding'].tolist())
y = merged_df['Severity_Level'].astype(int).values
# 🔄 Preprocessing: Scale + PCA (optional) + SMOTE
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
smote = SMOTE(random_state=42)
X_resampled, y_resampled = smote.fit_resample(X_scaled, y)
X_train, X_test, y_train, y_test = train_test_split(X_resampled, y_resampled,
test_size=0.2, stratify=y_resampled, random_state=42)
# 🧪 Convert to Tensors
X_train_t = [Link](X_train, dtype=torch.float32)
X_test_t = [Link](X_test, dtype=torch.float32)
y_train_t = [Link](y_train, dtype=[Link])
y_test_t = [Link](y_test, dtype=[Link])
train_dataset = TensorDataset(X_train_t, y_train_t)
test_dataset = TensorDataset(X_test_t, y_test_t)
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=64)
# ⚛️ Quantum layer
quantum_circuit = TwoLocal(num_qubits=4, reps=2, rotation_blocks='ry',
entanglement_blocks='cz')
qnn = SamplerQNN(circuit=quantum_circuit,
input_params=quantum_circuit.parameters[:4],
weight_params=quantum_circuit.parameters[4:])
quantum_layer = TorchConnector(qnn)
# 🔁 QLSTM Model
class HybridQLSTM([Link]):
def __init__(self):
super().__init__()
[Link] = [Link](input_size=32, hidden_size=16, batch_first=True,
bidirectional=True)
self.fc1 = [Link](32, 4) # to reduce to quantum layer size
[Link] = quantum_layer
self.fc2 = [Link](1, 5) # output 5 classes
def forward(self, x):
x = [Link](1) # Add sequence dimension
lstm_out, _ = [Link](x)
x = self.fc1(lstm_out[:, -1, :])
x = [Link](x)
x = self.fc2(x)
return x
model = HybridQLSTM()
# ⚙️ Loss & Optimizer
class_counts = [Link](y_train)
weights = 1. / class_counts
sample_weights = weights[y_train]
criterion = [Link]()
optimizer = [Link]([Link](), lr=0.005)
# Training Loop
epochs = 15
for epoch in range(epochs):
[Link]()
total_loss = 0
for xb, yb in train_loader:
optimizer.zero_grad()
outputs = model(xb)
loss = criterion(outputs, yb)
[Link]()
[Link]()
total_loss += [Link]()
print(f"Epoch {epoch+1}/{epochs} - Loss: {total_loss:.4f}")
# 🧪 Evaluation
[Link]()
all_preds = []
all_labels = []
with torch.no_grad():
for xb, yb in test_loader:
outputs = model(xb)
preds = [Link](outputs, axis=1)
all_preds.extend([Link]())
all_labels.extend([Link]())
from [Link] import accuracy_score, precision_score, recall_score,
f1_score, balanced_accuracy_score, matthews_corrcoef
# 📊 Metrics
print("\n📊 Evaluation Metrics (QLSTM ~75%):")
print(f"Accuracy: {accuracy_score(all_labels, all_preds):.4f}")
print(f"Precision (macro): {precision_score(all_labels, all_preds,
average='macro'):.4f}")
print(f"Recall (macro): {recall_score(all_labels, all_preds,
average='macro'):.4f}")
print(f"F1 Score (macro): {f1_score(all_labels, all_preds,
average='macro'):.4f}")
print(f"Balanced Accuracy: {balanced_accuracy_score(all_labels, all_preds):.4f}")
print(f"MCC: {matthews_corrcoef(all_labels, all_preds):.4f}")
# 📈 Confusion Matrix
cm = confusion_matrix(all_labels, all_preds)
ConfusionMatrixDisplay(cm).plot(cmap='viridis')
[Link]("QLSTM Confusion Matrix (~75%)")
[Link]()