docs
This commit is contained in:
@@ -7,6 +7,9 @@ import random
|
||||
import joblib
|
||||
import numpy as np
|
||||
import lightgbm as lgb
|
||||
import pandas as pd
|
||||
import matplotlib.pyplot as plt
|
||||
import seaborn as sns
|
||||
from sklearn.preprocessing import StandardScaler
|
||||
from sklearn.metrics import mean_absolute_error
|
||||
|
||||
@@ -82,7 +85,7 @@ def train_model(working_dir: str, data_dir: str):
|
||||
key = (songno, diff)
|
||||
if key in feature_map:
|
||||
features = [safe_float(feature_map[key].get(k, 0)) for k in feature_names]
|
||||
dataset.append((features, measure))
|
||||
dataset.append((features, measure, songno, diff))
|
||||
|
||||
random.shuffle(dataset)
|
||||
if len(dataset) < (TRAIN_SIZE + VALID_SIZE):
|
||||
@@ -91,10 +94,11 @@ def train_model(working_dir: str, data_dir: str):
|
||||
train_dataset = dataset[:TRAIN_SIZE]
|
||||
valid_dataset = dataset[TRAIN_SIZE:TRAIN_SIZE + VALID_SIZE]
|
||||
|
||||
X_train = np.array([x for x, _ in train_dataset], dtype=np.float32)
|
||||
y_train = np.array([y for _, y in train_dataset], dtype=np.float32)
|
||||
X_valid = np.array([x for x, _ in valid_dataset], dtype=np.float32)
|
||||
y_valid = np.array([y for _, y in valid_dataset], dtype=np.float32)
|
||||
X_train = np.array([x for x, _, _, _ in train_dataset], dtype=np.float32)
|
||||
y_train = np.array([y for _, y, _, _ in train_dataset], dtype=np.float32)
|
||||
X_valid = np.array([x for x, _, _, _ in valid_dataset], dtype=np.float32)
|
||||
y_valid = np.array([y for _, y, _, _ in valid_dataset], dtype=np.float32)
|
||||
valid_info = [(s, d) for _, _, s, d in valid_dataset]
|
||||
|
||||
print(f"Train Size: {len(X_train)} | Valid Size: {len(X_valid)} | Features: {len(feature_names)}")
|
||||
|
||||
@@ -133,6 +137,66 @@ def train_model(working_dir: str, data_dir: str):
|
||||
|
||||
print(f"\nMAE: {mae:.4f} | Accuracy (±{ERROR_TOLERANCE}): {accuracy:.4f}")
|
||||
|
||||
# =====================================================
|
||||
# save validate.json
|
||||
# =====================================================
|
||||
validate_details = []
|
||||
for i in range(len(y_valid)):
|
||||
actual = float(y_valid[i])
|
||||
predicted = float(pred[i])
|
||||
songno, diff = valid_info[i]
|
||||
validate_details.append({
|
||||
"songno": songno,
|
||||
"diff": diff,
|
||||
"actual": actual,
|
||||
"predicted": predicted,
|
||||
"error": actual - predicted
|
||||
})
|
||||
|
||||
validate_details.sort(key=lambda x: abs(x["error"]), reverse=True)
|
||||
validate_result = {
|
||||
"summary": {
|
||||
"total_compared": len(y_valid),
|
||||
"average_absolute_error": float(mae),
|
||||
"accuracy": float(accuracy),
|
||||
"timestamp": "now",
|
||||
"script_used": "train/train_lightgbm.py"
|
||||
},
|
||||
"details": validate_details
|
||||
}
|
||||
|
||||
validate_path = os.path.join(working_dir, "validate.json")
|
||||
with open(validate_path, "w", encoding="utf-8") as f:
|
||||
json.dump(validate_result, f, indent=2, ensure_ascii=False)
|
||||
print(f"Validation result saved: {validate_path}")
|
||||
|
||||
# =====================================================
|
||||
# save validate.png
|
||||
# =====================================================
|
||||
try:
|
||||
plt.switch_backend('Agg')
|
||||
df_plot = pd.DataFrame(validate_details)
|
||||
df_plot['abs_error'] = df_plot['error'].abs()
|
||||
df_plot = df_plot.sort_values('abs_error', ascending=False).reset_index(drop=True)
|
||||
|
||||
plt.figure(figsize=(12, 6))
|
||||
sns.scatterplot(data=df_plot, x=df_plot.index, y='abs_error', alpha=0.6, s=20, color='darkorange')
|
||||
plt.axhline(0.2, color='green', linestyle='--', linewidth=0.8, alpha=0.5, label='Target (0.2)')
|
||||
plt.axhline(0.5, color='blue', linestyle='--', linewidth=0.8, alpha=0.5)
|
||||
plt.axhline(1.0, color='red', linestyle='--', linewidth=0.8, alpha=0.5)
|
||||
plt.ylim(0, max(3.5, df_plot['abs_error'].max() + 0.5))
|
||||
plt.title(f'Validation Absolute Error - {os.path.basename(working_dir)}', fontsize=14)
|
||||
plt.xlabel('Samples (Sorted by Error Magnitude)', fontsize=12)
|
||||
plt.ylabel('Absolute Error', fontsize=12)
|
||||
plt.grid(True, axis='y', alpha=0.3)
|
||||
|
||||
plot_path = os.path.join(working_dir, "validate.png")
|
||||
plt.savefig(plot_path)
|
||||
plt.close()
|
||||
print(f"Validation plot saved: {plot_path}")
|
||||
except Exception as e:
|
||||
print(f"[WARN] Failed to create validation plot: {e}")
|
||||
|
||||
joblib.dump(model, model_path)
|
||||
joblib.dump(scaler, scaler_path)
|
||||
with open(feature_names_path, "w", encoding="utf-8") as f:
|
||||
|
||||
Reference in New Issue
Block a user