new file: Figure_1.png

deleted:    best_model.pth
	new file:   checkpoints/forward/best_tcn_model.pt
	new file:   checkpoints/forward/training_history.csv
	new file:   evaluation_outputs/forward/evaluation_forward_test_b0_s0.png
	new file:   sanity_check_alignment_forward.png
	modified:   src/__pycache__/config.cpython-310.pyc
	modified:   src/__pycache__/config.cpython-314.pyc
	modified:   src/__pycache__/dataset.cpython-310.pyc
	modified:   src/__pycache__/dataset.cpython-314.pyc
	modified:   src/__pycache__/model.cpython-310.pyc
	modified:   src/__pycache__/model.cpython-314.pyc
	modified:   src/config.py
	modified:   src/dataset.py
	modified:   src/evaluate.py
	modified:   src/model.py
	new file:   src/sanity_check.py
	modified:   src/train.py
	renamed:    src/__init__.py -> src_old/__init__.py
	new file:   src_old/__pycache__/config.cpython-310.pyc
	new file:   src_old/__pycache__/config.cpython-314.pyc
	new file:   src_old/__pycache__/dataset.cpython-310.pyc
	new file:   src_old/__pycache__/dataset.cpython-314.pyc
	new file:   src_old/__pycache__/evaluate.cpython-314.pyc
	new file:   src_old/__pycache__/model.cpython-310.pyc
	new file:   src_old/__pycache__/model.cpython-314.pyc
	new file:   src_old/__pycache__/train.cpython-310.pyc
	new file:   src_old/__pycache__/train.cpython-314.pyc
	new file:   src_old/config.py
	new file:   src_old/dataset.py
	new file:   src_old/evaluate.py
	new file:   src_old/model.py
	new file:   src_old/train.py
	deleted:    test_results.png
This commit is contained in:
2026-05-04 18:18:44 +08:00
parent c65e47e6b0
commit dcc023cc04
34 changed files with 2177 additions and 436 deletions

73
src_old/evaluate.py Normal file
View File

@@ -0,0 +1,73 @@
import torch
import numpy as np
import matplotlib.pyplot as plt
from config import *
from dataset import get_dataloaders
from model import BuildingTCN
def evaluate_model():
_, _, test_loader, scaler_X, scaler_Y = get_dataloaders()
if test_loader is None:
raise ValueError("当前数据配置下没有可用的测试集。")
model = BuildingTCN(input_size=1, output_size=5, num_channels=CHANNELS,
kernel_size=KERNEL_SIZE, dropout=DROPOUT).to(DEVICE)
model.load_state_dict(torch.load('best_model.pth', map_location=DEVICE))
model.eval()
all_preds = []
all_targets = []
with torch.no_grad():
for inputs, targets, masks in test_loader:
inputs = inputs.to(DEVICE)
outputs = model(inputs)
all_preds.append(outputs.cpu().numpy())
all_targets.append(targets.numpy())
# Concatenate results
all_preds = np.concatenate(all_preds, axis=0)
all_targets = np.concatenate(all_targets, axis=0)
# Inverse transform to physical scale for metrics
all_preds_inv = scaler_Y.inverse_transform(all_preds.reshape(-1, len(OUTPUT_SENSORS))).reshape(all_preds.shape)
all_targets_inv = scaler_Y.inverse_transform(all_targets.reshape(-1, len(OUTPUT_SENSORS))).reshape(all_targets.shape)
print("\n=== Test Metrics (All Windows) ===")
for i, sens in enumerate(OUTPUT_SENSORS):
pred_i = all_preds_inv[:, :, i].reshape(-1)
target_i = all_targets_inv[:, :, i].reshape(-1)
mae = float(np.mean(np.abs(pred_i - target_i)))
pred_std = float(np.std(pred_i))
target_std = float(np.std(target_i))
amp_ratio = pred_std / (target_std + 1e-12)
pred_peak = float(np.max(np.abs(pred_i)))
target_peak = float(np.max(np.abs(target_i)))
peak_ratio = pred_peak / (target_peak + 1e-12)
corr = float(np.corrcoef(pred_i, target_i)[0, 1]) if len(pred_i) > 1 else float("nan")
print(
f"{sens}: MAE={mae:.4f}, Corr={corr:.4f}, "
f"AmpRatio(std_pred/std_true)={amp_ratio:.4f}, "
f"PeakRatio(max|pred|/max|true|)={peak_ratio:.4f}"
)
# 取一个 batch 的第一条序列进行可视化
sample_pred = all_preds_inv[0]
sample_target = all_targets_inv[0]
plt.figure(figsize=(15, 10))
for i, sens in enumerate(OUTPUT_SENSORS):
plt.subplot(5, 1, i+1)
plt.plot(sample_target[:, i], label='True', alpha=0.7)
plt.plot(sample_pred[:, i], label='Pred', alpha=0.7, linestyle='--')
plt.title(f'Sensor {sens} Z-axis Response (Test: Earthquake)')
plt.legend()
plt.tight_layout()
plt.savefig('test_results.png')
print("Evaluation done. Result saved to test_results.png")
if __name__ == '__main__':
evaluate_model()