Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
Empty file.
120 changes: 120 additions & 0 deletions .history/blueprint_20250805161422.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
Of course. It's an excellent idea to document the process. This creates a clear narrative of the project, which is invaluable for understanding, reporting, and building upon your work.

Here is a comprehensive blueprint detailing our journey from A to Z.

Project Blueprint: Generating Synthetic Time-Series Data for Transaction Forecasting

Author: [Your Name]
Date: August 5, 2025
Objective: To extend a limited historical transaction dataset (2011-2016) by generating high-quality, realistic synthetic data for the period 2017 onwards. This final, combined dataset will be used to train an XGBoost forecasting model.

Part 1: The Initial Problem & First Approach
1.1. The Challenge: Data Scarcity

Our initial dataset, agg_trans_rows.csv, contained valuable transaction data but was limited to a 6-year historical window (72 data points per city). For robust time-series forecasting, especially with complex models like XGBoost, this limited history is a significant handicap. It makes it difficult for a model to learn long-term trends, seasonality, and complex patterns, leading to a high risk of poor generalization.

1.2. The Proposed Solution: Synthetic Data Generation

To overcome this limitation, we chose to employ a Time-series Generative Adversarial Network (TimeGAN). The goal was to train the TimeGAN on the real historical data and use it to generate a synthetic continuation of the time series, effectively creating a much larger dataset for our forecasting model.

1.3. First Approach: A Single, Combined Model

Our initial strategy was to train a single TimeGAN model on the data from all five cities combined.

Data Preparation: The 'city' column was one-hot encoded, creating binary features (e.g., city_Beirut, city_Tripoli) so the model could learn to associate transaction patterns with specific locations.

Merging: The plan was to generate a single synthetic data file and then merge it with the original data using pd.concat.

Part 2: The Failure of the First Approach & Diagnosis
2.1. Initial Merge and Visual Analysis

Upon concatenating the real data with the first batch of synthetic data, visual analysis immediately revealed critical failures. We plotted the transaction values over time for each city, marking the "merge point" between real and synthetic data.

Plot Analysis:

Unnatural Jumps (Structural Break): Every city's plot showed a massive, instantaneous jump or drop in value at the merge point. For example, Beirut's transaction values plummeted, while Tripoli's exploded upwards. This indicated the synthetic data was not on the same scale as the real data.

Change in Data Character: The synthetic data was visibly different. While the real data was noisy and volatile, the synthetic data was overly smooth, showing artificial-looking straight lines and simplistic patterns.

Conclusion: The merged dataset was not a continuous or believable time series. Feeding this into a forecasting model would lead to nonsensical results.

2.2. Root Cause Analysis: The GAN's Output

To understand the failure, we analyzed the diagnostic plots from the TimeGAN training process (PCA and t-SNE) and the quantitative metrics.

PCA/t-SNE Plot Analysis:

Mode Collapse: The plots clearly showed "mode collapse." The synthetic data points (blue) were tightly clumped into dense, repetitive structures, while the real data points (red) were scattered much more widely.

Interpretation: This meant the GAN was not learning the full diversity of the real data. Instead, it found a few "easy" patterns (modes) and generated them over and over, leading to the overly smooth and simplistic time series we observed.

Metric Analysis:

The discriminative score was very low (~0.08). A perfect score is 0.5, so this indicated that a simple classifier could distinguish between real and fake data with over 90% accuracy, confirming the poor quality of the synthetic data.

2.3. Identifying the Core Bugs

Through a process of iterative debugging, we identified three distinct problems:

The Scaling Bug: The primary reason for the massive value jumps was an error in the data transformation process. The values used to scale the data before training were not being correctly used to un-scale the data after generation. We discovered the original code used a custom NumPy function for scaling that did not save the min and max values needed for a precise inverse transformation.

The Data Mismatch Bug: The attempt to reconstruct the 'city' column from the GAN's one-hot encoded output was unreliable due to mode collapse. The idxmax() function was misattributing data to the wrong cities, scrambling the results (e.g., assigning Tripoli's low-value patterns to Beirut).

The Training Instability Bug: The model's tendency for "mode collapse" showed that training on all cities at once was too complex a task, preventing the GAN from learning the unique patterns of each individual city.

Part 3: The Successful Solution - "One Model Per City"

Based on the diagnosis, we pivoted to a more robust and granular strategy.

3.1. The Strategy: Isolate and Conquer

Instead of one complex model, we would train five separate, simpler TimeGAN models—one for each city. This approach ensures:

Each model only has to learn the specific patterns of one city, dramatically reducing complexity and the risk of mode collapse.

There is no ambiguity in labeling. Data generated by the "Beirut" model is guaranteed to be Beirut data.

3.2. The Corrected Workflow

Data Segregation: The original dataset was split into five separate files (e.g., Beirut_data.csv, Tripoli_data.csv), each containing only the two numeric columns (transaction_number, transaction_value).

Fixing the Scaling Process: We modified data_loading.py. The custom MinMaxScaler function was adjusted to not only return the scaled data but also the min and max values it calculated. These values were then saved to a city-specific file (e.g., min_max_Beirut.npz). This preserved the exact "key" needed for un-scaling.

Iterative Training: We ran the main_timegan.py script five times, once for each city, using the --data_name argument. After each run, we renamed the output files (e.g., synthetic_data_Beirut.csv).

Corrected Post-Processing: We created a new script, process_and_combine.py, which:

Looped through each city.

Loaded the specific raw synthetic data for that city.

Loaded the corresponding min_max_...npz file.

Correctly un-scaled the data to its original magnitude.

Added the date and city columns.

Finally, concatenated the five clean, un-scaled city datasets into a single master file: final_usable_synthetic_data_COMBINED.csv.

3.3. Understanding the Hyperparameters: The Role of seq_len

A key hyperparameter in this process is the sequence length (seq_len). This parameter defines the size of the "window" the model looks at to learn temporal patterns. For our monthly data:

A seq_len of 12 would allow the model to see one full year of data at a time, helping it learn yearly seasonality.

A seq_len of 24 (which we used) is often better, as it allows the model to see two full seasonal cycles. This gives it more context to understand the year-over-year trends and patterns, leading to more robust learning. The 72 rows of original data are converted into 72 - 24 + 1 = 49 overlapping training sequences, which is the actual number of samples the GAN learns from.

Part 4: Final Results & Next Steps

The "One Model Per City" approach was a complete success.

Final Analysis:

Visual Validation: The PCA and t-SNE plots for each individual city model showed excellent mixing between the real and synthetic data, indicating that mode collapse was overcome.

Quantitative Validation: Discriminative scores improved significantly (e.g., from ~0.08 to ~0.15), providing numerical proof of higher-quality data generation.

Data Integrity: The final combined file contains correctly scaled values assigned to the correct cities, with a total number of rows (~5880) that mathematically matches the generation process.

Next Steps:
The successfully generated synthetic dataset is now ready. It will be merged with the original agg_trans_rows.csv to create a final, extended time-series dataset. This dataset will serve as the foundation for training our XGBoost forecasting model. Further experiments involving longer training iterations (e.g., 20,000+) can be conducted to potentially improve the data quality even further.
Loading