Update app.py
Browse files
app.py
CHANGED
|
@@ -36,6 +36,8 @@ REPO_CONFIG = {
|
|
| 36 |
}
|
| 37 |
|
| 38 |
TARGET_COLS = ["error_Z_global", "error_X_global", "error_Y_global"]
|
|
|
|
|
|
|
| 39 |
|
| 40 |
NON_FEATURE_COLS = {
|
| 41 |
"sample_id", "sample_seed", "circuit_hash", "split", "circuit_qasm",
|
|
@@ -43,13 +45,10 @@ NON_FEATURE_COLS = {
|
|
| 43 |
"noise_type", "noise_prob", "observable_bases", "observable_mode", "shots",
|
| 44 |
"gpu_requested", "gpu_available", "backend_device", "precision_mode",
|
| 45 |
"circuit_signature", "noise_label",
|
| 46 |
-
|
| 47 |
-
"ideal_expval_X_global", "noisy_expval_X_global",
|
| 48 |
-
"ideal_expval_Y_global", "noisy_expval_Y_global",
|
| 49 |
"sign_ideal_Z_global", "sign_noisy_Z_global",
|
| 50 |
"sign_ideal_X_global", "sign_noisy_X_global",
|
| 51 |
"sign_ideal_Y_global", "sign_noisy_Y_global",
|
| 52 |
-
*TARGET_COLS,
|
| 53 |
}
|
| 54 |
|
| 55 |
SOFT_EXCLUDE_PATTERNS = ["ideal_", "noisy_", "sign_ideal_", "sign_noisy_"]
|
|
@@ -59,9 +58,7 @@ _ASSET_CACHE: Dict[str, pd.DataFrame] = {}
|
|
| 59 |
# ========================= HELPERS =========================
|
| 60 |
|
| 61 |
def load_guide_content() -> str:
|
| 62 |
-
"""
|
| 63 |
-
Read the GUIDE.md file from the root directory.
|
| 64 |
-
"""
|
| 65 |
try:
|
| 66 |
with open("GUIDE.md", "r", encoding="utf-8") as f:
|
| 67 |
return f.read()
|
|
@@ -184,10 +181,18 @@ def default_feature_selection(features: List[str]) -> List[str]:
|
|
| 184 |
selected = [f for f in preferred if f in features]
|
| 185 |
return selected[:10] if selected else features[:10]
|
| 186 |
|
| 187 |
-
def make_regression_figure(
|
| 188 |
-
|
| 189 |
-
|
| 190 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 191 |
min_v, max_v = min(y_true.min(), y_pred.min()), max(y_true.max(), y_pred.max())
|
| 192 |
axs[0].plot([min_v, max_v], [min_v, max_v], 'r--', lw=2)
|
| 193 |
axs[0].set_xlabel("True Error")
|
|
@@ -195,14 +200,27 @@ def make_regression_figure(y_true: np.ndarray, y_pred: np.ndarray, basis: str) -
|
|
| 195 |
axs[0].set_title(f"{basis} Error: Predicted vs True")
|
| 196 |
axs[0].grid(True, alpha=0.3)
|
| 197 |
|
|
|
|
| 198 |
residuals = y_true - y_pred
|
| 199 |
-
axs[1].hist(residuals, bins=50, alpha=0.7, color="
|
| 200 |
axs[1].axvline(0, color="red", linestyle="--")
|
| 201 |
axs[1].set_xlabel("Residual")
|
| 202 |
axs[1].set_ylabel("Count")
|
| 203 |
-
axs[1].set_title(f"{basis}
|
| 204 |
axs[1].grid(True, alpha=0.3)
|
| 205 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 206 |
fig.tight_layout()
|
| 207 |
return fig
|
| 208 |
|
|
@@ -218,7 +236,7 @@ def train_regressor(
|
|
| 218 |
return None, "### β Please select at least one feature.", None, None
|
| 219 |
|
| 220 |
df = load_single_dataset()
|
| 221 |
-
required_cols = feature_columns + TARGET_COLS
|
| 222 |
train_df = df.dropna(subset=required_cols).copy()
|
| 223 |
|
| 224 |
if len(train_df) < 50:
|
|
@@ -230,9 +248,15 @@ def train_regressor(
|
|
| 230 |
seed = int(random_state)
|
| 231 |
depth = int(max_depth) if max_depth and int(max_depth) > 0 else None
|
| 232 |
|
| 233 |
-
|
| 234 |
-
|
| 235 |
-
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 236 |
|
| 237 |
model = Pipeline([
|
| 238 |
("imputer", SimpleImputer(strategy="median")),
|
|
@@ -264,9 +288,10 @@ def train_regressor(
|
|
| 264 |
f"**Y-error** β MAE: {mae[2]:.5f} | RMSE: {rmse[2]:.5f} | RΒ²: {r2[2]:.4f}\n"
|
| 265 |
)
|
| 266 |
|
| 267 |
-
|
| 268 |
-
|
| 269 |
-
|
|
|
|
| 270 |
|
| 271 |
return fig_z, metrics_text, fig_x, fig_y
|
| 272 |
|
|
@@ -363,9 +388,9 @@ with gr.Blocks(title=APP_TITLE) as demo:
|
|
| 363 |
run_btn = gr.Button("π Train Multi-Output Regressor", variant="primary")
|
| 364 |
|
| 365 |
with gr.Row():
|
| 366 |
-
plot_z = gr.Plot(label="Z Error")
|
| 367 |
-
plot_x = gr.Plot(label="X Error")
|
| 368 |
-
plot_y = gr.Plot(label="Y Error")
|
| 369 |
metrics = gr.Markdown()
|
| 370 |
|
| 371 |
with gr.TabItem("π Guide"):
|
|
|
|
| 36 |
}
|
| 37 |
|
| 38 |
TARGET_COLS = ["error_Z_global", "error_X_global", "error_Y_global"]
|
| 39 |
+
IDEAL_COLS = ["ideal_expval_Z_global", "ideal_expval_X_global", "ideal_expval_Y_global"]
|
| 40 |
+
NOISY_COLS = ["noisy_expval_Z_global", "noisy_expval_X_global", "noisy_expval_Y_global"]
|
| 41 |
|
| 42 |
NON_FEATURE_COLS = {
|
| 43 |
"sample_id", "sample_seed", "circuit_hash", "split", "circuit_qasm",
|
|
|
|
| 45 |
"noise_type", "noise_prob", "observable_bases", "observable_mode", "shots",
|
| 46 |
"gpu_requested", "gpu_available", "backend_device", "precision_mode",
|
| 47 |
"circuit_signature", "noise_label",
|
| 48 |
+
*IDEAL_COLS, *NOISY_COLS, *TARGET_COLS,
|
|
|
|
|
|
|
| 49 |
"sign_ideal_Z_global", "sign_noisy_Z_global",
|
| 50 |
"sign_ideal_X_global", "sign_noisy_X_global",
|
| 51 |
"sign_ideal_Y_global", "sign_noisy_Y_global",
|
|
|
|
| 52 |
}
|
| 53 |
|
| 54 |
SOFT_EXCLUDE_PATTERNS = ["ideal_", "noisy_", "sign_ideal_", "sign_noisy_"]
|
|
|
|
| 58 |
# ========================= HELPERS =========================
|
| 59 |
|
| 60 |
def load_guide_content() -> str:
|
| 61 |
+
"""Read the GUIDE.md file from the root directory."""
|
|
|
|
|
|
|
| 62 |
try:
|
| 63 |
with open("GUIDE.md", "r", encoding="utf-8") as f:
|
| 64 |
return f.read()
|
|
|
|
| 181 |
selected = [f for f in preferred if f in features]
|
| 182 |
return selected[:10] if selected else features[:10]
|
| 183 |
|
| 184 |
+
def make_regression_figure(
|
| 185 |
+
y_true: np.ndarray,
|
| 186 |
+
y_pred: np.ndarray,
|
| 187 |
+
ideal_vals: np.ndarray,
|
| 188 |
+
noisy_vals: np.ndarray,
|
| 189 |
+
basis: str
|
| 190 |
+
) -> plt.Figure:
|
| 191 |
+
"""Generate diagnostic regression plots including physics emulation."""
|
| 192 |
+
fig, axs = plt.subplots(1, 3, figsize=(20, 6))
|
| 193 |
+
|
| 194 |
+
# 1. Error Prediction (Predicted vs True)
|
| 195 |
+
axs[0].scatter(y_true, y_pred, alpha=0.6, s=15, color='#3498db')
|
| 196 |
min_v, max_v = min(y_true.min(), y_pred.min()), max(y_true.max(), y_pred.max())
|
| 197 |
axs[0].plot([min_v, max_v], [min_v, max_v], 'r--', lw=2)
|
| 198 |
axs[0].set_xlabel("True Error")
|
|
|
|
| 200 |
axs[0].set_title(f"{basis} Error: Predicted vs True")
|
| 201 |
axs[0].grid(True, alpha=0.3)
|
| 202 |
|
| 203 |
+
# 2. Residual Distribution
|
| 204 |
residuals = y_true - y_pred
|
| 205 |
+
axs[1].hist(residuals, bins=50, alpha=0.7, color="#2ecc71", edgecolor="black")
|
| 206 |
axs[1].axvline(0, color="red", linestyle="--")
|
| 207 |
axs[1].set_xlabel("Residual")
|
| 208 |
axs[1].set_ylabel("Count")
|
| 209 |
+
axs[1].set_title(f"{basis} Error Residuals")
|
| 210 |
axs[1].grid(True, alpha=0.3)
|
| 211 |
|
| 212 |
+
# 3. Physics Emulation (Ideal vs Noisy Expectation Values)
|
| 213 |
+
pred_noisy_vals = ideal_vals + y_pred
|
| 214 |
+
|
| 215 |
+
axs[2].scatter(ideal_vals, noisy_vals, alpha=0.4, s=15, label="Actual Noisy (Simulated)", color="#95a5a6")
|
| 216 |
+
axs[2].scatter(ideal_vals, pred_noisy_vals, alpha=0.6, s=15, label="Predicted Noisy (ML)", color="#e74c3c")
|
| 217 |
+
axs[2].plot([-1, 1], [-1, 1], 'k--', lw=1, alpha=0.7, label="No Noise Limit")
|
| 218 |
+
axs[2].set_xlabel("Ideal Expectation Value")
|
| 219 |
+
axs[2].set_ylabel("Noisy Expectation Value")
|
| 220 |
+
axs[2].set_title(f"Physics Emulation: {basis} Basis Shift")
|
| 221 |
+
axs[2].legend()
|
| 222 |
+
axs[2].grid(True, alpha=0.3)
|
| 223 |
+
|
| 224 |
fig.tight_layout()
|
| 225 |
return fig
|
| 226 |
|
|
|
|
| 236 |
return None, "### β Please select at least one feature.", None, None
|
| 237 |
|
| 238 |
df = load_single_dataset()
|
| 239 |
+
required_cols = feature_columns + TARGET_COLS + IDEAL_COLS + NOISY_COLS
|
| 240 |
train_df = df.dropna(subset=required_cols).copy()
|
| 241 |
|
| 242 |
if len(train_df) < 50:
|
|
|
|
| 248 |
seed = int(random_state)
|
| 249 |
depth = int(max_depth) if max_depth and int(max_depth) > 0 else None
|
| 250 |
|
| 251 |
+
# Track indices to extract ideal and noisy arrays for the test set later
|
| 252 |
+
indices = np.arange(len(train_df))
|
| 253 |
+
idx_train, idx_test = train_test_split(indices, test_size=test_size, random_state=seed)
|
| 254 |
+
|
| 255 |
+
X_train, X_test = X.iloc[idx_train], X.iloc[idx_test]
|
| 256 |
+
y_train, y_test = y.iloc[idx_train], y.iloc[idx_test]
|
| 257 |
+
|
| 258 |
+
ideal_test = train_df[IDEAL_COLS].iloc[idx_test].values
|
| 259 |
+
noisy_test = train_df[NOISY_COLS].iloc[idx_test].values
|
| 260 |
|
| 261 |
model = Pipeline([
|
| 262 |
("imputer", SimpleImputer(strategy="median")),
|
|
|
|
| 288 |
f"**Y-error** β MAE: {mae[2]:.5f} | RMSE: {rmse[2]:.5f} | RΒ²: {r2[2]:.4f}\n"
|
| 289 |
)
|
| 290 |
|
| 291 |
+
# Generate figures passing ideal and true noisy data
|
| 292 |
+
fig_z = make_regression_figure(y_test.iloc[:, 0].values, y_pred[:, 0], ideal_test[:, 0], noisy_test[:, 0], "Z")
|
| 293 |
+
fig_x = make_regression_figure(y_test.iloc[:, 1].values, y_pred[:, 1], ideal_test[:, 1], noisy_test[:, 1], "X")
|
| 294 |
+
fig_y = make_regression_figure(y_test.iloc[:, 2].values, y_pred[:, 2], ideal_test[:, 2], noisy_test[:, 2], "Y")
|
| 295 |
|
| 296 |
return fig_z, metrics_text, fig_x, fig_y
|
| 297 |
|
|
|
|
| 388 |
run_btn = gr.Button("π Train Multi-Output Regressor", variant="primary")
|
| 389 |
|
| 390 |
with gr.Row():
|
| 391 |
+
plot_z = gr.Plot(label="Z Error Metrics")
|
| 392 |
+
plot_x = gr.Plot(label="X Error Metrics")
|
| 393 |
+
plot_y = gr.Plot(label="Y Error Metrics")
|
| 394 |
metrics = gr.Markdown()
|
| 395 |
|
| 396 |
with gr.TabItem("π Guide"):
|