Skip to content
Snippets Groups Projects
Commit 2f3b855c authored by Milson Sung's avatar Milson Sung
Browse files

update 07.03

parent 2ab36591
No related branches found
No related tags found
No related merge requests found
...@@ -18,7 +18,7 @@ logger = logging.getLogger(__name__) ...@@ -18,7 +18,7 @@ logger = logging.getLogger(__name__)
def train_model(tuner_type, request, project_path, train_data_file, scaler_x_file, scaler_y_file): def train_model(tuner_type, request, project_path, train_data_file, scaler_x_file, scaler_y_file):
"""Function to train the model for a given tuner type.""" """Function to train the model for a given tuner type."""
try: try:
model_path = os.path.join(MODEL_DIRECTORY, request.project_name) model_path = os.path.join(MODEL_DIRECTORY, f"{request.project_name}_{request.tuner}")
os.makedirs(model_path, exist_ok=True) os.makedirs(model_path, exist_ok=True)
regressor = AutoMLRegressor( regressor = AutoMLRegressor(
...@@ -74,7 +74,7 @@ def get_params(project_name: str): ...@@ -74,7 +74,7 @@ def get_params(project_name: str):
def start_training(request: TrainRequest): def start_training(request: TrainRequest):
"""Start training for the selected project.""" """Start training for the selected project."""
project_path = os.path.join(PROCESSED_DIRECTORY, request.project_name) project_path = os.path.join(PROCESSED_DIRECTORY, request.project_name)
model_path = os.path.join(MODEL_DIRECTORY, request.project_name) model_path = os.path.join(MODEL_DIRECTORY, f"{request.project_name}_{request.tuner}")
params_file = os.path.join(project_path, "params.json") params_file = os.path.join(project_path, "params.json")
train_data_file = os.path.join(project_path, "train_data.npz") train_data_file = os.path.join(project_path, "train_data.npz")
scaler_x_file = os.path.join(project_path, "scaler_X.pkl") scaler_x_file = os.path.join(project_path, "scaler_X.pkl")
......
import os
import json
from fastapi import APIRouter, HTTPException
from app.config import MODEL_DIRECTORY
router = APIRouter()
@router.get("/models")
def list_models():
"""Returns a list of available models in MODEL_DIRECTORY."""
try:
models = [d for d in os.listdir(MODEL_DIRECTORY) if os.path.isdir(os.path.join(MODEL_DIRECTORY, d))]
return {"models": models}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.get("/data/{model_name}")
def get_model_visualization_data(model_name: str):
"""Fetches MAE vs. Trials and MAE vs. Training Time data for the selected model."""
model_path = os.path.join(MODEL_DIRECTORY, model_name)
if not os.path.exists(model_path):
raise HTTPException(status_code=404, detail="Model not found")
trial_mae = []
training_time = None
# Load training time
training_time_path = os.path.join(model_path, "training_time.json")
if os.path.exists(training_time_path):
with open(training_time_path, "r") as f:
training_time_data = json.load(f)
training_time = training_time_data.get("training_time", None)
# Load trial MAE values
for trial_dir in sorted(os.listdir(model_path)):
trial_path = os.path.join(model_path, trial_dir, "trial.json")
if os.path.exists(trial_path):
try:
with open(trial_path, "r") as f:
trial_data = json.load(f)
val_loss_observations = trial_data.get("metrics", {}).get("metrics", {}).get("val_loss", {}).get("observations", [])
if val_loss_observations:
val_loss_value = val_loss_observations[0].get("value", [])
if val_loss_value:
trial_mae.append(val_loss_value[0])
except json.JSONDecodeError:
continue
if not trial_mae:
raise HTTPException(status_code=400, detail="No valid MAE data found for the model")
return {
"trial_mae": trial_mae,
"training_time": training_time
}
...@@ -31,9 +31,9 @@ class AutoMLRegressor: ...@@ -31,9 +31,9 @@ class AutoMLRegressor:
self.project_name = project_name self.project_name = project_name
self.models = {} self.models = {}
# Define project directories under PROCESSED_DIRECTORY # Define project directories under PROCESSED_DIRECTORY, MODEL_DIRECTORY
self.project_dir = os.path.join(PROCESSED_DIRECTORY, project_name) self.project_dir = os.path.join(PROCESSED_DIRECTORY, project_name)
self.model_dir = os.path.join(MODEL_DIRECTORY, project_name) self.model_dir = os.path.join(MODEL_DIRECTORY)
# Ensure the directories exist # Ensure the directories exist
os.makedirs(self.project_dir, exist_ok=True) os.makedirs(self.project_dir, exist_ok=True)
...@@ -76,6 +76,7 @@ class AutoMLRegressor: ...@@ -76,6 +76,7 @@ class AutoMLRegressor:
# Initialize the AutoKeras StructuredDataRegressor with the specified tuner # Initialize the AutoKeras StructuredDataRegressor with the specified tuner
regressor = ak.StructuredDataRegressor( regressor = ak.StructuredDataRegressor(
project_name=f'{self.project_name}_{tuner_type}', # Create a project folder based on tuner type project_name=f'{self.project_name}_{tuner_type}', # Create a project folder based on tuner type
directory=self.model_dir, # Save the trained model under model directory
tuner=tuner_type, tuner=tuner_type,
max_trials=100, # Maximum number of trials for AutoML max_trials=100, # Maximum number of trials for AutoML
overwrite=True, overwrite=True,
...@@ -88,16 +89,12 @@ class AutoMLRegressor: ...@@ -88,16 +89,12 @@ class AutoMLRegressor:
regressor.fit(self.X_train, self.y_train, epochs=100, validation_split=0.1) # Train with 100 epochs regressor.fit(self.X_train, self.y_train, epochs=100, validation_split=0.1) # Train with 100 epochs
end_time = time.time() end_time = time.time()
# Save the trained model under the model directory
model_save_path = os.path.join(self.model_dir, f'{tuner_type}_best_model')
regressor.export_model().save(model_save_path)
# Store the trained model and log the training time # Store the trained model and log the training time
self.models[tuner_type] = regressor self.models[tuner_type] = regressor
training_time = end_time - start_time training_time = end_time - start_time
# Save the training time to a JSON file # Save the training time to a JSON file
training_time_path = os.path.join(self.model_dir, f'{tuner_type}_training_time.json') training_time_path = os.path.join(self.model_dir, f'{self.project_name}_{tuner_type}', 'training_time.json')
with open(training_time_path, 'w') as f: with open(training_time_path, 'w') as f:
json.dump({'training_time': training_time}, f) json.dump({'training_time': training_time}, f)
...@@ -116,7 +113,7 @@ class AutoMLRegressor: ...@@ -116,7 +113,7 @@ class AutoMLRegressor:
print(f"Loading best model for tuner: {tuner_type}") print(f"Loading best model for tuner: {tuner_type}")
# Load the best model from the project folder # Load the best model from the project folder
best_model = load_model(os.path.join(self.model_dir, f'{tuner_type}_best_model')) best_model = load_model(os.path.join(self.model_dir, f'{self.project_name}_{tuner_type}','best_model'))
predictions = best_model.predict(X_test) predictions = best_model.predict(X_test)
# Inverse transform the predictions and actual values to the original scale # Inverse transform the predictions and actual values to the original scale
......
from fastapi import HTTPException
import os
import json
import asyncio
from app.schemas.train import TrainRequest
from app.services.automl import AutoMLRegressor
from app.config import PROCESSED_DIRECTORY
import logging
import pandas as pd
import json
import random
import os
# Method 1: Merging two json
# scenario_analysis_result_MAN_Test_hl.json
# scenario_analysis_result_MAN_Test_hl_new.json
# def merge_json_files(file1, file2, output_file):
# # Load both JSON files
# df1 = pd.read_json('scenario_analysis_result_MAN_Test_hl_new.json') # First file (ID_0 to ID_959)
# df2 = pd.read_json('scenario_analysis_result_MAN_Test_hl.json') # Second file (ID_0 to ID_3839)
# # Reset index for both to avoid duplicate indices
# df1 = df1.reset_index(drop=True)
# df2 = df2.reset_index(drop=True)
# # Concatenate both DataFrames
# combined_df = pd.concat([df1, df2], ignore_index=True)
# # Assign new unique ID from 0 to 4559
# combined_df.insert(0, "ID", [f"ID_{i}" for i in range(len(combined_df))])
# # Save to a new JSON file
# combined_df.to_json(output_file, orient="records", indent=4)
# print(f"Merged file saved as {output_file} with new unique IDs from ID_0 to ID_4559")
# if __name__ == "__main__":
# merge_json_files("scenario_analysis_result_MAN_Test_hl_new.json", "scenario_analysis_result_MAN_Test_hl.json", "combined4800.json")
# Method 2: Adding a new entry called EnergyConsumed [kWh]
# def modify_json_file(file_path):
# try:
# # Load JSON data from the file
# with open(file_path, "r") as file:
# data = json.load(file)
# # Ensure the JSON data is a list of dictionaries (or it can be another structure)
# if isinstance(data, list):
# for entry in data:
# if isinstance(entry, dict):
# # Check if the entry has an "ID" key
# if "ID" in entry:
# # Add the "EnergyConsumed [kWh]" field with a random value between 80 - 100
# entry["EnergyConsumed [kWh]"] = round(random.uniform(80, 100), 2)
# # Save the modified JSON back to the file
# with open(file_path, "w") as file:
# json.dump(data, file, indent=4)
# print(f"✅ Successfully updated {file_path}")
# else:
# print("⚠️ JSON structure is not a list of dictionaries. No changes made.")
# except FileNotFoundError:
# print("❌ Error: File not found.")
# except json.JSONDecodeError:
# print("❌ Error: Invalid JSON format.")
# if __name__ == "__main__":
# # Ensure you pass the correct file path here
# file_path = input("Enter the path to the JSON file (e.g., combined4800.json): ")
# modify_json_file(file_path)
# Method 3: Calculating a new entry call CFP [kgC02/kWh]
def process_data(input_file, output_file):
# Load the existing data from the JSON file
with open(input_file, 'r') as f:
data = json.load(f)
# Check if the data is a list (not a dictionary)
if isinstance(data, list):
# Iterate over each item in the list
for item in data:
# Check if 'EnergyConsumed [kWh]' exists and calculate 'CFP [kgC02/kWh]'
if 'EnergyConsumed [kWh]' in item:
energy_consumed = item['EnergyConsumed [kWh]']
cfp_value = energy_consumed * 0.321
item['CFP [kgC02/kWh]'] = cfp_value # Add new value with the correct key
else:
print("Error: The data is not in the expected format (list).")
return
# Save the updated data with the new values into a new JSON file
with open(output_file, 'w') as f:
json.dump(data, f, indent=4)
print(f"Updated data saved to {output_file}")
# Main function
def main():
input_file = 'combined4800.json' # Replace with your input file path
output_file = 'modified4800.json' # Replace with your desired output file path
process_data(input_file, output_file)
if __name__ == "__main__":
main()
\ No newline at end of file
Source diff could not be displayed: it is too large. Options to address this: view the blob.
...@@ -11,15 +11,18 @@ ...@@ -11,15 +11,18 @@
}, },
"dependencies": { "dependencies": {
"@tailwindcss/postcss": "^4.0.6", "@tailwindcss/postcss": "^4.0.6",
"@tailwindcss/vite": "^4.0.6", "@tailwindcss/vite": "^4.0.9",
"axios": "^1.7.9", "axios": "^1.7.9",
"chart.js": "^4.4.7", "chart.js": "^4.4.7",
"plotly.js": "^3.0.1",
"plotly.js-dist": "^3.0.1",
"prop-types": "^15.8.1", "prop-types": "^15.8.1",
"react": "^18.3.1", "react": "^18.3.1",
"react-chartjs-2": "^5.3.0", "react-chartjs-2": "^5.3.0",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-plotly.js": "^2.6.0",
"react-router-dom": "^7.1.5", "react-router-dom": "^7.1.5",
"tailwindcss": "^4.0.6" "tailwindcss": "^4.0.9"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.17.0", "@eslint/js": "^9.17.0",
......
import React, { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import axios from "axios"; import axios from "axios";
function Train() { function Train() {
...@@ -132,7 +132,7 @@ function Train() { ...@@ -132,7 +132,7 @@ function Train() {
onClick={handleTrainModel} onClick={handleTrainModel}
disabled={loading} disabled={loading}
> >
{loading ? "Training..." : "Start Training"} {loading ? "Training..." : "Start Training & Postprocessing"}
</button> </button>
</div> </div>
......
import React, { useState, useEffect } from "react";
import axios from "axios";
import Plot from "react-plotly.js";
const Visualize = () => {
const [models, setModels] = useState([]);
const [selectedModels, setSelectedModels] = useState([]);
const [trialMAE, setTrialMAE] = useState({});
const [trainingTime, setTrainingTime] = useState({});
const [error, setError] = useState("");
// Fetch available models
useEffect(() => {
axios
.get("http://localhost:8000/visualize/models")
.then((res) => setModels(res.data.models || []))
.catch(() => setError("Failed to load models."));
}, []);
// Fetch visualization data for selected models
const handleVisualize = async () => {
if (selectedModels.length === 0) {
setError("Please select at least one model.");
return;
}
setError("");
const newTrialMAE = {};
const newTrainingTime = {};
await Promise.all(
selectedModels.map(async (model) => {
try {
const res = await axios.get(`http://localhost:8000/visualize/data/${model}`);
newTrialMAE[model] = res.data.trial_mae || [];
newTrainingTime[model] = res.data.training_time || 0;
} catch {
setError(`Failed to load data for ${model}`);
}
})
);
setTrialMAE(newTrialMAE);
setTrainingTime(newTrainingTime);
};
const handleModelChange = (e) => {
const selectedOptions = Array.from(e.target.selectedOptions, (option) => option.value);
setSelectedModels(selectedOptions);
};
return (
<div className="container mx-auto p-6 bg-gray-50 rounded-lg shadow-md">
<h2 className="text-3xl font-semibold text-center mb-6">Model Visualization</h2>
{error && <p className="text-red-500">{error}</p>}
{/* Model selection */}
<div className="mb-6">
<label className="block text-lg font-medium mb-2">Select Models</label>
<select
multiple
value={selectedModels}
onChange={handleModelChange}
className="block w-full px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-400"
>
{models.map((model) => (
<option key={model} value={model}>
{model}
</option>
))}
</select>
</div>
{/* Button to fetch and visualize data */}
<button
onClick={handleVisualize}
className="w-full bg-blue-500 text-white py-2 rounded-md hover:bg-blue-600 focus:outline-none"
>
Visualize
</button>
{/* Display graphs in a 2x2 grid */}
{selectedModels.length > 0 && (
<div className="mt-6 grid grid-cols-1 md:grid-cols-2 gap-6">
{selectedModels.map((model) => (
<React.Fragment key={model}>
{/* MAE vs Trial Graph */}
{trialMAE[model] && trialMAE[model].length > 0 && (
<div className="p-4 bg-white rounded-lg shadow-md">
<h4 className="text-lg font-semibold text-center">{`${model} - MAE vs. Trial`}</h4>
<Plot
data={[
{
x: Array.from({ length: trialMAE[model].length }, (_, i) => i + 1),
y: trialMAE[model],
type: "scatter",
mode: "lines+markers",
marker: { color: "blue" },
},
]}
layout={{
title: "MAE vs. Trial",
xaxis: { title: "Trial Number" },
yaxis: { title: "MAE" },
height: 400,
width: 500,
}}
/>
</div>
)}
{/* MAE vs Training Time Graph */}
{trainingTime[model] !== undefined && (
<div className="p-4 bg-white rounded-lg shadow-md">
<h4 className="text-lg font-semibold text-center">{`${model} - MAE vs. Training Time`}</h4>
<Plot
data={[
{
x: [model],
y: [Math.min(...trialMAE[model] || [0])], // Best MAE value for this model
type: "bar",
name: "Best MAE",
marker: { color: "blue" },
yaxis: "y1",
},
{
x: [model],
y: [trainingTime[model]], // Training time for this model
type: "bar",
name: "Training Time (s)",
marker: { color: "orange" },
yaxis: "y2",
},
]}
layout={{
title: "MAE vs. Training Time",
barmode: "group",
xaxis: { title: "Model" },
yaxis: {
title: "Best MAE",
showgrid: false,
},
yaxis2: {
title: "Training Time (s)",
overlaying: "y",
side: "right",
showgrid: false,
anchor: "x",
},
height: 400,
width: 500,
}}
/>
</div>
)}
</React.Fragment>
))}
</div>
)}
</div>
);
};
export default Visualize;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment