Changes to be committed:
modified: .gitignore deleted: Figure_1.png deleted: checkpoints/forward/best_tcn_model.pt deleted: checkpoints/forward/training_history.csv deleted: checkpoints_mlp/task1_feature_mlp/best_feature_mlp.pt deleted: checkpoints_mlp/task1_feature_mlp/training_history.csv deleted: checkpoints_rms/forward_rms/best_rms_model.pt deleted: checkpoints_rms/forward_rms/training_history.csv deleted: checkpoints_tree/task1_tr_tree/best_tr_tree.pkl deleted: checkpoints_tree/task1_tr_tree/model_selection.csv deleted: evaluation_outputs/forward/evaluation_forward_test_b0_s0.png deleted: evaluation_outputs/forward/evaluation_forward_val_b0_s0.png deleted: evaluation_outputs/forward/evaluation_forward_val_b3_s0.png deleted: evaluation_outputs/forward_rms/evaluation_test_all_samples.csv deleted: evaluation_outputs/forward_rms/evaluation_test_s0.png deleted: evaluation_outputs/forward_rms/evaluation_train_all_samples.csv deleted: evaluation_outputs/forward_rms/evaluation_val_all_samples.csv deleted: evaluation_outputs/forward_rms/evaluation_val_s0.png deleted: evaluation_outputs/forward_rms/evaluation_val_s0_waveform.png deleted: evaluation_outputs/task1_feature_mlp/evaluation_train_all_samples.csv deleted: evaluation_outputs/task1_feature_mlp/evaluation_train_curve.png deleted: evaluation_outputs/task1_feature_mlp/evaluation_val_all_samples.csv deleted: evaluation_outputs/task1_feature_mlp/evaluation_val_curve.png deleted: evaluation_outputs/task1_feature_mlp/evaluation_val_s0.png deleted: evaluation_outputs/task1_feature_mlp/harmonic_5mm_0.75Hz_prediction.png deleted: evaluation_outputs/task1_feature_mlp/harmonic_5mm_1.55Hz_prediction.png deleted: evaluation_outputs/task1_tr_tree/evaluation_train_all_samples.csv deleted: evaluation_outputs/task1_tr_tree/evaluation_train_curve.png deleted: evaluation_outputs/task1_tr_tree/evaluation_val_all_samples.csv deleted: evaluation_outputs/task1_tr_tree/evaluation_val_curve.png deleted: evaluation_outputs/task1_tr_tree/harmonic_5mm_1.55Hz_prediction.png deleted: sanity_check_alignment_forward.png new file: scripts/README.md modified: scripts/__pycache__/config.cpython-310.pyc modified: scripts/__pycache__/dataset.cpython-310.pyc deleted: scripts/__pycache__/model.cpython-310.pyc modified: scripts/config.py modified: scripts/dataset.py modified: scripts/evaluate.py deleted: scripts/model.py modified: scripts/predict_single.py deleted: scripts/train.py new file: scripts/train_final.py deleted: scripts_tree/__pycache__/config.cpython-310.pyc deleted: scripts_tree/config.py deleted: scripts_tree/evaluate.py deleted: scripts_tree/predict_single.py deleted: scripts_tree/train.py deleted: src/__pycache__/config.cpython-310.pyc deleted: src/__pycache__/config.cpython-314.pyc deleted: src/__pycache__/dataset.cpython-310.pyc deleted: src/__pycache__/dataset.cpython-314.pyc deleted: src/__pycache__/model.cpython-310.pyc deleted: src/__pycache__/model.cpython-314.pyc deleted: src/config.py deleted: src/dataset.py deleted: src/evaluate.py deleted: src/model.py deleted: src/sanity_check.py deleted: src/train.py deleted: src_new/__pycache__/config.cpython-310.pyc deleted: src_new/__pycache__/dataset.cpython-310.pyc deleted: src_new/__pycache__/evaluate.cpython-310.pyc deleted: src_new/__pycache__/model.cpython-310.pyc deleted: src_new/__pycache__/train.cpython-310.pyc deleted: src_new/config.py deleted: src_new/dataset.py deleted: src_new/evaluate.py deleted: src_new/model.py deleted: src_new/train.py deleted: src_old/__init__.py deleted: src_old/__pycache__/config.cpython-310.pyc deleted: src_old/__pycache__/config.cpython-314.pyc deleted: src_old/__pycache__/dataset.cpython-310.pyc deleted: src_old/__pycache__/dataset.cpython-314.pyc deleted: src_old/__pycache__/evaluate.cpython-314.pyc deleted: src_old/__pycache__/model.cpython-310.pyc deleted: src_old/__pycache__/model.cpython-314.pyc deleted: src_old/__pycache__/train.cpython-310.pyc deleted: src_old/__pycache__/train.cpython-314.pyc deleted: src_old/config.py deleted: src_old/dataset.py deleted: src_old/evaluate.py deleted: src_old/model.py deleted: src_old/train.py
This commit is contained in:
@@ -1,60 +1,44 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import pickle
|
||||
from pathlib import Path
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
import torch
|
||||
|
||||
try:
|
||||
from .config import CORE_FEATURE_NAMES, make_experiment_config
|
||||
from .dataset import build_record_from_file, normalization_from_payload
|
||||
from .model import build_model
|
||||
from .config import CORE_FEATURE_NAMES, evaluation_dir, make_experiment_config
|
||||
from .dataset import build_record_from_file
|
||||
except ImportError:
|
||||
from config import CORE_FEATURE_NAMES, make_experiment_config
|
||||
from dataset import build_record_from_file, normalization_from_payload
|
||||
from model import build_model
|
||||
from config import CORE_FEATURE_NAMES, evaluation_dir, make_experiment_config
|
||||
from dataset import build_record_from_file
|
||||
|
||||
|
||||
def parse_args() -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser(description="Predict task1 RMS from a single waveform CSV.")
|
||||
parser = argparse.ArgumentParser(description="Predict task1 RMS from a single harmonic waveform CSV.")
|
||||
parser.add_argument("--file", type=str, required=True)
|
||||
parser.add_argument("--device", type=str, default=None)
|
||||
parser.add_argument("--checkpoint", type=str, default=None)
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def resolve_device(device_name: str | None, default_device: str) -> torch.device:
|
||||
requested = device_name or default_device
|
||||
if requested.startswith("cuda") and not torch.cuda.is_available():
|
||||
return torch.device("cpu")
|
||||
return torch.device(requested)
|
||||
|
||||
|
||||
def resolve_checkpoint_path(project_root: Path, checkpoint_dir: str, best_model_name: str, checkpoint_arg: str | None) -> Path:
|
||||
def resolve_checkpoint_path(project_root: Path, checkpoint_arg: str | None) -> Path:
|
||||
if checkpoint_arg:
|
||||
return Path(checkpoint_arg).resolve()
|
||||
return project_root / checkpoint_dir / "task1_feature_mlp" / best_model_name
|
||||
return project_root / "checkpoints_final" / "task1_final" / "task1_final_model.pkl"
|
||||
|
||||
|
||||
def save_prediction_figure(
|
||||
file_path: Path,
|
||||
record,
|
||||
pred_rms: float,
|
||||
true_rms: float | None,
|
||||
output_dir: Path,
|
||||
) -> Path:
|
||||
time_middle = record.time_middle.detach().cpu().numpy().reshape(-1)
|
||||
x_middle = record.x_middle.detach().cpu().numpy().reshape(-1)
|
||||
y_middle = record.y_middle.detach().cpu().numpy().reshape(-1)
|
||||
def save_prediction_figure(file_path: Path, record, pred_rms: float, output_dir: Path) -> Path:
|
||||
time_middle = record.time_middle.reshape(-1)
|
||||
x_middle = record.x_middle.reshape(-1)
|
||||
y_middle = record.y_middle.reshape(-1)
|
||||
sampling_rate = record.sampling_rate
|
||||
fft_values = np.fft.rfft(x_middle)
|
||||
fft_values = np.fft.rfft(x_middle - np.mean(x_middle))
|
||||
freqs = np.fft.rfftfreq(x_middle.size, d=1.0 / sampling_rate)
|
||||
amplitudes = np.abs(fft_values)
|
||||
|
||||
fig, axes = plt.subplots(3, 1, figsize=(12, 10))
|
||||
fig.suptitle(f"Task1 Single-File Prediction | {file_path.name}")
|
||||
fig, axes = plt.subplots(4, 1, figsize=(12, 12))
|
||||
fig.suptitle(f"Task1 Final Single-File Prediction | {file_path.name}")
|
||||
|
||||
axes[0].plot(time_middle, x_middle, color="tab:blue")
|
||||
axes[0].set_title("Input Base Excitation (Middle Segment)")
|
||||
@@ -62,26 +46,28 @@ def save_prediction_figure(
|
||||
axes[0].set_ylabel("Acceleration")
|
||||
axes[0].grid(True, alpha=0.3)
|
||||
|
||||
axes[1].plot(freqs, amplitudes, color="tab:purple")
|
||||
axes[1].axvline(record.frequency_hz, color="tab:red", linestyle="--", label=f"Dominant freq = {record.frequency_hz:.4f} Hz")
|
||||
axes[1].set_xlim(0.0, 5.0)
|
||||
axes[1].set_title("Input Spectrum")
|
||||
axes[1].set_xlabel("Frequency (Hz)")
|
||||
axes[1].set_ylabel("Amplitude")
|
||||
axes[1].plot(time_middle, y_middle, color="tab:green")
|
||||
axes[1].set_title("True Top Response (Middle Segment)")
|
||||
axes[1].set_xlabel("Time")
|
||||
axes[1].set_ylabel("Acceleration")
|
||||
axes[1].grid(True, alpha=0.3)
|
||||
axes[1].legend()
|
||||
|
||||
labels = ["Pred RMS"] if true_rms is None else ["True RMS", "Pred RMS"]
|
||||
values = [pred_rms] if true_rms is None else [true_rms, pred_rms]
|
||||
colors = ["tab:orange"] if true_rms is None else ["tab:green", "tab:orange"]
|
||||
axes[2].bar(labels, values, color=colors)
|
||||
title = f"Predicted RMS = {pred_rms:.6f}"
|
||||
if true_rms is not None:
|
||||
error_percent = abs(pred_rms - true_rms) / max(abs(true_rms), 1e-12) * 100.0
|
||||
title = f"True RMS = {true_rms:.6f} | Pred RMS = {pred_rms:.6f} | Error = {error_percent:.2f}%"
|
||||
axes[2].set_title(title)
|
||||
axes[2].set_ylabel("RMS")
|
||||
axes[2].grid(True, axis="y", alpha=0.3)
|
||||
axes[2].plot(freqs, amplitudes, color="tab:purple")
|
||||
axes[2].axvline(record.frequency_hz, color="tab:red", linestyle="--", label=f"Frequency = {record.frequency_hz:.4f} Hz")
|
||||
axes[2].set_xlim(0.0, 5.0)
|
||||
axes[2].set_title("Input Spectrum")
|
||||
axes[2].set_xlabel("Frequency (Hz)")
|
||||
axes[2].set_ylabel("Amplitude")
|
||||
axes[2].grid(True, alpha=0.3)
|
||||
axes[2].legend()
|
||||
|
||||
axes[3].bar(["True RMS", "Pred RMS"], [record.y_rms, pred_rms], color=["tab:green", "tab:orange"])
|
||||
error_percent = abs(pred_rms - record.y_rms) / max(abs(record.y_rms), 1e-12) * 100.0
|
||||
axes[3].set_title(
|
||||
f"True RMS = {record.y_rms:.6f} | Pred RMS = {pred_rms:.6f} | Error = {error_percent:.2f}%"
|
||||
)
|
||||
axes[3].set_ylabel("RMS")
|
||||
axes[3].grid(True, axis="y", alpha=0.3)
|
||||
|
||||
plt.tight_layout()
|
||||
output_dir.mkdir(parents=True, exist_ok=True)
|
||||
@@ -94,49 +80,29 @@ def save_prediction_figure(
|
||||
def main() -> None:
|
||||
args = parse_args()
|
||||
config = make_experiment_config()
|
||||
device = resolve_device(args.device, config.train.device)
|
||||
checkpoint_path = resolve_checkpoint_path(
|
||||
config.data.project_root,
|
||||
config.train.checkpoint_dir,
|
||||
config.train.best_model_name,
|
||||
args.checkpoint,
|
||||
)
|
||||
if not checkpoint_path.exists():
|
||||
raise FileNotFoundError(f"Checkpoint not found: {checkpoint_path}")
|
||||
|
||||
checkpoint = torch.load(checkpoint_path, map_location=device, weights_only=False)
|
||||
normalization = normalization_from_payload(checkpoint["normalization"])
|
||||
model = build_model(config).to(device)
|
||||
model.load_state_dict(checkpoint["model_state_dict"])
|
||||
model.eval()
|
||||
ckpt_path = resolve_checkpoint_path(config.data.project_root, args.checkpoint)
|
||||
with ckpt_path.open("rb") as handle:
|
||||
payload = pickle.load(handle)
|
||||
model = payload["model"]
|
||||
|
||||
file_path = Path(args.file).resolve()
|
||||
record = build_record_from_file(file_path, split="predict", config=config.data)
|
||||
feature_norm = ((record.features - normalization.feature_mean) / normalization.feature_std).unsqueeze(0).to(device)
|
||||
x_rms_raw = record.x_rms.unsqueeze(0).to(device)
|
||||
target_mean = normalization.target_mean.to(device).view(1, 1)
|
||||
target_std = normalization.target_std.to(device).view(1, 1)
|
||||
record = build_record_from_file(file_path, config.data)
|
||||
pred_tr = max(float(model.predict([record.features.tolist()])[0]), config.data.normalization_eps)
|
||||
pred_rms = pred_tr * record.x_rms
|
||||
|
||||
with torch.no_grad():
|
||||
pred_norm = model(feature_norm)
|
||||
pred_tr = torch.clamp(pred_norm * target_std + target_mean, min=1e-6)
|
||||
pred_rms = float((pred_tr * x_rms_raw).detach().cpu().numpy().reshape(-1)[0])
|
||||
out_dir = evaluation_dir(config)
|
||||
fig_path = save_prediction_figure(file_path, record, pred_rms, out_dir)
|
||||
|
||||
true_rms = float(record.y_rms.item()) if record.y_rms.numel() > 0 else None
|
||||
output_dir = config.data.project_root / "evaluation_outputs" / "task1_feature_mlp"
|
||||
figure_path = save_prediction_figure(file_path, record, pred_rms, true_rms, output_dir)
|
||||
|
||||
print(f"Checkpoint: {checkpoint_path}")
|
||||
print(f"Checkpoint: {ckpt_path}")
|
||||
print(f"Model: {payload['model_name']}")
|
||||
print(f"Input file: {file_path}")
|
||||
print(f"Extracted frequency (Hz): {record.frequency_hz:.6f}")
|
||||
for feature_name, feature_value in zip(CORE_FEATURE_NAMES, record.features.tolist()):
|
||||
print(f"{feature_name}: {feature_value:.6f}")
|
||||
print(f"Predicted TR: {pred_tr:.6f}")
|
||||
print(f"Predicted RMS: {pred_rms:.6f}")
|
||||
if true_rms is not None:
|
||||
error_percent = abs(pred_rms - true_rms) / max(abs(true_rms), 1e-12) * 100.0
|
||||
print(f"True RMS: {true_rms:.6f}")
|
||||
print(f"Relative RMS Error (%): {error_percent:.4f}")
|
||||
print(f"Figure saved to: {figure_path}")
|
||||
print(f"True RMS: {record.y_rms:.6f}")
|
||||
print(f"Relative RMS Error (%): {abs(pred_rms - record.y_rms) / max(abs(record.y_rms), 1e-12) * 100.0:.4f}")
|
||||
print(f"Figure saved to: {fig_path}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user