mroe things

This commit is contained in:
jexck committed 2025-05-12 16:25:26 +07:00
1 parent af558c6eb5
commit f73d6af1b2
3 files changed
+103 -8

No files matched your search

+19 -1
View File
@@ -7,22 +7,31 @@ from model_train import (
evaluate_model, evaluate_model,
) )
from visualize import ( from visualize import (
plot_original_vs_scaled,
plot_predictions, plot_predictions,
plot_residuals, plot_residuals,
plot_error_hist, plot_error_hist,
plot_scatter, plot_scatter,
plot_loss_curve, plot_loss_curve,
plot_value_distribution,
visualize_sequence_window,
) )
from sklearn.model_selection import train_test_split from sklearn.model_selection import train_test_split
# Step 1: Load data # Step 1: Load data
data = load_weather_data("hanoi_weather_data.csv") data = load_weather_data("hanoi_weather_data.csv")
plot_value_distribution(data)
# Step 2: Preprocess (scale and sequence) # Step 2: Preprocess (scale and sequence)
scaled_data, scaler = scale_data(data) scaled_data, scaler = scale_data(data)
plot_original_vs_scaled(data, scaled_data)
seq_length = 50 seq_length = 50
X, y = create_sequences(scaled_data, seq_length) X, y = create_sequences(scaled_data, seq_length)
visualize_sequence_window(data["QV2M"], seq_length=10, start_idx=1000)
# Step 3: Train/test split # Step 3: Train/test split
date_index = data.index[seq_length:] date_index = data.index[seq_length:]
X_train, X_test, y_train, y_test = train_test_split( X_train, X_test, y_train, y_test = train_test_split(
@@ -31,7 +40,16 @@ X_train, X_test, y_train, y_test = train_test_split(
date_train, date_test = train_test_split(date_index, test_size=0.02, shuffle=False) date_train, date_test = train_test_split(date_index, test_size=0.02, shuffle=False)
# Step 4: Train model with gradient descent # Step 4: Train model with gradient descent
theta, losses = train_linear_regression_gd(X_train, y_train, lr=0.005, n_epochs=10000) # import math
# lr_schedule = lambda epoch: max(0.005, 0.01 * (1 + math.cos(epoch / 1000 * math.pi)) / 2)
theta, losses = train_linear_regression_gd(
X_train,
y_train,
# lr_schedule=lr_schedule,
n_epochs=10000,
)
predictions = predict_linear_regression(X_test, theta) predictions = predict_linear_regression(X_test, theta)
# Step 5: Evaluate # Step 5: Evaluate
+7 -7
View File
@@ -1,7 +1,8 @@
import numpy as np import numpy as np
from sklearn.metrics import mean_squared_error, r2_score
def train_linear_regression_gd(X_train, y_train, lr=0.01, n_epochs=1000): def train_linear_regression_gd(X_train, y_train, lr_schedule= lambda _e: 0.01, n_epochs=1000):
""" """
Train linear regression model using batch gradient descent. Train linear regression model using batch gradient descent.
@@ -15,6 +16,7 @@ def train_linear_regression_gd(X_train, y_train, lr=0.01, n_epochs=1000):
losses = [] losses = []
for epoch in range(n_epochs): for epoch in range(n_epochs):
lr = lr_schedule(epoch)
predictions = X_b @ theta predictions = X_b @ theta
errors = predictions - y_train errors = predictions - y_train
gradients = (2 / m) * X_b.T @ errors gradients = (2 / m) * X_b.T @ errors
@@ -24,7 +26,7 @@ def train_linear_regression_gd(X_train, y_train, lr=0.01, n_epochs=1000):
losses.append(loss) losses.append(loss)
if epoch % 1000 == 0: if epoch % 1000 == 0:
print(f"Epoch {epoch}: Loss = {loss:.6f}") print(f"Epoch {epoch}: Loss = {loss:.6f}, LR: {lr:.6f}")
print(f"Final Loss: {losses[-1]:.6f}") print(f"Final Loss: {losses[-1]:.6f}")
return theta, losses return theta, losses
@@ -37,9 +39,7 @@ def predict_linear_regression(X, theta):
def evaluate_model(y_true, y_pred): def evaluate_model(y_true, y_pred):
"""Evaluate MSE and R^2 manually.""" """Evaluate using sklearn's built-in MSE and R² functions."""
mse = np.mean((y_true - y_pred) ** 2) mse = mean_squared_error(y_true, y_pred)
ss_total = np.sum((y_true - np.mean(y_true)) ** 2) r2 = r2_score(y_true, y_pred)
ss_res = np.sum((y_true - y_pred) ** 2)
r2 = 1 - (ss_res / ss_total)
return mse, r2 return mse, r2
+77
View File
@@ -58,3 +58,80 @@ def plot_loss_curve(losses):
plt.grid(True) plt.grid(True)
plt.tight_layout() plt.tight_layout()
plt.show() plt.show()
def plot_original_vs_scaled(original_data, scaled_data, feature_names=None):
"""
Plot original and scaled data, aligned by date.
"""
if feature_names is None:
feature_names = original_data.columns[:2]
dates = original_data.index # Grab the datetime index
fig, axs = plt.subplots(2, 1, figsize=(12, 6), sharex=True)
for col in feature_names:
axs[0].plot(dates, original_data[col], label=f"Original {col}")
axs[0].set_title("Original Data")
axs[0].legend()
axs[0].grid(True)
for i, col in enumerate(feature_names):
col_index = original_data.columns.get_loc(col)
axs[1].plot(dates, scaled_data[:, col_index], label=f"Scaled {col}")
axs[1].set_title("Scaled Data (MinMaxScaler)")
axs[1].legend()
axs[1].grid(True)
plt.xlabel("Date")
plt.tight_layout()
plt.show()
def plot_value_distribution(data):
# import matplotlib.pyplot as plt
plt.figure(figsize=(8, 4))
plt.hist(data.iloc[:, 0], bins=40, color="skyblue", edgecolor="black")
plt.title("Distribution of Values")
plt.xlabel(data.columns[0])
plt.ylabel("Frequency")
plt.grid(True)
plt.tight_layout()
plt.show()
def visualize_sequence_window(series, seq_length=5, start_idx=0):
"""
Visualize how a sequence window is used to create X (input) and y (target).
Parameters:
series (pd.Series or np.ndarray): 1D time series data
seq_length (int): Length of input window
start_idx (int): Where to start slicing from for demo
"""
if isinstance(series, np.ndarray):
data = series
else:
data = series.to_numpy()
x_seq = data[start_idx:start_idx + seq_length]
y_val = data[start_idx + seq_length]
full_seq = np.concatenate([x_seq, [y_val]])
plt.figure(figsize=(8, 3))
plt.plot(range(start_idx, start_idx + seq_length + 1), full_seq, marker='o')
plt.axvline(x=start_idx + seq_length - 0.5, linestyle="--", color="gray")
for i in range(seq_length):
plt.text(start_idx + i, x_seq[i], f"x[{i}]", ha="center", va="bottom", fontsize=9)
plt.text(start_idx + seq_length, y_val, "y", ha="center", va="bottom", color="red", fontsize=9)
plt.title(f"Sequence Window (seq_length={seq_length}) → Predict Next")
plt.xlabel("Time Step")
plt.ylabel("Value")
plt.grid(True)
plt.tight_layout()
plt.show()