From 6fdf53034a048dd712a80a541f540a19ddcb7caa Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 24 Jun 2025 20:49:05 +0000 Subject: [PATCH 1/6] feat: Implement conditional text generation for LLMGenerator Adds functionality to LLMGenerator to generate novel text values for specified columns, conditioned on the values of other attribute columns, while attempting to preserve attribute distributions. Key changes: - Modified `SamplerLLM` to accept `text_generating_columns` and `conditional_columns` parameters. - Updated `generate_data` to handle conditional logic, using `be_great.impute` for non-text columns and direct LLM prompting via a new `_generate_via_prompt` helper for text columns. - Implemented novelty checks for generated text. - Added unit tests (mocked due to environment constraints for full runs) for the new functionality. - Updated README.md with documentation for the new parameters and an example. Note: Full testing was impeded by sandbox environment disk space limitations preventing complete dependency installation (primarily PyTorch and its CUDA components). --- README.md | 43 +++++++++ requirements.txt | 9 +- src/tabgan/sampler.py | 216 ++++++++++++++++++++++++++++++++++++++---- tests/test_sampler.py | 180 +++++++++++++++++++++++++++++++++++ 4 files changed, 425 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 6261032..451dcb6 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,8 @@ All samplers (`OriginalGenerator`, `GANGenerator`, `ForestDiffusionGenerator`, ` ```python {"batch_size": 32, "epochs": 4, "llm": "distilgpt2", "max_length": 500} ``` +* **text_generating_columns**: `list` (default: `None`) - Specific to `LLMGenerator`. A list of column names for which new, plausible text values should be generated (e.g., names, descriptions). Requires `conditional_columns` to be set. +* **conditional_columns**: `list` (default: `None`) - Specific to `LLMGenerator`. A list of column names that the generation of `text_generating_columns` should be conditioned upon (e.g., generating names based on gender). The available samplers are: 1. **`GANGenerator`**: Utilizes the Conditional Tabular GAN (CTGAN) architecture, known for effectively modeling tabular data distributions and handling mixed data types (continuous and discrete). It learns the data distribution and generates synthetic samples that mimic the original data. @@ -114,6 +116,47 @@ new_train_gan_all_params, new_target_gan_all_params = GANGenerator( use_adversarial=True ) +# Example for generating new text values with LLMGenerator +name_train_df = pd.DataFrame({ + "Name": ["Anna", "Maria", "Ivan", "Sergey", "Elena", "Dmitry"], + "Gender": ["F", "F", "M", "M", "F", "M"], + "Age": [25, 30, 35, 40, 28, 42] +}) +name_target_df = pd.DataFrame({"Salary": [50, 60, 70, 80, 55, 85]}) # Example target +name_test_df = pd.DataFrame({ + "Name": ["Olga", "Boris"], # Test data for post-processing context if enabled + "Gender": ["F", "M"], + "Age": [28, 32] +}) + + +# Initialize LLMGenerator for conditional text generation +# Note: For actual generation, ensure the chosen LLM in gen_params is powerful enough +# and epochs/batch_size are set appropriately for your dataset size. +# Smaller models like 'distilgpt2' might require more careful prompt engineering or fine-tuning +# for high-quality, highly conditional text generation. +llm_text_generator = LLMGenerator( + text_generating_columns=["Name"], + conditional_columns=["Gender"], + gen_x_times=1, # Generate same number of new samples as original + gen_params={"batch_size": 4, "epochs": 1, "llm": "distilgpt2", "max_length": 50}, # Adjust params as needed + is_post_process=False # Disable post-processing for this example to focus on generation +) + +# Generate new data. Target can be None if not applicable to your generation task. +# For LLMGenerator with text generation, target is often not directly used in the text prompting itself, +# but the GReaT model is still trained on all columns passed in train_df (which includes target if added). +new_names_df, new_names_target_df = llm_text_generator.generate_data_pipe( + name_train_df, + name_target_df, # Pass target if you want it in the output and trained GReaT model + name_test_df, # test_df is used if is_post_process=True or adversarial filtering is on + only_generated_data=True +) + +print("\\nGenerated data with new names:") +print(new_names_df) +# print(new_names_target_df) # if target was used + ``` Thus, you may use this library to improve your dataset quality: diff --git a/requirements.txt b/requirements.txt index 42c07bb..7fb6002 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,13 +1,12 @@ -scipy>=1.4.1 +scipy>=1.12.0 category_encoders>=2.6.3 -numpy>=1.22.0 torch>=1.6.0 -pandas>=1.2.2 +pandas>=2.2.0 lightgbm>=2.2.3 scikit_learn>=1.5.2 torchvision>=0.4.2 -numpy>=2.0 -python-dateutil==2.8.1 +numpy>=1.23.1 +python-dateutil>=2.8.2 tqdm>=4.61.1 xgboost>=2.0.0 be-great==0.0.8 \ No newline at end of file diff --git a/src/tabgan/sampler.py b/src/tabgan/sampler.py index 9f59a73..3f8e467 100644 --- a/src/tabgan/sampler.py +++ b/src/tabgan/sampler.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- import logging +import numpy as np import warnings from typing import Tuple @@ -80,6 +81,8 @@ def __init__( pregeneration_frac: float = 2, only_generated_data: bool = False, gen_params: dict = {"batch_size": 45, 'patience': 25, "epochs": 50, "llm": "distilgpt2"}, + text_generating_columns: list = None, + conditional_columns: list = None, ): """ @@ -97,17 +100,26 @@ def __init__( concatenating input train dataframe. @param gen_params: dict params for GAN training. Only works for SamplerGAN, ForestDiffusionGenerator, LLMGenerator. + @param text_generating_columns: list = None - List of column names for which new text values should be generated. + @param conditional_columns: list = None - List of column names to condition the generation of text_generating_columns. """ - self.gen_x_times = gen_x_times - self.cat_cols = cat_cols - self.is_post_process = is_post_process - self.bot_filter_quantile = bot_filter_quantile - self.top_filter_quantile = top_filter_quantile - self.adversarial_model_params = adversarial_model_params - self.pregeneration_frac = pregeneration_frac - self.only_generated_data = only_generated_data - self.gen_params = gen_params - self.TEMP_TARGET = "TEMP_TARGET" + super().__init__( + gen_x_times=gen_x_times, + cat_cols=cat_cols, + bot_filter_quantile=bot_filter_quantile, + top_filter_quantile=top_filter_quantile, + is_post_process=is_post_process, + adversarial_model_params=adversarial_model_params, + pregeneration_frac=pregeneration_frac, + only_generated_data=only_generated_data, + gen_params=gen_params, + ) + self.text_generating_columns = text_generating_columns + self.conditional_columns = conditional_columns + # Ensure TEMP_TARGET is initialized here if not by super() + if not hasattr(self, 'TEMP_TARGET'): + self.TEMP_TARGET = "TEMP_TARGET" + @staticmethod def preprocess_data_df(df) -> pd.DataFrame: @@ -378,21 +390,189 @@ def generate_data( ) -> Tuple[pd.DataFrame, pd.DataFrame]: self._validate_data(train_df, target, test_df) self.check_params() + + # Use a copy to avoid modifying the original train_df if target is added + current_train_df = train_df.copy() if target is not None: - train_df[self.TEMP_TARGET] = target + current_train_df[self.TEMP_TARGET] = target + logging.info("Fitting LLM model") is_fp16 = torch.cuda.is_available() - model = GReaT(llm=self.gen_params["llm"], batch_size=self.gen_params["batch_size"], - epochs=self.gen_params["epochs"], fp16=is_fp16) - model.fit(train_df) + # Ensure GReaT is imported + try: + from be_great import GReaT + except ImportError: + raise ImportError("be_great library is not installed. Please install it to use LLMGenerator.") + + great_model_instance = GReaT(llm=self.gen_params["llm"], batch_size=self.gen_params["batch_size"], + epochs=self.gen_params["epochs"], fp16=is_fp16) + great_model_instance.fit(current_train_df) + logging.info("Finished training LLM model") + + device = "cuda" if torch.cuda.is_available() else "cpu" # Needed for _generate_via_prompt + + if self.text_generating_columns and self.conditional_columns: + logging.info("Starting conditional generation of text columns.") + num_samples_to_generate = int(self.gen_x_times * train_df.shape[0]) + + original_unique_text_values = {} + for col in self.text_generating_columns: + if col not in current_train_df.columns: + raise ValueError(f"Text generating column '{col}' not found in training data.") + original_unique_text_values[col] = set(current_train_df[col].unique()) + + attribute_distributions = {} + for col in self.conditional_columns: + if col not in current_train_df.columns: + raise ValueError(f"Conditional column '{col}' not found in training data.") + attribute_distributions[col] = current_train_df[col].value_counts(normalize=True) + + generated_rows = [] + all_train_columns = current_train_df.columns.tolist() + + for _ in range(num_samples_to_generate): + current_row_data = {} + + # 1. Sample conditional attributes + for attr_col in self.conditional_columns: + dist = attribute_distributions[attr_col] + current_row_data[attr_col] = np.random.choice(dist.index, p=dist.values) + + # 2. Generate other non-text columns using be_great.impute + # Create a template row with NaNs for be_great to fill + row_template_for_impute = pd.DataFrame(columns=all_train_columns, index=[0]) + for col in all_train_columns: + if col in current_row_data: # Conditional column already sampled + row_template_for_impute.loc[0, col] = current_row_data[col] + elif col not in self.text_generating_columns: # Column to be imputed + row_template_for_impute.loc[0, col] = np.nan + # else: text_generating_columns will be filled later by _generate_via_prompt + + # Impute NaNs for non-text, non-conditional columns + # Note: be_great.impute might expect specific formatting or might modify inplace. + # This part might need adjustment based on be_great's exact API for single row imputation. + # For now, assuming it returns a DataFrame with NaNs filled. + # Also, max_length might need to be dynamic or a class parameter. + imputed_full_row_df = great_model_instance.impute(row_template_for_impute.copy(), + max_length=self.gen_params.get("max_length", 500)) + + for col in all_train_columns: + if col not in self.text_generating_columns and col not in current_row_data: + current_row_data[col] = imputed_full_row_df.loc[0, col] + + # 3. Generate novel text values + for text_col in self.text_generating_columns: + # Construct prompt + prompt_parts = [] + for cond_col in self.conditional_columns: + prompt_parts.append(f"{cond_col}: {current_row_data[cond_col]}") + # Include other relevant, already generated/imputed columns in the prompt + for other_col in all_train_columns: + if other_col not in self.text_generating_columns and other_col not in self.conditional_columns and other_col in current_row_data: + # Limit length of values in prompt + val_str = str(current_row_data[other_col]) + if len(val_str) > 30: val_str = val_str[:27] + "..." + prompt_parts.append(f"{other_col}: {val_str}") + + prompt = ", ".join(prompt_parts) + f", Generate {text_col}: " + + generated_text_candidate = None + max_retries = 10 + for _retry_attempt in range(max_retries): + # Placeholder for now, will be implemented in next step + # Pass great_model_instance.model and great_model_instance.tokenizer + generated_text_candidate = self._generate_via_prompt(prompt, great_model_instance, device=device) + if generated_text_candidate not in original_unique_text_values[text_col]: + break + else: # Max retries reached + logging.warning(f"Max retries reached for generating novel text for {text_col}. Using last candidate.") + current_row_data[text_col] = generated_text_candidate + + # Ensure all columns are present in the order of original train_df (excluding TEMP_TARGET for generated_df) + ordered_row = {col: current_row_data.get(col) for col in train_df.columns} # Uses original train_df columns + if target is not None and self.TEMP_TARGET in current_row_data: # Handle target if it was part of generation + ordered_row[self.TEMP_TARGET] = current_row_data[self.TEMP_TARGET] + + generated_rows.append(ordered_row) + + generated_df = pd.DataFrame(generated_rows) + # Align columns with current_train_df (which includes TEMP_TARGET if target was not None) + # This ensures generated_df has the TEMP_TARGET before handle_generated_data if it was part of training + generated_df = generated_df.reindex(columns=current_train_df.columns) - logging.info("Finished training ForestDiffusionModel") - device = "cuda" if torch.cuda.is_available() else "cpu" + else: + logging.info("Starting standard LLM sampling.") + generated_df = great_model_instance.sample(int(self.gen_x_times * current_train_df.shape[0]), + device=device, + max_length=self.gen_params["max_length"]) + + # current_train_df already includes TEMP_TARGET if target was not None + # generated_df should also have TEMP_TARGET column if it was part of generation process (e.g. via impute or if it was a regular col) + # handle_generated_data expects train_df without target, and generated_df potentially with target - generated_df = model.sample(int(self.gen_x_times * train_df.shape[0]), device=device, - max_length=self.gen_params["max_length"]) + # If target was added to current_train_df, we pass the original train_df (without target) + # to handle_generated_data, and generated_df (which might contain the target column from generation) return self.handle_generated_data(train_df, generated_df, only_generated_data) + def _generate_via_prompt(self, prompt: str, great_model_instance, device: str, max_tokens_to_generate=50) -> str: + """ + Generates text using the underlying LLM from the GReaT model instance based on a given prompt. + """ + llm_model = great_model_instance.model + tokenizer = great_model_instance.tokenizer + + if llm_model is None or tokenizer is None: + logging.error("LLM model or tokenizer not available in GReaT instance.") + return "" # Or raise an error + + # Ensure model is on the correct device (might already be, but good to ensure) + llm_model.to(device) + + inputs = tokenizer(prompt, return_tensors="pt", truncation=True, max_length=tokenizer.model_max_length - max_tokens_to_generate) + input_ids = inputs.input_ids.to(device) + attention_mask = inputs.attention_mask.to(device) + + # Generate output tokens + # Common parameters for generate: + # - no_repeat_ngram_size: to prevent repetitive phrases + # - early_stopping: if applicable + # - temperature: for randomness + # - top_k, top_p: for nucleus sampling + # These could be exposed via self.gen_params if more control is needed + try: + outputs = llm_model.generate( + input_ids, + attention_mask=attention_mask, + max_new_tokens=max_tokens_to_generate, + pad_token_id=tokenizer.eos_token_id, + do_sample=True, # Enable sampling for more diverse outputs + temperature=0.7, # Default temperature, can be tuned + top_k=50, # Default top_k, can be tuned + top_p=0.95 # Default top_p, can be tuned + ) + # Decode the generated tokens, excluding the prompt tokens + generated_text = tokenizer.decode(outputs[0, input_ids.shape[1]:], skip_special_tokens=True) + + # Basic post-processing: + # GReaT often serializes as "Feature: Value | Feature: Value". + # The prompt ends with "Generate ColumnName: ". We want the value part. + # This might need to be smarter if the LLM generates more than just the value. + # For now, a simple strip should work for many cases. + # If the LLM generates "GeneratedColumn: Value", we might want to strip "GeneratedColumn: ". + # This depends on how GReaT serializes and what the LLM learns. + # For a generic approach, we might look for the first newline or pipe if the model generates more structured output. + + # Example: if prompt is "..., Generate Name: " and output is "John Doe | Age: ...", we want "John Doe" + # A simple heuristic: take text until a potential separator or end. + # This is a tricky part and might need refinement based on observed LLM outputs. + generated_text = generated_text.split('\n')[0].split('|')[0].strip() + + return generated_text + + except Exception as e: + logging.error(f"Error during text generation via prompt: {e}") + return "" # Fallback or re-raise + if __name__ == "__main__": setup_logging(logging.DEBUG) diff --git a/tests/test_sampler.py b/tests/test_sampler.py index 34ce968..2364f6b 100644 --- a/tests/test_sampler.py +++ b/tests/test_sampler.py @@ -5,6 +5,7 @@ __license__ = "Apache 2.0" from unittest import TestCase +from unittest.mock import patch, MagicMock, call import numpy as np import pandas as pd @@ -94,6 +95,185 @@ def test_generate_data(self): self.assertTrue(gen_train.shape[0] > new_train.shape[0]) self.assertEqual(np.max(self.target.nunique()), np.max(new_target.nunique())) + +class TestSamplerLLMConditional(TestCase): + def setUp(self): + self.train_df = pd.DataFrame({ + "Name": ["Anna", "Maria", "Ivan", "Sergey"], + "Gender": ["F", "F", "M", "M"], + "Age": [25, 30, 35, 40], + "Occupation": ["Engineer", "Doctor", "Artist", "Teacher"] + }) + self.target_df = pd.DataFrame({"Y": [0, 1, 0, 1]}) # Can be None if not used for LLM + # test_df is used for postprocessing, might not be strictly needed for all LLM tests if postprocessing is off + self.test_df = pd.DataFrame({ + "Name": ["Olga", "Boris", "Svetlana"], + "Gender": ["F", "M", "F"], + "Age": [28, 32, 45], + "Occupation": ["Manager", "Pilot", "Scientist"] + }) + + # Default gen_params for LLMGenerator + self.gen_params = {"batch_size": 32, "epochs": 1, "llm": "distilgpt2", "max_length": 50} + + + @patch('tabgan.sampler.GReaT') # Mock GReaT where it's imported in sampler.py + @patch.object(LLMGenerator, '_generate_via_prompt') + def test_conditional_generation_basic(self, mock_generate_prompt, mock_great_constructor): + # --- Mock GReaT setup --- + mock_great_instance = mock_great_constructor.return_value + mock_great_instance.fit.return_value = None + mock_great_instance.model = MagicMock() # mock the underlying llm + mock_great_instance.tokenizer = MagicMock() # mock the tokenizer + + # Configure mock_great_instance.impute + # It should take a DataFrame and fill NaNs in 'Age' and 'Occupation' for this test + def mock_impute_logic(df_to_impute, max_length): + df_imputed = df_to_impute.copy() + if "Age" in df_imputed.columns and pd.isna(df_imputed.loc[0, "Age"]): + df_imputed.loc[0, "Age"] = 33 # Predictable age + if "Occupation" in df_imputed.columns and pd.isna(df_imputed.loc[0, "Occupation"]): + # Based on Gender if available + gender = df_imputed.loc[0, "Gender"] + df_imputed.loc[0, "Occupation"] = "MockOccupationF" if gender == "F" else "MockOccupationM" + return df_imputed + mock_great_instance.impute.side_effect = mock_impute_logic + + # Configure mock_generate_prompt for "Name" + # It needs to return different names based on gender and ensure novelty + # Store original names to check against for novelty + original_names = set(self.train_df["Name"].unique()) + + # Use a dict to track generated names per gender to ensure novelty within test + generated_names_by_gender = {"F": [], "M": []} + + def mock_prompt_logic(prompt_text, great_model_inst, device): + # Simplified logic: just check for gender in prompt + if "Gender: F" in prompt_text: + candidate = "Laura" + if candidate in original_names or candidate in generated_names_by_gender["F"]: + candidate = "Sophia" # Next novel female name + generated_names_by_gender["F"].append(candidate) + return candidate + elif "Gender: M" in prompt_text: + candidate = "Peter" + if candidate in original_names or candidate in generated_names_by_gender["M"]: + candidate = "David" # Next novel male name + generated_names_by_gender["M"].append(candidate) + return candidate + return "UnknownName" + mock_generate_prompt.side_effect = mock_prompt_logic + + # --- LLMGenerator setup --- + llm_generator = LLMGenerator( + gen_x_times=0.5, # Generate 2 new samples (0.5 * 4 original) + text_generating_columns=["Name"], + conditional_columns=["Gender"], + gen_params=self.gen_params, + # Disable post_process and adversarial for simpler focused test + is_post_process=False + ) + # Get the actual sampler object + llm_sampler = llm_generator.get_object_generator() + + # --- Run generation --- + # For this test, target can be None as LLMGenerator handles it internally if provided + # and we are mostly concerned with feature generation. + # test_df is also not strictly necessary if is_post_process=False + new_train_df, _ = llm_sampler.generate_data_pipe( + self.train_df.copy(), + target=None, # Or self.target_df.copy() if testing with target + test_df=self.test_df.copy(), # Or None + only_generated_data=True # Focus on generated samples + ) + + # --- Assertions --- + self.assertEqual(len(new_train_df), 2) # 0.5 * 4 samples + + # Check that _generate_via_prompt was called for each new sample + self.assertEqual(mock_generate_prompt.call_count, 2) + + # Check generated names and their novelty + for index, row in new_train_df.iterrows(): + name = row["Name"] + gender = row["Gender"] + self.assertNotIn(name, original_names) + if gender == "F": + self.assertIn(name, ["Laura", "Sophia"]) + elif gender == "M": + self.assertIn(name, ["Peter", "David"]) + + # Check imputed values + self.assertEqual(row["Age"], 33) + expected_occupation = "MockOccupationF" if gender == "F" else "MockOccupationM" + self.assertEqual(row["Occupation"], expected_occupation) + + # Check gender distribution (simple check for this small sample size) + # Ensure that the generated names align with their conditioned gender from the input. + # The actual distribution preservation is statistical over many samples. + # Here, we mainly check if the conditioning worked for each sample. + generated_F = new_train_df[new_train_df["Gender"] == "F"] + generated_M = new_train_df[new_train_df["Gender"] == "M"] + + # Depending on how attributes are sampled, we might get 1F/1M or 2F/0M or 0F/2M for 2 samples. + # The mock_prompt_logic ensures Name matches Gender. + # The attribute_distributions sampling in generate_data should pick F/M with 0.5 prob each. + + for _, row in generated_F.iterrows(): + self.assertIn(row["Name"], ["Laura", "Sophia"]) + for _, row in generated_M.iterrows(): + self.assertIn(row["Name"], ["Peter", "David"]) + + @patch('tabgan.sampler.GReaT') + def test_llm_generator_fallback_behavior(self, mock_great_constructor): + # --- Mock GReaT setup for standard sampling --- + mock_great_instance = mock_great_constructor.return_value + mock_great_instance.fit.return_value = None + + # Expected columns for the dummy generated data by great_model_instance.sample + # This should match self.train_df columns + self.target_df column if target is used + # For this test, assuming target is None for simplicity in LLMGenerator call + sample_columns = self.train_df.columns.tolist() + + # Create dummy data that model.sample() would return + dummy_sampled_data = pd.DataFrame([ + ["SampledName1", "F", 50, "SampledOccupation1"], + ["SampledName2", "M", 55, "SampledOccupation2"] + ], columns=sample_columns) + mock_great_instance.sample.return_value = dummy_sampled_data + + # --- LLMGenerator setup (no text_generating_columns) --- + llm_generator = LLMGenerator( + gen_x_times=0.5, # Generate 2 samples + gen_params=self.gen_params, + is_post_process=False + ) + llm_sampler = llm_generator.get_object_generator() + + # --- Spy on _generate_via_prompt --- + # We want to ensure it's NOT called in this fallback scenario + llm_sampler._generate_via_prompt = MagicMock() + + # --- Run generation --- + new_train_df, _ = llm_sampler.generate_data_pipe( + self.train_df.copy(), + target=None, + test_df=self.test_df.copy(), + only_generated_data=True + ) + + # --- Assertions --- + self.assertEqual(len(new_train_df), 2) + mock_great_instance.sample.assert_called_once() + llm_sampler._generate_via_prompt.assert_not_called() + + # Check if the output matches the dummy_sampled_data + pd.testing.assert_frame_equal(new_train_df.reset_index(drop=True), dummy_sampled_data.reset_index(drop=True)) + +# TODO: Add TestSamplerLLMWithTarget to test scenarios where target is not None for LLM. +# TODO: Add test for novelty retry logic (more complex mock for _generate_via_prompt) +# TODO: Add test for edge cases (e.g. text_generating_columns or conditional_columns are empty/None after being set) + class TestSamplerSamplerDiffusion(TestCase): def setUp(self): self.train = pd.DataFrame(np.random.randint(-10, 150, size=(50, 4)), columns=list('ABCD')) From b62187c3fd7349f3d9dcb8f9deae2db0a7b6111a Mon Sep 17 00:00:00 2001 From: Insaf Ashrapov Date: Sat, 7 Mar 2026 13:42:48 +0300 Subject: [PATCH 2/6] fixed links --- README.md | 95 ++++++++++++++++++++--- src/tabgan/sampler.py | 170 +++++++++++++++++++----------------------- 2 files changed, 162 insertions(+), 103 deletions(-) diff --git a/README.md b/README.md index 451dcb6..b2a51d0 100644 --- a/README.md +++ b/README.md @@ -2,19 +2,96 @@ [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![Downloads](https://pepy.tech/badge/tabgan)](https://pepy.tech/project/tabgan) -# GANs and TimeGANs, Diffusions, LLM for tabular data +# GANs, TimeGANs, Diffusions and LLMs for Tabular Data -Generative Networks are well-known for their success in realistic image generation. However, they can also be applied to generate tabular data. This library introduces major improvements for generating high-fidelity tabular data by offering a diverse suite of cutting-edge models, including Generative Adversarial Networks (GANs), specialized TimeGANs for time-series data, Denoising Diffusion Probabilistic Models (DDPM), and Large Language Model (LLM) based approaches. These enhancements allow for robust data generation across various dataset complexities and distributions, giving an opportunity to try GANs, TimeGANs, Diffusions, and LLMs for tabular data generation. -* Arxiv article: ["Tabular GANs for uneven distribution"](https://arxiv.org/abs/2010.00638) -* Medium post: GANs for tabular data [link broken] +`tabgan` is a library for **high‑fidelity tabular data generation**. +It provides a unified interface over several state‑of‑the‑art generative approaches: + +- **GANs** (CTGAN‑style architectures) for mixed continuous / categorical data +- **TimeGAN‑style workflows** for time‑series tabular data +- **Diffusion models** via Forest Diffusion for complex tabular structures +- **LLM‑based generators** (GReaT‑style) for realistic and conditional tabular text + +These models allow you to: + +- **Augment training data** for better downstream model performance +- **Handle class imbalance** by oversampling rare classes +- **Generate privacy‑preserving synthetic datasets** +- **Prototype quickly** with simple, high‑level APIs + +- Arxiv article: ["Tabular GANs for uneven distribution"](https://arxiv.org/abs/2010.00638) + +--- + +## Table of Contents + +- [Installation](#installation) +- [Quickstart](#quickstart) +- [Data Format](#data-format) +- [Samplers Overview](#samplers-overview) +- [`generate_data_pipe` API](#generatedata_pipe-api) +- [Extended Examples](#extended-examples) + - [LLM‑based text generation](#llm-based-text-generation) + - [Improving downstream model quality](#improving-downstream-model-quality) + - [Time‑series style usage](#time-series-style-usage) +- [Experiments](#experiments) +- [Results](#results) +- [Citation](#citation) +- [References](#references) + +--- + +## Installation + +- **From PyPI** (recommended): + +```bash +pip install tabgan +``` + +- **From source**: + +```bash +git clone https://github.com/diyago/tabular-data-generation.git +cd tabular-data-generation +pip install -r requirements.txt +pip install -e . +``` + +--- + +## Quickstart + +Generate synthetic training data using different samplers with a single, unified API: + +```python +from tabgan.sampler import OriginalGenerator, GANGenerator, ForestDiffusionGenerator, LLMGenerator +import pandas as pd +import numpy as np + +# random input data +train = pd.DataFrame(np.random.randint(-10, 150, size=(150, 4)), columns=list("ABCD")) +target = pd.DataFrame(np.random.randint(0, 2, size=(150, 1)), columns=list("Y")) +test = pd.DataFrame(np.random.randint(0, 100, size=(100, 4)), columns=list("ABCD")) + +# generate data +new_train1, new_target1 = OriginalGenerator().generate_data_pipe(train, target, test) +new_train2, new_target2 = GANGenerator( + gen_params={"batch_size": 500, "epochs": 10, "patience": 5} +).generate_data_pipe(train, target, test) +new_train3, new_target3 = ForestDiffusionGenerator().generate_data_pipe(train, target, test) +new_train4, new_target4 = LLMGenerator( + gen_params={"batch_size": 32, "epochs": 4, "llm": "distilgpt2", "max_length": 500} +).generate_data_pipe(train, target, test) +``` + +--- ## How to use library -* Installation: `pip install tabgan` -* To generate new data to train by sampling and then filtering by adversarial training - call `GANGenerator().generate_data_pipe`. +To generate new data by sampling and then filtering via adversarial training, call `*.generate_data_pipe` on one of the samplers described below. ### Data Format @@ -177,8 +254,8 @@ print("initial metric", fit_predict(clf, X_train, y_train, X_test, y_test)) new_train1, new_target1 = OriginalGenerator().generate_data_pipe(X_train, y_train, X_test, ) print("OriginalGenerator metric", fit_predict(clf, new_train1, new_target1, X_test, y_test)) -new_train1, new_target1 = GANGenerator().generate_data_pipe(X_train, y_train, X_test, ) -print("GANGenerator metric", fit_predict(clf, new_train2, new_target2, X_test, y_test)) # Corrected variable name +new_train2, new_target2 = GANGenerator().generate_data_pipe(X_train, y_train, X_test, ) +print("GANGenerator metric", fit_predict(clf, new_train2, new_target2, X_test, y_test)) ``` ### Advanced Usage: Generating Time-Series Data with TimeGAN diff --git a/src/tabgan/sampler.py b/src/tabgan/sampler.py index 3f8e467..f076795 100644 --- a/src/tabgan/sampler.py +++ b/src/tabgan/sampler.py @@ -5,7 +5,6 @@ import warnings from typing import Tuple -import numpy as np import pandas as pd import torch from be_great import GReaT @@ -85,23 +84,35 @@ def __init__( conditional_columns: list = None, ): """ + Initialize an original sampler configuration. - @param gen_x_times: float = 1.1 - how much data to generate, output might be less because of postprocessing and - adversarial filtering - @param cat_cols: list = None - categorical columns - @param bot_filter_quantile: float = 0.001 - bottom quantile for postprocess filtering - @param top_filter_quantile: float = 0.999 - top quantile for postprocess filtering - @param is_post_process: bool = True - perform or not postfiltering, if false bot_filter_quantile - and top_filter_quantile ignored - @param adversarial_model_params: dict params for adversarial filtering model, default values for binary task - @param pregeneration_frac: float = 2 - for generation step gen_x_times * pregeneration_frac amount of data - will be generated. However, in postprocessing (1 + gen_x_times) % of original data will be returned - @param only_generated_data: bool = False If True after generation get only newly generated, without - concatenating input train dataframe. - @param gen_params: dict params for GAN training. Only works for SamplerGAN, ForestDiffusionGenerator, - LLMGenerator. - @param text_generating_columns: list = None - List of column names for which new text values should be generated. - @param conditional_columns: list = None - List of column names to condition the generation of text_generating_columns. + Args: + gen_x_times (float): Factor controlling how many synthetic samples + to generate relative to the training size. The final amount + can be smaller after post-processing and adversarial filtering. + cat_cols (list | None): Names of categorical columns in the + training data. + bot_filter_quantile (float): Lower quantile used for numeric + post-processing filters. + top_filter_quantile (float): Upper quantile used for numeric + post-processing filters. + is_post_process (bool): Whether to apply post-processing filters + based on the distribution of `test_df`. If False, the + quantile-based filters are skipped. + adversarial_model_params (dict): Parameters for the adversarial + filtering model used to keep generated samples close to the + test distribution. + pregeneration_frac (float): Oversampling factor applied before + post-processing. The final number of rows is derived from + `gen_x_times`. + only_generated_data (bool): If True, return only synthetic rows. + If False, append generated rows to the original training data. + gen_params (dict): Model-specific generation parameters shared by + subclasses (GAN, ForestDiffusion, LLM). + text_generating_columns (list | None): Column names for which new + text values should be generated (used by `SamplerLLM`). + conditional_columns (list | None): Column names that condition + text generation for `text_generating_columns`. """ super().__init__( gen_x_times=gen_x_times, @@ -116,11 +127,9 @@ def __init__( ) self.text_generating_columns = text_generating_columns self.conditional_columns = conditional_columns - # Ensure TEMP_TARGET is initialized here if not by super() - if not hasattr(self, 'TEMP_TARGET'): + if not hasattr(self, "TEMP_TARGET"): self.TEMP_TARGET = "TEMP_TARGET" - @staticmethod def preprocess_data_df(df) -> pd.DataFrame: logging.info("Input shape: {}".format(df.shape)) @@ -256,27 +265,26 @@ def _validate_data(train_df, target, test_df): def handle_generated_data(self, train_df, generated_df, only_generated_data): """ - Integrates synthetic data with the original dataset by preserving data types - and structural alignment. + Align and optionally merge generated rows with the original training data. - This method transforms generated data to match the original dataset's structure - and types. It can either combine synthetic with original data or return only - the synthetic data. + The generated data is cast to the dtypes and column order of `train_df` + so that downstream models receive data with a consistent schema. Args: - train_df: The original dataset that defines the expected structure - generated_df: The synthetic data to be processed - only_generated_data: Boolean flag to return only synthetic data + train_df (pd.DataFrame): Original training data used to infer the + schema and target column. + generated_df (pd.DataFrame or array-like): Newly generated + samples to be aligned with `train_df`. + only_generated_data (bool): If True, return only synthetic rows; + otherwise, append them to `train_df` before returning. Returns: - A tuple containing: - - Feature matrix (with or without original data) - - Corresponding target vector + Tuple[pd.DataFrame, pd.Series | pd.DataFrame]: Features and + corresponding target values. """ generated_df = pd.DataFrame(generated_df) generated_df.columns = train_df.columns - # Preserve original data types for column_index in range(len(generated_df.columns)): target_column = generated_df.columns[column_index] generated_df[target_column] = generated_df[target_column].astype( @@ -391,14 +399,12 @@ def generate_data( self._validate_data(train_df, target, test_df) self.check_params() - # Use a copy to avoid modifying the original train_df if target is added current_train_df = train_df.copy() if target is not None: current_train_df[self.TEMP_TARGET] = target logging.info("Fitting LLM model") is_fp16 = torch.cuda.is_available() - # Ensure GReaT is imported try: from be_great import GReaT except ImportError: @@ -409,7 +415,7 @@ def generate_data( great_model_instance.fit(current_train_df) logging.info("Finished training LLM model") - device = "cuda" if torch.cuda.is_available() else "cpu" # Needed for _generate_via_prompt + device = "cuda" if torch.cuda.is_available() else "cpu" # Needed for _generate_via_prompt if self.text_generating_columns and self.conditional_columns: logging.info("Starting conditional generation of text columns.") @@ -438,21 +444,13 @@ def generate_data( dist = attribute_distributions[attr_col] current_row_data[attr_col] = np.random.choice(dist.index, p=dist.values) - # 2. Generate other non-text columns using be_great.impute - # Create a template row with NaNs for be_great to fill row_template_for_impute = pd.DataFrame(columns=all_train_columns, index=[0]) for col in all_train_columns: - if col in current_row_data: # Conditional column already sampled + if col in current_row_data: row_template_for_impute.loc[0, col] = current_row_data[col] - elif col not in self.text_generating_columns: # Column to be imputed + elif col not in self.text_generating_columns: row_template_for_impute.loc[0, col] = np.nan - # else: text_generating_columns will be filled later by _generate_via_prompt - # Impute NaNs for non-text, non-conditional columns - # Note: be_great.impute might expect specific formatting or might modify inplace. - # This part might need adjustment based on be_great's exact API for single row imputation. - # For now, assuming it returns a DataFrame with NaNs filled. - # Also, max_length might need to be dynamic or a class parameter. imputed_full_row_df = great_model_instance.impute(row_template_for_impute.copy(), max_length=self.gen_params.get("max_length", 500)) @@ -462,14 +460,12 @@ def generate_data( # 3. Generate novel text values for text_col in self.text_generating_columns: - # Construct prompt prompt_parts = [] for cond_col in self.conditional_columns: prompt_parts.append(f"{cond_col}: {current_row_data[cond_col]}") - # Include other relevant, already generated/imputed columns in the prompt for other_col in all_train_columns: - if other_col not in self.text_generating_columns and other_col not in self.conditional_columns and other_col in current_row_data: - # Limit length of values in prompt + if (other_col not in self.text_generating_columns and other_col not in self.conditional_columns + and other_col in current_row_data): val_str = str(current_row_data[other_col]) if len(val_str) > 30: val_str = val_str[:27] + "..." prompt_parts.append(f"{other_col}: {val_str}") @@ -479,25 +475,24 @@ def generate_data( generated_text_candidate = None max_retries = 10 for _retry_attempt in range(max_retries): - # Placeholder for now, will be implemented in next step - # Pass great_model_instance.model and great_model_instance.tokenizer - generated_text_candidate = self._generate_via_prompt(prompt, great_model_instance, device=device) + generated_text_candidate = self._generate_via_prompt(prompt, great_model_instance, + device=device) if generated_text_candidate not in original_unique_text_values[text_col]: break - else: # Max retries reached - logging.warning(f"Max retries reached for generating novel text for {text_col}. Using last candidate.") + else: # Max retries reached + logging.warning( + f"Max retries reached for generating novel text for {text_col}. Using last candidate.") current_row_data[text_col] = generated_text_candidate # Ensure all columns are present in the order of original train_df (excluding TEMP_TARGET for generated_df) - ordered_row = {col: current_row_data.get(col) for col in train_df.columns} # Uses original train_df columns - if target is not None and self.TEMP_TARGET in current_row_data: # Handle target if it was part of generation + ordered_row = {col: current_row_data.get(col) for col in + train_df.columns} # Uses original train_df columns + if target is not None and self.TEMP_TARGET in current_row_data: # Handle target if it was part of generation ordered_row[self.TEMP_TARGET] = current_row_data[self.TEMP_TARGET] generated_rows.append(ordered_row) generated_df = pd.DataFrame(generated_rows) - # Align columns with current_train_df (which includes TEMP_TARGET if target was not None) - # This ensures generated_df has the TEMP_TARGET before handle_generated_data if it was part of training generated_df = generated_df.reindex(columns=current_train_df.columns) else: @@ -506,72 +501,59 @@ def generate_data( device=device, max_length=self.gen_params["max_length"]) - # current_train_df already includes TEMP_TARGET if target was not None - # generated_df should also have TEMP_TARGET column if it was part of generation process (e.g. via impute or if it was a regular col) - # handle_generated_data expects train_df without target, and generated_df potentially with target - - # If target was added to current_train_df, we pass the original train_df (without target) - # to handle_generated_data, and generated_df (which might contain the target column from generation) return self.handle_generated_data(train_df, generated_df, only_generated_data) def _generate_via_prompt(self, prompt: str, great_model_instance, device: str, max_tokens_to_generate=50) -> str: """ - Generates text using the underlying LLM from the GReaT model instance based on a given prompt. + Generate a short text completion from the underlying GReaT LLM. + + Args: + prompt (str): Serialized row description used as generation context. + great_model_instance: Fitted GReaT instance providing `model` and + `tokenizer` attributes. + device (str): Target device for inference (for example, ``"cpu"`` + or ``"cuda"``). + max_tokens_to_generate (int): Maximum number of new tokens to + sample from the model. + + Returns: + str: Post-processed generated text. Returns an empty string if + generation fails. """ llm_model = great_model_instance.model tokenizer = great_model_instance.tokenizer if llm_model is None or tokenizer is None: logging.error("LLM model or tokenizer not available in GReaT instance.") - return "" # Or raise an error + return "" # Or raise an error - # Ensure model is on the correct device (might already be, but good to ensure) llm_model.to(device) - inputs = tokenizer(prompt, return_tensors="pt", truncation=True, max_length=tokenizer.model_max_length - max_tokens_to_generate) + inputs = tokenizer(prompt, return_tensors="pt", truncation=True, + max_length=tokenizer.model_max_length - max_tokens_to_generate) input_ids = inputs.input_ids.to(device) attention_mask = inputs.attention_mask.to(device) - # Generate output tokens - # Common parameters for generate: - # - no_repeat_ngram_size: to prevent repetitive phrases - # - early_stopping: if applicable - # - temperature: for randomness - # - top_k, top_p: for nucleus sampling - # These could be exposed via self.gen_params if more control is needed try: outputs = llm_model.generate( input_ids, attention_mask=attention_mask, max_new_tokens=max_tokens_to_generate, pad_token_id=tokenizer.eos_token_id, - do_sample=True, # Enable sampling for more diverse outputs - temperature=0.7, # Default temperature, can be tuned - top_k=50, # Default top_k, can be tuned - top_p=0.95 # Default top_p, can be tuned + do_sample=True, # Enable sampling for more diverse outputs + temperature=0.7, # Default temperature, can be tuned + top_k=50, # Default top_k, can be tuned + top_p=0.95 # Default top_p, can be tuned ) - # Decode the generated tokens, excluding the prompt tokens generated_text = tokenizer.decode(outputs[0, input_ids.shape[1]:], skip_special_tokens=True) - # Basic post-processing: - # GReaT often serializes as "Feature: Value | Feature: Value". - # The prompt ends with "Generate ColumnName: ". We want the value part. - # This might need to be smarter if the LLM generates more than just the value. - # For now, a simple strip should work for many cases. - # If the LLM generates "GeneratedColumn: Value", we might want to strip "GeneratedColumn: ". - # This depends on how GReaT serializes and what the LLM learns. - # For a generic approach, we might look for the first newline or pipe if the model generates more structured output. - - # Example: if prompt is "..., Generate Name: " and output is "John Doe | Age: ...", we want "John Doe" - # A simple heuristic: take text until a potential separator or end. - # This is a tricky part and might need refinement based on observed LLM outputs. generated_text = generated_text.split('\n')[0].split('|')[0].strip() return generated_text except Exception as e: logging.error(f"Error during text generation via prompt: {e}") - return "" # Fallback or re-raise + return "" # Fallback or re-raise if __name__ == "__main__": @@ -591,7 +573,7 @@ def _generate_via_prompt(self, prompt: str, great_model_instance, device: str, m GANGenerator(cat_cols=["A"], gen_x_times=20, only_generated_data=True), ForestDiffusionGenerator(cat_cols=["A"], gen_x_times=10, only_generated_data=True), ForestDiffusionGenerator(gen_x_times=15, only_generated_data=False, - gen_params={"batch_size": 500, "patience": 25, "epochs": 500}) + gen_params={"batch_size": 500, "patience": 25, "epochs": 500}) ] for gen in generators: From 7c82bad1faa9aec8606b19220384e87bf0bfb3e1 Mon Sep 17 00:00:00 2001 From: Insaf Ashrapov Date: Sat, 7 Mar 2026 13:54:15 +0300 Subject: [PATCH 3/6] fixed links --- README.md | 12 ++--- images/workflow.png | Bin 83807 -> 142381 bytes setup.cfg | 11 +--- src/tabgan/cli.py | 129 ++++++++++++++++++++++++++++++++++++++++++++ tests/test_cli.py | 51 ++++++++++++++++++ 5 files changed, 187 insertions(+), 16 deletions(-) create mode 100644 src/tabgan/cli.py create mode 100644 tests/test_cli.py diff --git a/README.md b/README.md index b2a51d0..7a5ec81 100644 --- a/README.md +++ b/README.md @@ -6,15 +6,13 @@ -`tabgan` is a library for **high‑fidelity tabular data generation**. -It provides a unified interface over several state‑of‑the‑art generative approaches: +> **High‑fidelity synthetic tabular data with GANs, diffusion, and LLMs.** -- **GANs** (CTGAN‑style architectures) for mixed continuous / categorical data -- **TimeGAN‑style workflows** for time‑series tabular data -- **Diffusion models** via Forest Diffusion for complex tabular structures -- **LLM‑based generators** (GReaT‑style) for realistic and conditional tabular text +`tabgan` turns your real tables into realistic **synthetic tabular datasets** for modeling, privacy, and experimentation. +Under the hood it combines CTGAN‑style GANs, Forest Diffusion, TimeGAN‑style workflows, and GReaT‑style LLM generators behind a single, high‑level API. +It is built for **ML engineers** shipping models, **privacy & governance teams** who must protect sensitive data, and **Kaggle competitors** who need more signal without leaking the real thing. -These models allow you to: +With `tabgan` you can: - **Augment training data** for better downstream model performance - **Handle class imbalance** by oversampling rare classes diff --git a/images/workflow.png b/images/workflow.png index c1d75b171afad4fcccf0e45f7a3573f849d8c68e..06d00817ec23188e733f2cf98eb4da9a69ad8767 100644 GIT binary patch literal 142381 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®WoHM>^5H_GtFN!GQ^C{Bg72n3iZO^C!cUxT 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 B zBLSC#RcP1%G6x1k@!$4LtspKg4u~RHjrc8`;C4_n$K{l!|8Q)40;)RNiSj^4a86(> zz|UV`%N`z90d4MW^E8+#KyGE~|L3A1E(Oe#+qq`k_5rzdfJ=eI3KEZ#xfSRz0Bi!V zn%;o@fat0;LbIdStcCyDkVl<*(#`mFJE;>#Zcw4$w|?{g zZ~c_=z~TR9NC#k*(?C^C@4tXD9MRnYIMfQ)m+H0`1Oh|Yk6_Tv{V?42M|@-?8$`xf zwVWD#{Xhnq37E49isC}|TNKwhE&8p^Axa0>1ZLOaFJ&%aZ?L&JGzKCZTw>;Cwll2SSW zS|`xl1J8*;0}Ry8EEV}Cw?~K9Wu}xA>3iiDvPN{&iUS=*mQ+605jqUJj7@%l5>=`T zfr;^hfD)z(HskS$iLV?1ni+1FfT})bKX?1m4#Q1S(N@-O@TS*(|BPLu<%V)o6gJfRhM)YWk$pV}7 zSeE8||51N;odEx)ijlmjj|^l&!2Zp96S054DDNeGifv5%dKz}GJCd^II!AXs54 z9&Q5w1iWOp#re`I`3JCA#IztBNMOz-66g2;3!MNJro14_pr6Db=2ZhcJQeV8oe5b} z1B&{?5Su?h`2t%b<-XS{#33ekIG8MKa#mvRFqL*Z+K}c!x>cf|?IiG@P9rM%F137$ zNRk6cNWo9#QM)otG%DbEofHvL3Q63;zMSmr`?9g6k%+$HnyBz@yA+TTVWo_Zj(#;x zQz{s@bXojqBWaMaaSP9ADjRB!4u*k-W3y0po3a|50AMQaW#;|mS0WrN#rA|xb4cd=}08sVHAU~U^xLC0P=-S z+NGk-IGAUyz$;%V%@JDskI>@FP~w&c9$C{c?;I}spvd*_7Fd$Dj^_dl@vl2B6#W1pNIY+p>)+k(Oy!bpot-Nu0Ez@9Borco!zbEOxd}nqb!Dylzt(f z^dS*2dOr063?w)YpVen+_^nX<&wJb8d*X{DB`}c82jSQfxg-C10ut6a(iD*p)Cd4A zm>YfnajIk*{|@Ki01NaZaQcCST`c&el~rnNEOl!7A!3sQF=v;9n3tEAj)&+iH|@`B z%^-+}+X=ct^q0MDO&La7^Xl#NFb+GE;Lxwcp*!d)hgh01o)=U4GUxA*rcSQ_A~hhUkXbJ z~LGGYO77*-!0E8L4{qEV9tlJIcT zY*8W93hl`)*Lg(mB;&#{f`fze@L>|5>CrMvd?L6iPjIM!0wL;uee@>~>v%2=fYs9V z{X0R8A@ty&U4(?aDBz|4X{L^lO1p#(zp1&I(=j@=wei8dHdI-yX9rfBgvwJCCe zUHt*-%W`gN>RatZH00!L%%vax>p&e=4>VIhmD0y4K-f~6YFYP4KX{#`mD>exruta* zJa2tkkGe%fexv{Ojj)0Ox;D=xP`$nWiupYTrgddn45y>i1*N4{SJOV;D{#7Cj!?

S&_;Tw!Knbj5jtK>`hcCxeuep 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 OwvF^mbqU%RBmWEI#l8ms literal 83807 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�=&V{dmO8KE#HN}9 zR=EhckygVPF|=zeuv#)G!H){F&+2 zf+C{JGy`J!KW|7eGtn0n$uObQ%E(BBYmJ#_?66Al3(qZ zZ#$C^zaV?ia;EM>^kfGJp~l^a;&627AogI~FkHG`((w4P{Z>agLja$Gy?0r(gz6;*(li5r@%dsbr}^hECK99J_3b8MhegDh!m9 z|D%tzesP?8zh-A=$HvBHXGvY46-Typi?t4`Vj~SrS$_lLV%=yZw2w{&4x623tIXWp z-CM|;up<@D;2=o7pQ+5+uhnj@Tbq+_D=Y|eMlx-|85SzI&)B~Da+Br5b-^nZviz`f z@vQa7LhT;SMHKxPDVt#FF+#~VG7+%_8G_JHGXHUk*J6vxc6JBS&%EgJJ|FdvSd64y zUGJ95Gi820mdzZU{x1Hu!nniU=Vty3Id4K-T=Tz9%u%5WeJiVNNfLuxtGWHU<@?Ns z+hCWIoM(6aOttX)o3@9WB-6;*HXk1sm$N@VzqVZs+h=?nV2Y?5WN&NE%iDlZP}7Ph zL#3HYb=95r^OhwbcYB_7ESG1`SOyy(wA;$bc!%$*t*>5+_21aH_#9ao-F5sB5p4XI zG;iOy$UW?Hd*xHytC%WqGDNQ|o;Znr8`P! zE<7VsJ``+D_HM=LK#Em=c<~Tnt}q$?eRP#mv3=TcM-KBMc!m( z&`jpE5*l^n`p+5s_!{{F{GAkQP3LV zWTD$=}`s-4DtlPg)ycD?2F;5or=_u6_>HA{t&B9a=;lsA31(&$#S zoZ&K8V#eN_#`S7zweR6{+><@sYn8urxHMv{#q+$(;KxB)dD=~mo)7oK&B>i#9M1Cn zzvl2!p~LKxe5KUu^2AKGViu?1cflA$o+p!4Nu)eji|9u5)xBy&c|U0DZ7*6&JkhW68@p}F>b7WCJdp}N~7|{fC*gzN@H=Qy) zC12?Ldmq)!gz3RZ_+XfTz-!it8r!Do>WQrjY}>d%;{>s4f5E@+`{}Q6v-Ix6IOI@j z6`HEK!Z^m8sc@uFRK@V#H~kmO)s|bzb&Mfx7)P zwbvUfhQe$WBd;HZdLHU7`NX$wj2zkSKD9ix;qUzUs+=L>b3aw8H(h4XWZdD;?zJt?tW^S2 zJi&Yx$TaklaxN6EHV_*YtF9zsc9TGfeM7D+v^!a8+GkfZtD*n)bQkSlPNT(Y`rM#} z>wU8?VI2J0@c0mOF#Ma%*ER{^=>MZrpPfS zyX>%t{ha!uH?KDzT>qH_Uq8jJQjt4Fj89DNkrCUnQ6oMAA)UYHafkGKkw2o4?Sp_D z49q%=T0NhR-?(<3+E!;+w;a6-IB?v$&ad-HPLUk>ag9XPPtPR9xUU|h3XAEyxIk4A=y6%7WtYIthV(H`7=%$y&5;J@A@z%}5@nUML z)7PbBP4@2V9;lqIhDZG(I+=6&#e$Vc9BS1au30 z@RG&)yUpc0+ra}bwE_8&q>~>L7F;;;%E~_#a4x;bOr_W6fVU$Ag~bR-%+SU!ymy`8 z#=(z*+NAVCodz_hW^%Wf4yYy~hkd$|5Sala(>XxSZ*khr1JzO5cVYhd{BqMk8H z!BmMWqOyepWtAb^Bh&|JN-rnbE8tuLpI!K;* z5uoP{E3}NY)s^P+e;!kVgN5g9y~yt`R;^TU7ELyfE-EL-fklGU<$UEwfMERhumlgR ztm&E15ZAl+L{^_yzUV2vZ20vZwN)q4+HiRHOpY!Pw^C+E*X~M2B!pIKOYd1Lm1Qx@ zOXeh)$sTnu#I$ne`fQh+oc!eEgqfLHQ**J(Z18-4zQxd9Qc}{+&d$`-R8dipg_!x} z%a^RIJc`x%`T1pKc0)-VnwpwSOiTiOzo4i{PFcCUv~;oFF$Xuhq~sAOvs4Ni8yoZT%x*7_;^X5ZDu+RG zJ5$+pc%iMS`Gu4#zqPeBKff0ifgh~HQfsvybfNuQ@Tzy5>MC!sz{ zUQ=s#*@|jY@U|G4PvF5D8yjgS*yOJ!r>4x!%)ngp^79XtT0AH66(L#2$H$=r46d%O zTH4xmKYkDq5^88@;EKJnovX2#E)%6z(bNQ!(F7Mwx=;tJ7M?f8$mD{BS5`VM)H{Mp zR8bbYQ>F8@wiDc?RaKn4ymf_zh57j}$i65gbLN$l>=6h}EiD-u7%YyBaafJ#E>Que zEH5e==UY(sLVP1Cja}klYygaa=7lasRM>^)_=3vO%w{xpPQcR0ARud!X0?2-% z;IUwZQGIf9a$(`&Ib)U}$pyP~0Mr+C_SK4$|sj>y@h`ryEThNeNC-QuH!keHbG^(&Y8P!iZe zdiexrXJ>tn?L51!i_C}StB##BGlId$GDae?$fN2XHp?ehYWd2{NA5yRZa-R2$HRd> z)&f{JIB*IRxBt3ujC}6Sz&3Sub^;69&esZo*Fo3aPc|Dqu7VjZfelZ#$l!O`(Gct3 z`CV)TXgwI)+}vDJQZhF;CmBvG`8?*4i5C`3_u)X53 z*RYiVNLusdTKM4LARq+~0KzkX2-DJ2zEke6YJdZKb;{0hMSyQlPA$pnvNGoXhR)@0m)n zvgjyCS65f1rKOJq0PwCSB>FJ0a+>brjX@*N{U3$u--(Hd^YildXDZjhEm9Bzm*1KI zjIdAx%A1b|fRk>Gr0W?PjzINVJkBuLn_(uMaNsS#ZGbY#X4uR}@ziJE#)z4XEwbmG zee2a`7!k9Q@YNsSW98FLCS5^+m?Y-!-`B^VgM*UcbAJV*dpKKT|Je-Mv(NuFQ|*;f zU)hf5%KC{K1HV=lIwLgQ+bJ$*V`TjM_peUvhgrb6M)Z*bdPkEJtEed=f<#4ZdZ{8$LNt`XK~e&z^=@^SX`d({ z%J?iw>-=hX)rUeMpvz}{i{l$Dp`!>o4cE9@(17nM7oRS+j7L<%+afN)_%tplQqwqm zIdss%0~Py5qRjVk0)xrqn+Kj4##nDrPa~;QK0DS+|3Hqi(o(OBMK>HGPl4O00IPpi z^EkZ-7tY_&ZmmW#BWmI@Fjr21xQ z^4}e|aa+SG1sL8A!4P!wkuIN#C?6(}wO@fO8Krz3+(PyF-$lVRjJp?tn)kS-ST3h= z(w7sW*qd&BC3&a~EKL0rO@KZQG>!Ck8f3B>&-NWNVvDk{E>$8)Qy$Use!LQ5Yb zrg?ISNFz}hE9dmV&T#~-O=D#4ht0$NMO(lH!V2tmbNa$zJ^|XW9srYrJXU8iS+R>* z?ZgmzWu>dTn!n)p=czA-FW$-nW-um4!*!=z!^zMef)oj1gTBph|w4`ufcvIyy-B z%V5BN%}gF4&8}cFnd#N*ew1aTf%7rd2ZZe^roP$-&QImo*W_-ozv$z2J+&<2F?bgx zc(g|DfQZ!(mSW$0BsDLb%`2m>K2ch?)ChvldyoBwyK_BsdL7riI`LQm1gw_!*Ef6B znVtvy4ifKheL9C((!OpE`_pvR3-A$83a9ENn3-@CaAK>;DNc+}Oh_+ukmaA954b3^ zd+rwI*-!D-b=b@KSZunG!AJ+^-4K97I0^eJEZXF>+3|5C;0;hiKbN!L z%ifo(!5w(${&BImDXYVTVi6wN-*k|3JQBXJ!cjUt!LkWVK>*+E2`7o_7AIDlOPfy< zALXq;<%x)lj1*@T=U14iU7Vf$$*)}HmO*ZJ>4!_F2^AXKAi$rH*LlR)zwzBsz z!9U68zkYD0!+0mXU@2SpA5D1cUVV6LP|m246(&a{2I~k}XM0+`pRbro%%%^SR*Q9< zHgGd==y(Fj0!Wmfn|lkA?>7)uqgFvc3vRO8!--ixl0O_p`E)}c{soJqiTDWjUUm~G zf3UIwak*~Eqj>%}Mw;qse)&F#qxJT9FrB}s07S{-L3X!?v)r#r)|Qr{kW&4I<20v{ ztG_u>0B}@QRULbXwD|_#y+Cfe-PjKaKfrMMRtgxX3FPO^!A&NJ1&2{SpB?UR?LAry z9R^6k<2V_3L<|NODlP(w{B?7FA?KIc&)kgN@0WVpV&w7B(z5cfijvY0uD^l1aw`rF z4Z$&)e)f-!0{*iEsE)O@H6SpChD!jk%Yn9_!=k0D8;UzuXTKb;ZJ3;p;JTS?@iHtn zBjY|;v!0_2>i#A||?d@$qUIg3@x}j0zymkX|OtJ)hMa9Jd;TQ-(ME)G_hE8sl zMJ^Xk1_2ld2w$!Q+}&J|2O(C^wCb1>Wq!@tbgup3l)9@mxhCr^l^d5fFNPssH*NQJ ztfEEz)gRNKW~L<&Eq%gz38hHs1Cn%vy{=EMPPV$};}oWY;*P;Fx!*N<2*Ygz!G9S< zKTNjzZ)Ig=xw-FGI|Bio!Vx%`eRsq=2Fs`DnFufnSOkZuv$feQh|gESPkic6 zd=8jiGLMX4T~f!LJz+M=?u%%=p02^7Z(^kPd6%Ir`y)UCBR5xuM_ev)`00m0yoqQA z`FAf$VYLFuMK8I3Cr|~*MI~C`=g!dKciBP-M1G!6V9D>iY3hh=lv10pWE10LdE3>j z+41%zWifsxn^<}?qU?4~GGdCYJZ*O>7T$TZDA{mNh=inP2(Nkxie;n}QcwtrJ91)e zRPOgG3buWiePoyt(anSoTbG=MGs^x8e=Cfi=VQ+Dy|4FC^~lI%<#SBw@m0s{!jdZJ zBA+~Gb-nSH`hq0crID3vwVh0ARn$3I-`bfJ-Q|X=Ht-p(?hyDX`d|L2ES3J@?kW~} z)wl^|k#x02zzhw2nxsDY6d%5TkCqT&;aQ18;E<$ z61jb|<5IIbBuj>_%Hzy>uOy^F=nUJ3)SYiB($}0lvhpjfZ8y zV=>#>d?eReUi#u%>jzN$nb$JLG}XxScnU(}csl)&m@GvF81fqiNb>L1){ee&1-Rlz z+(}$a$mkm%Ny+zerzP~VgsQ;nBqf-;GBm6UXTA@r{IZLdxt8G;J!A8ur=?1Z?cGC0 z!Yo9z?tPLFfwGV4_kle$SM6&~eS28wH-9gy$$XvA&`4_g=OOtji_)Erem&$LtgQL= zptwLGnG98V&&LudmYit~FXWDnO-baHIswTdBSu$}irmxX7L$nGogFeVGC-&i>)i0= z*_bxu*;`K24?p)&E_(jW3eNbn7P|DrJTJ~qv^||=O>hH}H@SXvs&RjEb9aC?SmkUW z4G{uN3vI~(0w6HRgsxa2Q{ZB+-szv;f-AHJ;SrLdrc%-QR_ghLu-@K{sBmbb?To$* z%_5qHzRrqjVd3+}R@-H7sSxL-fbU8y#&L~NdzW9`_@2q))6l@Jl0E3A#>T9468g5u zazjgkF1NoyRauuJ>$=HJ;n1&Y)Wt$eZ**jg<8#ffk~h@dYnujPRWNg5K}1@Xyb!V@ zCwxz~Xz}Ro)yl9j4fn{Tv$72NZcA zp7|!ELRc?Q40tL&1jU1a2DB>FmGuqtE`RPNwfJ>FE+`-{e|RCVffXCQe1Bdy%$o0< zu@4KxMF^5Kc4=Fpk*i!jOy#x`duzRO53=a%gbL8<$en`R=ZF{ZC$jNch_zHLd;GSN z=qm$m7_3uiRX!A*7#ePps#*TLsBp=5ngC+CzyC&@w^HmjDtAWdb43yt$)@xTc;>#d1Z9!2>%!d7Gg66Sw-|ug!J$J z9zY^Tx0KJW6ztH%X$CnpHRW+oATK&}=*ZC32axW4r*otfX$di8XKj6PV{{@gSEmKn zk3ZgdE1ngkNNWlys3wzXYujBG*|h(KIR@&mOwD1qm=QITozOybU*@B*+-QMVj##9 z*?}w%qMjp&gH^99z8Q--ow(LVBN)#-Ar=c!Tg!d%srS$O+}tY$qCdL{J+`Yue|k{9 z^p?0qsM<*XYhe|5=Yoy@Gopk;GoC0#+6;8Iye559_KWPGj4l%QsLj264qHhd?-{fu zzW(B09=R#4K^JY3TIZt2Fhsyz;pl{^=S>62cyf*6KffcDSe$3b0799I}NQ@Mic(B%)jjje_>E+jO z-t<1^cmzs(s~~CgK4{p2^(L4Blm_I07Ct^cUR6~keEl~Eh#4Sci-6!?RP@4+3kZ7| z4Hib@LaZd?&ayH{Xr?Cq^jk-CI?qCai{>@M zY*{LbXCK+3kfT;w_nY1?b?kehw|MWXK6C%`iaJ-%IE&3dW_|pn9Zx6x9sYE6fQq)- z0FVv9jJuUTwq37rk=!1}j>zPWx{E`$6Y}&DZpi0}og&jwcLoelw$Vf`I|6WoEum6C zvx))=JCM!94W++XI(etonL_>&Jm6kxN}TjkCsz2ygzwo6HK^G$Z|qi`Tj zY-M=bf!x2WeJw5OnTR(ie2HBBRHpJeRqcXB0`rj=eRc$T7O+l4giU#iYgZ8V&7;=n z>Bd4V|J2U~hz@Bk2h-6fodN06NOTRz?YQ!gI!`ChoHCVAi8RcEdu5riv!=16%}5SA zORKiKET7gUYoX4+r|Xedn}J)GUKzflyC*g&`LDC$X^(V1j{3!kJ!hhG4R{k!k=gw$ z-GB`98HAAEvE+bjPOqvT(c8J3zBkxr*)#aSC&1q4+nd8r+WK1rvM@L$=Obl<3JyL&7TU8>w4mU@V^(W6Vcx}Hyj8_FMfaB?B*>K1ypO=A;v zE$AUY2OwH)B_^^=`LPf&IPOtKTEsX%9EEncOD78c5q~i+y0g$W>!pG!<8!np@F3YI zU(1f_seTBAlu~#a+(|=RwXXU4l~^cPCkbAEGRIl#y)$z026*Tm+MLee5G>v*JF24z8_CpL?LF+P9odagFea%QaYzJs0Z-T9kXi?vBcG z5(UGWc3Y#K!-X04n+%Y{<+SgVR(go(5}L>r&X-5cS-j37ya-c8pXGTk#i#{!$@gBT zJwp{~Z#rAKp_?OUja|GB&kpbwthf;8{uW%d_to_>dCrujN&0nDp8y&Of5HE>1_FKK zhG22@hV41|`x|YX2DPfuHaRAFhA$5Tqzv?mlYcOqW5UD2?3#~yJ;A|dLvuS`0lJwm zD1DDH83Iv={MqLU#GONg_843pG~&)(`f3j|#;B1k&gTXJxM=RC9_8Nt&qVCt7eB}gmzr<*dL};ofb~-Fe2Y@j&J#R&+V$nZC~6t zIXOvps|rXm_gBW#SDS03Bz$Sy>3IjIGd+#1R+h!QT-CGyWgXSsc_B|%7qn1<6IC>X zpUf4$e%D>dh$ZYh4Y#DNZW=B$&~@NPtsr@!T`MpkaO!(+=y6U#hx4|EZZVVdVccmo z134(v-fP#xt&oBy?TR7#&r={*M8eWes$`!mH?3vwvb|;(5cZ|GU7 z*I->6RXAySmJEy#JJ>}sD*|s^laErS*(QZUaY8EWN11m@Ql{s5iK(`hy~|BwiRexp zn*ff~j^8RRMWipNt?2kcrWkBkCN^uMy9>QGE{amL&loXGG{mr&X_7&ufM;5ttEvo0 zSXK;5nX0PYffcMbeJAXsdEpEQ(qXA~jp)^7Ypm4kK>L{@Auy(fa>xl%@$_tgF8}Y> zUMcyFHh7%@Oo%-L-Jt{)qZvZ}lc9P&-tW8*3j3awa%yqYJj7O;(?Tgwg1*wr6XS_R z|3B;R_oM0Ta{0Yj-Na!!X;7>xBLT~HlyOUU#0up^r`G}r?OQ!PAmU1o_iW~#dYzT% zh8wxxpq;S2iyKf)`@@hIk!%vR7Op#%ztXz-%X={_5%~@{GUwjkj0D#Gu}y`Cna(}6c#oYqxBbJJLKS5bEi0{onRCk% zaJ`X|GVv9Yh!f}5dBzkg>*_VPy_Sh+n_Coe;7njHiN0mrm@cmqNr&>Vj3xvnzt=XUVcQ=pPHLyfb5bDTPOr^f&%m`6& z25cweuB|O{#Hr7gqwuBuPG!$FsqRErWK>Gbl!Lln&2WWjNI@8WdlI*F%6#^I$~()f z-Vn1I>6EuQw)!(+;}Ic!HD?Jj^52)(aL)<~BZ`J&@@sVjXp1(jxKVI==ia7Ma&9sx ztozqVyq$ZupAb#Oqp0pRd}RNj59&E7MZOw>_aU^lcLvuRNyO|i!KsW7hU-Ye%9)mdIpI%<{jV zvz#k1v7BQeh@(nWJY^Q~-2N^shOx8AzydJrQQWtfpQ zI^)Fd^Ujk-LfOMt`e-v>aY%`Dnt1o$OD05C*z@KV;|}EN&9rcnd|=824*nDG@5xfWT1n7Q!H` z`Au8Oj`I-}PuRi~9=_OVg6>Kt%HBTc9Jm0R>@|lS(6ItKPuPJx&0*T>OCCiRL{x0M znDOAR5W-2#QGcoEeA-vfJr>#e+bkSwntEg0~L?zS;LJ@)l)4NXmgskzz?iiWXTM1+Zxm~K8W6>&cfTei>@Rhm#Gh=N9kVEB~sm~ zB|?gnXPK-d|N8%ZP4(GhiJ#EyqFiD^Fn+{ZWqh4Q=3!Gf-&TjpB=K`eOSoDmqhD5T zH$gX$3`t2zGhLHL(?8*?2S`I{+)XWwl;(2ZlNCRYP2wD%o9%3nnbAMSCNJXX6q4Vl zFWvy{RdG>B4jn7YO12$29O6;QL1yS99J%at?;$3Ak(7@`Dhp!SZ)K6WWKxjtpT>zc zWs9b@iY%#o7zwRyY!zo97tQX|GE8gu@}fW)_iew4_z`+@S@}vdT%%PFq}xILIUxz%);^|5cO>$t_)*Q zQPJjbDw;PGZ)Ra`sy+ihL4Oo|+=`oAZ~!W=v-;^|Si~uI!QjSNhvM<)C-8nGd=e%z zRn;+Fi}WWLpCpVO*YEb_iHcrKyix6RbuO`s;xT`3{-Px2;dUzrj!TF40%D3zfDWQ4 zF@$xc;`@{J^Ye2d&vVhTYY4v)-EeCB2WuU<_-jVh5A#Yo4@xRiWd=7FZ4Z>Uu;(fTubsxNh5FEpGei^1G;FR_!*R15N?K@ht%|Z$t(20su7XpCE3~=EmGM)Q@LK5I3XT3?nai;xnTkKY_DjK{gLRR{tR}n zkD2C@So0=MElL{vIDie(5!T5_546lel&CzErhI}=c7neS&z|Vk#(Z!jjIgyrXTo=1 z;35w1(4a(sYQ?_vH%r+Bl7%#rLDhS78VTnU{u2cbsR%qtRq(T4#Utw!>CmpUUJRJvB|eBQIT_{nK;B;d7O8+IRSInfIq!G<-X9AN!)W9%Oc1^3yQ+CPq`KeD=D^LJpHm9Ny(y({9NNviX0w$i7(&vOy5u4>JxY z!@Lh5#JX;0EY*yAvZpCEB@i^_e(hThUW`n%mZCx&;&J;p&WFk z?Jb3borgFStN03Qfj&h4@I*roEAXMizdFf$*gNwmZ#ka>`Xnir`KhC}v~(Y+K|HJk z;DB2G=H@17y|@4stDge{RV+3@U|7DMssmB!2sADeh~+CJe+1nH-}CZRJR!U-C~UOS8=vg##((iD)MPVc8PFhMUt8&Fd_j4K)&uL14hKd4{NaNkVc zpRc2Z17!yE6$51tEYGbmHTU~>pNpntTPrJf5NaP|J0J}QKxEag{g7N#1e$l044553 zukojrrH-ZMq|H1MjE=8+D3`iLVuC?2^$li;`o}y>fvJBE%Dy7c=7P@uVxLU8|0C%v z!>Vf9D14AQ2;xCN>F$u0?(Qz>4(XKc1`$LW3F&S`NU^lC}QMHAOBD#tgC^}-LmsHJ&iQ5Zwt{|*)Ta20quywn$u zk^%tt$%wFUI!vL0WK79UY8BF=MVQ+BLPD1 zg9_N~JqD1!+tZ9!^b`nEn|b&A&d5j~9F)Tz?_UPeHos@1oU~&I0779p5ng6%cxG~J zQ)s<1s`RS3HYemIRdv3Ly$|I&v<0n~vAW^*>Yrd@nS44g#B|XjEp&mo?3Qe#^p zd!cNW`P{a)EZ6%2z+D14)a|4O2*t0Mbp8R=?R#@`Gr-fJqdvg*0U86mU{b*!pzQda z?M!CdE)n(WsNdDBF@#YkXhcSs4*iKD>;#u1U5r~90G8nX{uC{P1S+|xq|g^6uXLVz z$OV~(R@=M{H*ta&BxUE)Buhl1+srRCHrqt&NKCtTb21OrW_>_0ynFEhfFOn*vlf3M zM$Yufkj(7n&%2)s`+}}Qrc)OhfUMFvtl)uF*bZhF-9>j4ulE*zW!ShVT6IT;mV12K zO)sP_PXLlEapahT0lH%pnD%!$+{PDsHK8WWOxXk_PGgG&Sd(L7l(Yd4sHSX8t98Y%}h}agXJ|eG=O_kRF2pS zI)6+??U`yI-~k|mpeeXYeoP+ou6y0<mT7jeqn{mEQ`l!CSs+;F%181&xzv z(!INW@6s>_TUn%&7&9UxJ>7WA-I$ZKW?&txem zwD>SGge@jRg&UUTf4vQ`reA|{To~$dD@+>FS&`F42Z7Ch!c7>XExc24f@KiOENIC9 zBj^XJ82|f|>=4EUoU%GN-_Y(EW--qqVNrGUKd>x~z~Ns2xFaRio6>P>(eyEOWV7Yq z`!19meCB{`QfHwH1S~bG7X$tM-~I%n1986>F9Y;fm|nW}bpbr^b;qsC#b?Xv4OMsV zPWm@Zi36KYqVylAu)bzx5rg&0@t|GX>2*u;U=T1?vts7Bn&L`5qu=_D*96^tFp7t*4nZG!> zq-%Zw?}UiVivkl9bLschLU=JfO8oovof8g%$4DUw>qFcqW4>wICI9t0wNzel(HYgJ4i66Z&R zQe9cF!DgI>zbn|U^G|0;6_~xy(9mqZEAoJYd!(0NxxVbb82wv1gMg807_w8#)VHVD zet*3y=@$<>*nbiP8i_)+h{3Gd-~6i4u!CX2nR@q!=O*G9n@6wyCe0q$5PK zZ1D35#ECBp5fyVm`C>bn@FYx-74C~qjxnCogFzw7<`e%*G0yZ#j%-Uqg(%LZI;1x^ zF%%kv*K{{CQZF2}7xVn!u0pd6)2pRt2IuQ9W6;P1AFmH|(TmX*56q1%a~x9N$Qn{z z2#j2ksbyr@wZwB(hL_efwT=4lknNQYRCt=vk;IJeT5)TpieZf+#MPv8(?plPS*}8E zB1aV|%HI!ymp3d5DRD-vitRNO>a%qoo296`E3da+o9B@jxqL7QU)`2hb$D46E8}iH zJ+T)%t1h8lxPV6Y?t&V3PLAyIjQr^0^SJ>3Z|=e!{OQ26Kx}r*c-}J1Q7HZO4w!2nbu(`Q2c$N#j8IKJ#F#)@Qt*b9G(I z@es$e`Y!4|NQMffEGo24FPCHQO^rFCr@(zhCsM^wU_;pi zeH*K--?6mYiH&TwK7t%;e1`i_G&c5VJ%>>fn>W>GW4< z*srj-GBDBoa61GEB+_w~b8ZoTwO5I)6WsRnFDTA-c6L^}BVxw3u-;Npvc>C0jj!75 z{f?CHa?y!joWTY*C4$vq4;ROdccUc8!A9=B*pk(x>cn@*W^}SLs*x1((PHNKX042~ zA5^s2egZMr$a|Yw6;tp@8r|3HyWX6mjWxq9lBE1XZqA9mJ-Hq5?HXpL^-Q1z#r%^p zJ(|2$!C0;N6^Y>aJb{^=9axtjlrO`Wb!K9MYA`oK!R(`+d|X{Cl*lRW8#M6@&#-gw z*Du^sxyS!ZDE(ki(~x(6OpKKg!X^Va(Gk8~rpMnsI7}Qzh}GlFC&pb0a(i8IP?}lcQ0o(l!0k}Pbe-SnjQ7}?@obz;a_pr7sw}#FR2PLA4 zSi%xc#m7ArgLd}H_fm-|NCJEr#PFPqEgJuH4H!I*fuGq^S|X^2X~hZT9g&oqxbkI% zn?#Q7Uem`aOuXM!Au^667pd86%}!6Z?0bb9k|siiq;&y%x~s?Vu2Fm1zN&IwP1h`4 zqrW`$%{1&a`25b*+o0Zb1qVL?HG!TU<6t#oLbU+vq0Hc4xjA-`apEgX`qAC9-aW-7 z&t>sg_N8P7>C69K9CzM0=86Yji)-e10neeY#bg4A1pL^a%?M3SI& zlJy{SA*67`Je=yM17s4ws)$HoJ}r+op~(c5K$A)~fm*70`PIK0@!XFjsye1vj5H<1 z#oyKvboSFW$RUNYZ50TPWO$fiil0=$aMfV^S#TgPhLjTW{|z7C zZUuYRc0e`jIks^nw^{u~>$UmRf%0=&1d04~ml-8)oAnvLhh0-jRoEjJUG#_8LhX+!W_L2q*w%au9M3vXy}g}sqtrctA!?8-$fNI zX{m8~{@YK067%^i=lQ|n4d~2d@VW1RS8arMlPF~f897Tz&2;emry)h(q=-bbY9_mY zS$q-EWeuYfWGrY}yoH%ZJ#-VR6a1S5$(uO>e zgLBs|j6NuMrT_%qk-vl`2L1_P@QSiB4(7e@FEww=MhxjV^+2Z5Uzx#Q->%+5b9z;9 zIh+zXxGd*~&!(6EZN75|nfgXO*YNn$wN*6dt8Keq^5@WnR?n_hI68>Zu|J*U;tpuq zK$T43jQHzTN`KJPS>VS$o`~>=g2iO7|F7Z82z}yF?X!bLet!Oznwrtg6ID6MSq~I) zg3C&8ORp8WK|WRE2F?biD-T*(PMUv+*?H6&MQA*mqKRbLWS30k9u1*Z>MJqMINKjm}$JTZ>fN7jS#|b|STxXSelS#X$FN1T{PL z49;|uMkxh074{F@?`ModRX0m~acN;xyKF>`BF;9Yj8dD zn2V58_|%n7!VWegeC`c+d2Zj(yf6#K=8s`Kg%;aw|=KdJa_x&C`oO{48TSyP}C&f}}_TZnGhj zbZYDWt%dk7F}YdX&G>0^n<|1B*MqV8QSqU+_CPHBd|spl!?&->b{8=>fw#gAF#dUT z-bml^uU+ok@I9kpolwX5);P7d0y#75O6IX8rEe#yppa_6p>ueQN?1aDjg73jv6YsV z*6;^3U{Z#N;kn6trj%lNTy-j0$J3eaj>^ZM?fSOgDdW#L+nkpNzWtl9!^3LSsEzo(4q@I&(u!-u$6e3&Bm-lrTfBO`SGiT9;WGIEQ|SP zZ8<9`J+*&+0cWrNBtevyy3>8{qst&(LUnn6w0N?)m`p}Uv5fM}uPK5qTt=-&`^V!Y zA<0wEO1s&{h9BTb=|ra&yeJwujG4{2onJmMi=8WieieT5IA(a}_S*+jBu&km@gB7A zCLRL4!+0628`eU0_VRn zwIzDL6@Wl)uHflK2zZ75pYTI_9CA9V+OOx1zrVm1`)?K~zQe*;73ACud^dRbOIvXD zlj4C>z6)wrPFGtvkWL{VIzw`h8M9uNnv<7j3Y;;I*TXmY%JE*K%f+gd*R0$#dkGSl zrOChhZkM%FsLHW#iWt^a+lk1}B7htGKH?%`%E`=DZm)2#c|AD;*7=b%GlKsx(7Nrh zW{6-vYEVWht#v#79khOTotl)Mgvqow$s&wOp5HGqj-#kaCE0~%Qp1ZU@1ByBWL`9g zRe*KFYN^#^Ct9rD#i=59lYGj5o^Phut>0$)Y%|Bj$6_Bohp>()hx*yWFd_`r5Ng|9 zxV+-jV>eKx*VJp+9{sZ0e=vmY9Oz1M#Qf(#^$CX6dPuNfgAWzo%n?>&1TJ!$3;PJ) z5uFtNpFc^e-NdCdvJzT2lAm!j6VZC1Vp#V)$vX#q;4K1WxMbYpTc41*M$v0cTVk(m z+J&5=z^-@_74e0~c`It#$U}U+aS&UHmz;y~>&aW_<^p{)b$)2~N-Faept#vLF+_gM zj_@~k0Pa}5Na^lx3=0DzAx5wJC)M4+2A#ndkHbnLANw*k@B-gZD5t*o;^UbA&nvG| zhO)%`l0+KDS}M`lF!Fe=sdC*D&}Pz35|0-l-*Kk4+T~o3ZA)eIm`MG)^k6IHEp^@a zYreH&DWh<~?Fjc3y)A7xq+nqyMS$sNf`PgocHQ;r{mtPzjo`<+5b(*&=5q%v2WE&! zq6!aeO5CKIQ}I(23KMJ(wKk&kPap>z|1gIG(<}=a57ENUds8O*v z$YoEdB1J7-pxY+8G9H-z5Y-8BUMaZhJwu&s4cZtNE1ZwTUtcdoqT2DHy>4@)7M=?k zv^Ec|TY&J@c>d6Np6DO=+B!(&&#YDUVzo&KaR?0_r(ZkSroJY=*vFcFqLV+Hl~|19 z$)p2sQLrn|gN-KN=oWGBjoa??9`LmcJ;VYeYbS^=VDaMqx`2Gy!xBY8u;DY-6KN`X zS83|?!Ya(k8@wcx)y>oSCe1xeUklS*!jY>sB0i@IK3&Ewm*)Q5kL z-X}BZvV;CIFd#TAw;O~q?+f54-giW>Wb>@VuQ(N}TfF4j{-W%W?14~Bt#6gSP||GH zxaRnMJ6ZVlDBa`G;~NXxDcDE?6HAo=aBa;ua)G{LeNIW!H6mT!2$6(os?$W{On}Jx zKpOtJ=G9K}HDUYo-Q+L^nho`(`?Lg^n2xL(_6;wGRO!LJj)!PJnFLhSpVj_M8(SyS zRSKjbSp3qn8i?j#ZW43PdO{shTu$eQ*Pt{PNjzyF&cboqIaRumWpriRF3Xfk)_jdE z`xB1>$7X1e-JqJ#l{7}Y1)+Ba=&ht6BnMbLjDSr9V1v>g9*xEOO6x1iRqICu#%vTB zdhMRbbulhCKg-cO0nz4mwDyiU1c_|TM^NSxR6@6_M}4Tt+WOwJ*$2%x2{I33%_MJF zLkqo}&@ZqU%~0NY`mfI3r%|$T*G-SwilLB|T0aCE&7-gq9AD}+a@qTbSbJ3(TD@RS zfuWhfo}nyRw2i&gu{@cI?@}D%K#$kNc17Sou=;@!l^%`xZ1j|%Yn9=Sk-pwh@B=;A@Fl%jb1dm7^uD0j@~~-M}NMuj{cG<6>K&KXtQs@?%`k- z0_sYH#S}7X=O2H|L+ECL63l!4%~^SQg$d>!;>k2qlEiOm!AGcp-Ux^f}o7i9{UTsh1@P2IcV-mSJKSFiZ2IcQ-Sk((eB)#Bl3xj<1Y*s z8s4$`Pz>cs{VaZjf$H<8s%|aSyXf}79RZYH;gwKq%=0kdy-Nqz1BMtdD*4KNLNjlP zzln=H>d$+yM2!46WGgVf<2fC zYuZQP{j*(ats*3_r7H+6_KSXsE2)J;A-g7Wyue}mzEr5FT@gR559=rLHyb_t(K@6o ziwwN5z>+B5+P`*{x9NW|L=wsEPRzDz8>M57&ANLZ)<1usEzM9zY%Gw(g<{roxt0#W z>tmO`HdWkY!(DaNzK^4kB|!ogP2Z+xWIW1FQ1xuuFYitN{pkcuUE%L>0~D!m+P2Oi zRYGqx`*S-X@}sqSQPYPfp!r1NwbuVLCIE6H^SPVX(bo3(<}NNS4!92`POnCU()Lvn zl?i;r^deDuz0AcLIy4R8UNcQ!8*CjM2HrFA@^FOJzi|6(&rWm@oWyhp-#^5^N;&G0 zkT=8fLCZmRKx{bB-*U2`hhzLGu|5qJw;PPLjcQiX_TDe#y${5~2zMXPFZbzM!+H4< z5NQX-Mj-Wop=#O(sL-adl35;EFHI(%auR4S#lb{6Ms2IX_Jhsm6L6j|{kRd>fszaC z6n_=Evx93dGhOc0HFH?{1MsT@8M5$xNHC!NS}vsaxn%&~MyeS=bA^LcQpfK4JT}|s zs4+di%+O~B+uZ= zGaPBZ!w`gfzORB^8~Cr~#qHmy;GIFS`kK;0`1H=Sc(|xd6O*Y)ti@H1HYRYBl-Rsg zQ%js7+A~!s?aR=65}K3|%YoDVj2`FdoqnMeqbY7^s7P84S>6=4S;FRA2dx>aT^|uw zoHcw(a49V8j=w_jg^2~y;wUlJXy$=RPGey^+aL5DlkxhECkDo;Fs>(&#ipj@mtjtD zHdO@f+aMJK1G9cke6ALMEOfDNAlpLQ$nPvCMXk$3EK;X^XJ>$#!jBzw6eRNf;B_6c zVQ@wY?o4eP0Oj{5wx>CMB(MW6P0T0yT{6iQ5$ZnYN76extwmWbwF=dR^snxYeB-AB z=IxshLW9W{Srr)j2bNl%7mMUdjxW*o%jfOfRbI?CVxhQmuKjR?!Z^P+${M($luCnrtrRGmy zA&1bdg5IR>h#`brf+sj%PAP(c5f3{#XW)axCK*8DkN1Hn>@U8AGomHTF_o*LPCV;A1 zQXEMVB-$pD2DPTQ@2C~PH{Oib0JJ8nBYN!nAEaI%_a*oT&A z>en^qlXK6o<2GL(%b}Sry>Y+p`V7Vo&!Vo+Iy(5!ya%lE&sT7AbM!t&@fAMcqfGwS zT0WO0d9kW=@Lb>@gxjViWo=|ckFV0Q!JfF0^kX!|#OEB^V#ePVjj~WC(N+^YDc11# zK6H<|h3I_uZZ#{~=YL-$V)Z2T9t`UL6?HK3P#Bm~RYG&8-b(PRmxn!(hdE;4vHk&y zFZTLx%ADbaw;h<>-{h2$5Nszix;TqVYchJSD_ibSm}oB=^@OOLTeBk`D=j8bUquBT z7JB+Lz{&lq-+%02mXTV@P_?VAlhxLE$*Skj@H6sTTJ&*@2t-wA@M_s1w{MDql7)d*oBHWpV424~*(Oml>M!}Ws`$+HH90b+U3v{+ZhLig@h?)zVTs44DN-<^$<^^X z2+4RH;m2x${As*T1V^U@c*e8vJS5(M)uWz0MWNH*%lHLE2YgljDsp8t1@6*{h!6C6 zf{*Qew7+Q}bYOib<*^_)mbkWhR>;(j^s*=ozN9p}Z*$gDzQ?nkyc!t^30QS}W`m2K6tQHeqZ+)Z z?nN*WT?%Hy<=aDT;p?%7d#95SN56mWI@8Yv>DEV)nMb>j#f;C&x5;n4@7a0J`qyq( z^MqY?5+1x(7Vj=Ljp=-E1eN3Xwi7Gn%MhecO-oVewezT^Y-Dc%kgFzoU}n zvNJY~p|-B(yLhYEnt;2_it_f=CI1WTKsK`X^XFO3cglWSqbZQiydaV%wM;GgmEEl{ z%aJbzZ{O~Cw0vR)#s(lO6e?vAgapr!I)phV|G?}zHy^3VFsmsjm^Ey#b)W3KHlD>i z)_O|3c803uICuW%q$>L)rA0WsWhSR^_H~`9u9-9Z6|?T5XTPqv^n?F)t-HwFkUw1S z(BB)5%w4I|kh^$z}oSjY0s84Qw`(9kvJ;^(wwg?_`4 zh@Cze?EBu%jS^9Sg{wTHh;>!A%jVrkreEhX;VYa@gmKCysG{7nZo4xS9;-~mP%<+C zqBMTC3G!Qm3GyHQ#SF)Op7+hn3^nUq5c1k_K@X^MYgvK6kmr#s_I>P}rN`}gOZM>% zqUWLuK12ZTDQd`ylZ@4rm1L|0St#uL>Om3d`#s4}l`;@0{IJ=vY-e|Rdz0Nn&C?Ls zg&yAirK7&G(&no4nXtoBLdN);mPz-ojg{M@v_`_F{ekTTet2di@hmt`W2U@h3ZH?L zClBD?0^t(^nM0kNiXdKZZjK-hB1=E%?pGz=%zQdus6WN??t+*fAv%kE(tl}(i}jk} zCfNGrb>l?Hi&TdTRkt`EfNy6_8wJCQ6OS3&JJZ2W3>$FcY$yEwfK$~5)a5mEmz%| zY+)6Q3hNFzCL9*+hA)%ma~}WRL2l7Ywzi7$Ky^r?hR%tFOUoH+KLnriyX~=$(pFgU z)PEorfrew!-~H`=kZ}Cmz&|W0!Q3lgs?y~jKsM(}Nkaqk{*&-Z=<@v%f0Yo%Wu=n+ zg$2K)-A#ssgVuPG)q}fFhGPE2wVQRpNBg>{Xo_Xm`E0%=@fMR3kB?=@` z#S5IY?zS$8(3Knct#=dUFMv^=Bk$+72pY%T?r3Mx>q?_Ei#iLKKhl1`)=B?(dW_cGR+y{ER+u@*_ z29N+-TLy9o%}L#Y(X|!_m)orMU=`aO@#Od9&etYa<#o;%um@Ih!h;j`)0@ zlv`U2N|b*5m+|nGmV!=;KgW;a+V2NjH7N?MTU9~Ek4sl~d`JHq&coqUL~|P-i(l1j z9m39Cnz&!#hn_vUyWDm@M;�=uc5H&$lmO#7zt_fl-G9axNq)s*u-eaa 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 aq`Nz8b;>K07%uVqKgqpRmMW7le*b?r>3g^U diff --git a/setup.cfg b/setup.cfg index db13bba..46eb6d6 100644 --- a/setup.cfg +++ b/setup.cfg @@ -66,15 +66,8 @@ testing = pytest-cov [options.entry_points] -# Add here console scripts like: -# console_scripts = -# script_name = tabgan.module:function -# For example: -# console_scripts = -# fibonacci = tabgan.skeleton:run -# And any other entry points, for example: -# pyscaffold.cli = -# awesome = pyscaffoldext.awesome.extension:AwesomeExtension +console_scripts = + tabgan-generate = tabgan.cli:main [test] # py.test options when running `python setup.py test` diff --git a/src/tabgan/cli.py b/src/tabgan/cli.py new file mode 100644 index 0000000..a2f6025 --- /dev/null +++ b/src/tabgan/cli.py @@ -0,0 +1,129 @@ +import argparse +import logging +from typing import List, Optional + +import pandas as pd + +from tabgan.sampler import ( + OriginalGenerator, + GANGenerator, + ForestDiffusionGenerator, + LLMGenerator, +) + + +def _parse_cat_cols(raw: Optional[str]) -> Optional[List[str]]: + if not raw: + return None + return [c.strip() for c in raw.split(",") if c.strip()] + + +def main() -> None: + """ + Command-line interface for generating synthetic tabular data with tabgan. + + Example: + tabgan-generate \\ + --input-csv train.csv \\ + --target-col target \\ + --generator gan \\ + --gen-x-times 1.5 \\ + --cat-cols year,gender \\ + --output-csv synthetic_train.csv + """ + parser = argparse.ArgumentParser( + description="Generate synthetic tabular data using tabgan samplers." + ) + parser.add_argument( + "--input-csv", + required=True, + help="Path to input CSV file containing training data (with or without target column).", + ) + parser.add_argument( + "--target-col", + default=None, + help="Name of the target column in the CSV (optional).", + ) + parser.add_argument( + "--output-csv", + required=True, + help="Path to write the generated synthetic dataset as CSV.", + ) + parser.add_argument( + "--generator", + choices=["original", "gan", "diffusion", "llm"], + default="gan", + help="Which sampler to use for generation.", + ) + parser.add_argument( + "--gen-x-times", + type=float, + default=1.1, + help="Factor controlling how many synthetic samples to generate relative to the training size.", + ) + parser.add_argument( + "--cat-cols", + default=None, + help="Comma-separated list of categorical column names (e.g. 'year,gender').", + ) + parser.add_argument( + "--only-generated", + action="store_true", + help="If set, output only synthetic rows instead of original + synthetic.", + ) + + args = parser.parse_args() + + logging.basicConfig(level=logging.INFO) + + logging.info("Reading input CSV from %s", args.input_csv) + df = pd.read_csv(args.input_csv) + + target_df = None + train_df = df + if args.target_col is not None: + if args.target_col not in df.columns: + raise ValueError(f"Target column '{args.target_col}' not found in input CSV.") + target_df = df[[args.target_col]] + train_df = df.drop(columns=[args.target_col]) + + cat_cols = _parse_cat_cols(args.cat_cols) + + generator_map = { + "original": OriginalGenerator, + "gan": GANGenerator, + "diffusion": ForestDiffusionGenerator, + "llm": LLMGenerator, + } + generator_cls = generator_map[args.generator] + + logging.info("Initializing %s generator", generator_cls.__name__) + generator = generator_cls( + gen_x_times=args.gen_x_times, + cat_cols=cat_cols, + only_generated_data=bool(args.only_generated), + ) + + # Use train_df itself as test_df when a dedicated hold-out set is not provided. + logging.info("Generating synthetic data...") + new_train, new_target = generator.generate_data_pipe( + train_df, target_df, train_df + ) + + if new_target is not None and args.target_col is not None: + out_df = new_train.copy() + # new_target can be DataFrame or Series; align to a 1D array + if hasattr(new_target, "values") and new_target.ndim > 1: + out_df[args.target_col] = new_target.values.ravel() + else: + out_df[args.target_col] = new_target + else: + out_df = new_train + + logging.info("Writing synthetic data to %s", args.output_csv) + out_df.to_csv(args.output_csv, index=False) + + +if __name__ == "__main__": + main() + diff --git a/tests/test_cli.py b/tests/test_cli.py new file mode 100644 index 0000000..5f526b7 --- /dev/null +++ b/tests/test_cli.py @@ -0,0 +1,51 @@ +import os +import subprocess +import sys +import tempfile + +import numpy as np +import pandas as pd + + +def test_tabgan_generate_cli_creates_output_with_target(): + # Prepare temporary input and output CSV paths + with tempfile.TemporaryDirectory() as tmpdir: + input_path = os.path.join(tmpdir, "train.csv") + output_path = os.path.join(tmpdir, "synthetic.csv") + + # Small dummy dataset with a target column + df = pd.DataFrame( + np.random.randint(0, 10, size=(20, 3)), + columns=["A", "B", "target"], + ) + df.to_csv(input_path, index=False) + + # Invoke the installed console script through Python -m to avoid PATH issues in CI + cmd = [ + sys.executable, + "-m", + "tabgan.cli", + "--input-csv", + input_path, + "--target-col", + "target", + "--generator", + "original", + "--gen-x-times", + "1.0", + "--output-csv", + output_path, + ] + + result = subprocess.run(cmd, check=False, capture_output=True, text=True) + + assert result.returncode == 0, f"CLI failed: {result.stderr}" + assert os.path.exists(output_path), "Output CSV was not created by CLI" + + out_df = pd.read_csv(output_path) + + # Target column must be present + assert "target" in out_df.columns + # At least as many rows as the original (OriginalGenerator samples with replacement) + assert len(out_df) >= len(df) + From b715e1ea936e3458ecfee57bc784d89b3660cb74 Mon Sep 17 00:00:00 2001 From: Insaf Ashrapov Date: Sat, 7 Mar 2026 13:57:49 +0300 Subject: [PATCH 4/6] fixed links --- src/tabgan/sampler.py | 238 ++++++++++++++++++++++++++---------------- 1 file changed, 148 insertions(+), 90 deletions(-) diff --git a/src/tabgan/sampler.py b/src/tabgan/sampler.py index f076795..53b2a45 100644 --- a/src/tabgan/sampler.py +++ b/src/tabgan/sampler.py @@ -393,16 +393,19 @@ def check_params(self): self.gen_params["epochs"])) self.gen_params["epochs"] = 3 - def generate_data( - self, train_df, target, test_df, only_generated_data: bool - ) -> Tuple[pd.DataFrame, pd.DataFrame]: - self._validate_data(train_df, target, test_df) - self.check_params() - + def _build_training_frame(self, train_df: pd.DataFrame, target: pd.DataFrame | None) -> pd.DataFrame: + """ + Return a copy of the training frame with TEMP_TARGET attached when a target is provided. + """ current_train_df = train_df.copy() if target is not None: current_train_df[self.TEMP_TARGET] = target + return current_train_df + def _fit_great_model(self, current_train_df: pd.DataFrame): + """ + Fit a GReaT model on the provided training frame and return the instance and inference device. + """ logging.info("Fitting LLM model") is_fp16 = torch.cuda.is_available() try: @@ -410,96 +413,151 @@ def generate_data( except ImportError: raise ImportError("be_great library is not installed. Please install it to use LLMGenerator.") - great_model_instance = GReaT(llm=self.gen_params["llm"], batch_size=self.gen_params["batch_size"], - epochs=self.gen_params["epochs"], fp16=is_fp16) + great_model_instance = GReaT( + llm=self.gen_params["llm"], + batch_size=self.gen_params["batch_size"], + epochs=self.gen_params["epochs"], + fp16=is_fp16, + ) great_model_instance.fit(current_train_df) logging.info("Finished training LLM model") - device = "cuda" if torch.cuda.is_available() else "cpu" # Needed for _generate_via_prompt + device = "cuda" if torch.cuda.is_available() else "cpu" + return great_model_instance, device + + def _conditional_text_generation( + self, + great_model_instance, + current_train_df: pd.DataFrame, + train_df: pd.DataFrame, + target: pd.DataFrame | None, + device: str, + ) -> pd.DataFrame: + """ + Generate rows when text and conditional columns are specified. + """ + logging.info("Starting conditional generation of text columns.") + num_samples_to_generate = int(self.gen_x_times * train_df.shape[0]) + + original_unique_text_values: dict[str, set] = {} + for col in self.text_generating_columns: + if col not in current_train_df.columns: + raise ValueError(f"Text generating column '{col}' not found in training data.") + original_unique_text_values[col] = set(current_train_df[col].unique()) + + attribute_distributions: dict[str, pd.Series] = {} + for col in self.conditional_columns: + if col not in current_train_df.columns: + raise ValueError(f"Conditional column '{col}' not found in training data.") + attribute_distributions[col] = current_train_df[col].value_counts(normalize=True) + + generated_rows: list[dict] = [] + all_train_columns = current_train_df.columns.tolist() + + for _ in range(num_samples_to_generate): + current_row_data: dict = {} + + for attr_col in self.conditional_columns: + dist = attribute_distributions[attr_col] + current_row_data[attr_col] = np.random.choice(dist.index, p=dist.values) + + row_template_for_impute = pd.DataFrame(columns=all_train_columns, index=[0]) + for col in all_train_columns: + if col in current_row_data: + row_template_for_impute.loc[0, col] = current_row_data[col] + elif col not in self.text_generating_columns: + row_template_for_impute.loc[0, col] = np.nan + + imputed_full_row_df = great_model_instance.impute( + row_template_for_impute.copy(), + max_length=self.gen_params.get("max_length", 500), + ) - if self.text_generating_columns and self.conditional_columns: - logging.info("Starting conditional generation of text columns.") - num_samples_to_generate = int(self.gen_x_times * train_df.shape[0]) - - original_unique_text_values = {} - for col in self.text_generating_columns: - if col not in current_train_df.columns: - raise ValueError(f"Text generating column '{col}' not found in training data.") - original_unique_text_values[col] = set(current_train_df[col].unique()) - - attribute_distributions = {} - for col in self.conditional_columns: - if col not in current_train_df.columns: - raise ValueError(f"Conditional column '{col}' not found in training data.") - attribute_distributions[col] = current_train_df[col].value_counts(normalize=True) - - generated_rows = [] - all_train_columns = current_train_df.columns.tolist() - - for _ in range(num_samples_to_generate): - current_row_data = {} - - # 1. Sample conditional attributes - for attr_col in self.conditional_columns: - dist = attribute_distributions[attr_col] - current_row_data[attr_col] = np.random.choice(dist.index, p=dist.values) - - row_template_for_impute = pd.DataFrame(columns=all_train_columns, index=[0]) - for col in all_train_columns: - if col in current_row_data: - row_template_for_impute.loc[0, col] = current_row_data[col] - elif col not in self.text_generating_columns: - row_template_for_impute.loc[0, col] = np.nan - - imputed_full_row_df = great_model_instance.impute(row_template_for_impute.copy(), - max_length=self.gen_params.get("max_length", 500)) - - for col in all_train_columns: - if col not in self.text_generating_columns and col not in current_row_data: - current_row_data[col] = imputed_full_row_df.loc[0, col] - - # 3. Generate novel text values - for text_col in self.text_generating_columns: - prompt_parts = [] - for cond_col in self.conditional_columns: - prompt_parts.append(f"{cond_col}: {current_row_data[cond_col]}") - for other_col in all_train_columns: - if (other_col not in self.text_generating_columns and other_col not in self.conditional_columns - and other_col in current_row_data): - val_str = str(current_row_data[other_col]) - if len(val_str) > 30: val_str = val_str[:27] + "..." - prompt_parts.append(f"{other_col}: {val_str}") - - prompt = ", ".join(prompt_parts) + f", Generate {text_col}: " - - generated_text_candidate = None - max_retries = 10 - for _retry_attempt in range(max_retries): - generated_text_candidate = self._generate_via_prompt(prompt, great_model_instance, - device=device) - if generated_text_candidate not in original_unique_text_values[text_col]: - break - else: # Max retries reached - logging.warning( - f"Max retries reached for generating novel text for {text_col}. Using last candidate.") - current_row_data[text_col] = generated_text_candidate - - # Ensure all columns are present in the order of original train_df (excluding TEMP_TARGET for generated_df) - ordered_row = {col: current_row_data.get(col) for col in - train_df.columns} # Uses original train_df columns - if target is not None and self.TEMP_TARGET in current_row_data: # Handle target if it was part of generation - ordered_row[self.TEMP_TARGET] = current_row_data[self.TEMP_TARGET] - - generated_rows.append(ordered_row) - - generated_df = pd.DataFrame(generated_rows) - generated_df = generated_df.reindex(columns=current_train_df.columns) + for col in all_train_columns: + if col not in self.text_generating_columns and col not in current_row_data: + current_row_data[col] = imputed_full_row_df.loc[0, col] + + for text_col in self.text_generating_columns: + prompt_parts: list[str] = [] + for cond_col in self.conditional_columns: + prompt_parts.append(f"{cond_col}: {current_row_data[cond_col]}") + for other_col in all_train_columns: + if ( + other_col not in self.text_generating_columns + and other_col not in self.conditional_columns + and other_col in current_row_data + ): + val_str = str(current_row_data[other_col]) + if len(val_str) > 30: + val_str = val_str[:27] + "..." + prompt_parts.append(f"{other_col}: {val_str}") + + prompt = ", ".join(prompt_parts) + f", Generate {text_col}: " + + generated_text_candidate = None + max_retries = 10 + for _retry_attempt in range(max_retries): + generated_text_candidate = self._generate_via_prompt( + prompt, + great_model_instance, + device=device, + ) + if generated_text_candidate not in original_unique_text_values[text_col]: + break + else: + logging.warning( + f"Max retries reached for generating novel text for {text_col}. Using last candidate." + ) + current_row_data[text_col] = generated_text_candidate + ordered_row = {col: current_row_data.get(col) for col in train_df.columns} + if target is not None and self.TEMP_TARGET in current_row_data: + ordered_row[self.TEMP_TARGET] = current_row_data[self.TEMP_TARGET] + + generated_rows.append(ordered_row) + + generated_df = pd.DataFrame(generated_rows) + return generated_df.reindex(columns=current_train_df.columns) + + def _standard_llm_sampling( + self, + great_model_instance, + current_train_df: pd.DataFrame, + device: str, + ) -> pd.DataFrame: + """ + Fallback sampling when no explicit text/conditional columns are provided. + """ + logging.info("Starting standard LLM sampling.") + return great_model_instance.sample( + int(self.gen_x_times * current_train_df.shape[0]), + device=device, + max_length=self.gen_params["max_length"], + ) + + def generate_data( + self, train_df, target, test_df, only_generated_data: bool + ) -> Tuple[pd.DataFrame, pd.DataFrame]: + self._validate_data(train_df, target, test_df) + self.check_params() + + current_train_df = self._build_training_frame(train_df, target) + great_model_instance, device = self._fit_great_model(current_train_df) + + if self.text_generating_columns and self.conditional_columns: + generated_df = self._conditional_text_generation( + great_model_instance, + current_train_df=current_train_df, + train_df=train_df, + target=target, + device=device, + ) else: - logging.info("Starting standard LLM sampling.") - generated_df = great_model_instance.sample(int(self.gen_x_times * current_train_df.shape[0]), - device=device, - max_length=self.gen_params["max_length"]) + generated_df = self._standard_llm_sampling( + great_model_instance, + current_train_df=current_train_df, + device=device, + ) return self.handle_generated_data(train_df, generated_df, only_generated_data) From 0f7fbddb0e0a610cbedd5ec711b3f85c6e7b045b Mon Sep 17 00:00:00 2001 From: Insaf Ashrapov Date: Sat, 7 Mar 2026 14:45:29 +0300 Subject: [PATCH 5/6] fixed test --- .gitignore | 1 + src/tabgan/abc_sampler.py | 30 +++++- src/tabgan/sampler.py | 8 +- tests/conftest.py | 22 ++-- tests/test_cli.py | 7 +- tests/test_sampler.py | 216 ++++++++++++++++++++++++++++++++------ 6 files changed, 243 insertions(+), 41 deletions(-) diff --git a/.gitignore b/.gitignore index 787cbdf..6dd64c4 100644 --- a/.gitignore +++ b/.gitignore @@ -132,3 +132,4 @@ dmypy.json .DS_Store /src/tabgan/trainer_great/ +/tests/trainer_great/ diff --git a/src/tabgan/abc_sampler.py b/src/tabgan/abc_sampler.py index b44a5ed..f8ae341 100644 --- a/src/tabgan/abc_sampler.py +++ b/src/tabgan/abc_sampler.py @@ -83,7 +83,35 @@ def generate_data_pipe( class Sampler(ABC): - """Interface for each sampling strategy""" + """Interface for each sampling strategy. + + Concrete sampler implementations share a common configuration interface + (generation factor, categorical columns, post-processing flags, etc.). + This base ``__init__`` stores those shared parameters so that subclasses + can call ``super().__init__(...)`` and focus on strategy-specific logic. + """ + + def __init__( + self, + gen_x_times: float, + cat_cols: list | None, + bot_filter_quantile: float, + top_filter_quantile: float, + is_post_process: bool, + adversarial_model_params: dict, + pregeneration_frac: float, + only_generated_data: bool, + gen_params: dict | None = None, + ) -> None: + self.gen_x_times = gen_x_times + self.cat_cols = cat_cols + self.bot_filter_quantile = bot_filter_quantile + self.top_filter_quantile = top_filter_quantile + self.is_post_process = is_post_process + self.adversarial_model_params = adversarial_model_params + self.pregeneration_frac = pregeneration_frac + self.only_generated_data = only_generated_data + self.gen_params = gen_params or {} def get_generated_shape(self, input_df): """Calculates final output shape""" diff --git a/src/tabgan/sampler.py b/src/tabgan/sampler.py index 53b2a45..09a50f6 100644 --- a/src/tabgan/sampler.py +++ b/src/tabgan/sampler.py @@ -559,7 +559,13 @@ def generate_data( device=device, ) - return self.handle_generated_data(train_df, generated_df, only_generated_data) + # When a target is provided, ``current_train_df`` already includes the + # TEMP_TARGET column and represents the true training frame used for + # generation. Passing it to ``handle_generated_data`` keeps feature and + # target alignment consistent for both conditional and standard LLM + # sampling paths. + base_train_for_handling = current_train_df if target is not None else train_df + return self.handle_generated_data(base_train_for_handling, generated_df, only_generated_data) def _generate_via_prompt(self, prompt: str, great_model_instance, device: str, max_tokens_to_generate=50) -> str: """ diff --git a/tests/conftest.py b/tests/conftest.py index ffa0de2..d97df36 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,11 +1,21 @@ # -*- coding: utf-8 -*- """ - Dummy conftest.py for tabgan. +Test configuration for tabgan. - If you don't know what this is for, just leave it empty. - Read more about conftest.py under: - - https://docs.pytest.org/en/stable/fixture.html - - https://docs.pytest.org/en/stable/writing_plugins.html +We ensure that the project `src` directory is on ``sys.path`` so that both +``src.tabgan`` and sibling top-level packages such as ``_ForestDiffusion`` +are importable when running tests from the repository root. """ -# import pytest +import os +import sys +from pathlib import Path + + +PROJECT_ROOT = Path(__file__).resolve().parents[1] +SRC_PATH = PROJECT_ROOT / "src" + +src_str = os.fspath(SRC_PATH) +if src_str not in sys.path: + sys.path.insert(0, src_str) + diff --git a/tests/test_cli.py b/tests/test_cli.py index 5f526b7..b4886d9 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -20,6 +20,11 @@ def test_tabgan_generate_cli_creates_output_with_target(): ) df.to_csv(input_path, index=False) + # Set up environment with PYTHONPATH pointing to src directory + env = os.environ.copy() + src_path = os.path.join(os.path.dirname(__file__), "..", "src") + env["PYTHONPATH"] = src_path + os.pathsep + env.get("PYTHONPATH", "") + # Invoke the installed console script through Python -m to avoid PATH issues in CI cmd = [ sys.executable, @@ -37,7 +42,7 @@ def test_tabgan_generate_cli_creates_output_with_target(): output_path, ] - result = subprocess.run(cmd, check=False, capture_output=True, text=True) + result = subprocess.run(cmd, check=False, capture_output=True, text=True, env=env) assert result.returncode == 0, f"CLI failed: {result.stderr}" assert os.path.exists(output_path), "Output CSV was not created by CLI" diff --git a/tests/test_sampler.py b/tests/test_sampler.py index 2364f6b..2ee45c7 100644 --- a/tests/test_sampler.py +++ b/tests/test_sampler.py @@ -9,7 +9,7 @@ import numpy as np import pandas as pd -from src.tabgan.sampler import OriginalGenerator, Sampler, GANGenerator, ForestDiffusionGenerator, LLMGenerator +from src.tabgan.sampler import OriginalGenerator, Sampler, GANGenerator, ForestDiffusionGenerator, LLMGenerator, SamplerLLM class TestOriginalGenerator(TestCase): @@ -117,14 +117,14 @@ def setUp(self): self.gen_params = {"batch_size": 32, "epochs": 1, "llm": "distilgpt2", "max_length": 50} - @patch('tabgan.sampler.GReaT') # Mock GReaT where it's imported in sampler.py - @patch.object(LLMGenerator, '_generate_via_prompt') - def test_conditional_generation_basic(self, mock_generate_prompt, mock_great_constructor): - # --- Mock GReaT setup --- - mock_great_instance = mock_great_constructor.return_value + @patch.object(SamplerLLM, "_fit_great_model") + @patch.object(SamplerLLM, "_generate_via_prompt") + def test_conditional_generation_basic(self, mock_generate_prompt, mock_fit_great): + # --- Mock GReaT setup (via patched _fit_great_model) --- + mock_great_instance = MagicMock() mock_great_instance.fit.return_value = None - mock_great_instance.model = MagicMock() # mock the underlying llm - mock_great_instance.tokenizer = MagicMock() # mock the tokenizer + mock_great_instance.model = MagicMock() # mock the underlying llm + mock_great_instance.tokenizer = MagicMock() # mock the tokenizer # Configure mock_great_instance.impute # It should take a DataFrame and fill NaNs in 'Age' and 'Occupation' for this test @@ -138,6 +138,7 @@ def mock_impute_logic(df_to_impute, max_length): df_imputed.loc[0, "Occupation"] = "MockOccupationF" if gender == "F" else "MockOccupationM" return df_imputed mock_great_instance.impute.side_effect = mock_impute_logic + mock_fit_great.return_value = (mock_great_instance, "cpu") # Configure mock_generate_prompt for "Name" # It needs to return different names based on gender and ensure novelty @@ -173,18 +174,15 @@ def mock_prompt_logic(prompt_text, great_model_inst, device): # Disable post_process and adversarial for simpler focused test is_post_process=False ) - # Get the actual sampler object - llm_sampler = llm_generator.get_object_generator() - # --- Run generation --- # For this test, target can be None as LLMGenerator handles it internally if provided # and we are mostly concerned with feature generation. # test_df is also not strictly necessary if is_post_process=False - new_train_df, _ = llm_sampler.generate_data_pipe( + new_train_df, _ = llm_generator.generate_data_pipe( self.train_df.copy(), - target=None, # Or self.target_df.copy() if testing with target - test_df=self.test_df.copy(), # Or None - only_generated_data=True # Focus on generated samples + target=None, # Or self.target_df.copy() if testing with target + test_df=None, # test_df not needed when postprocessing is disabled + only_generated_data=True, # Focus on generated samples ) # --- Assertions --- @@ -224,10 +222,11 @@ def mock_prompt_logic(prompt_text, great_model_inst, device): for _, row in generated_M.iterrows(): self.assertIn(row["Name"], ["Peter", "David"]) - @patch('tabgan.sampler.GReaT') - def test_llm_generator_fallback_behavior(self, mock_great_constructor): - # --- Mock GReaT setup for standard sampling --- - mock_great_instance = mock_great_constructor.return_value + @patch.object(SamplerLLM, "_fit_great_model") + @patch.object(SamplerLLM, "_generate_via_prompt") + def test_llm_generator_fallback_behavior(self, mock_generate_prompt, mock_fit_great): + # --- Mock GReaT setup for standard sampling (via patched _fit_great_model) --- + mock_great_instance = MagicMock() mock_great_instance.fit.return_value = None # Expected columns for the dummy generated data by great_model_instance.sample @@ -241,6 +240,7 @@ def test_llm_generator_fallback_behavior(self, mock_great_constructor): ["SampledName2", "M", 55, "SampledOccupation2"] ], columns=sample_columns) mock_great_instance.sample.return_value = dummy_sampled_data + mock_fit_great.return_value = (mock_great_instance, "cpu") # --- LLMGenerator setup (no text_generating_columns) --- llm_generator = LLMGenerator( @@ -248,31 +248,183 @@ def test_llm_generator_fallback_behavior(self, mock_great_constructor): gen_params=self.gen_params, is_post_process=False ) - llm_sampler = llm_generator.get_object_generator() - - # --- Spy on _generate_via_prompt --- - # We want to ensure it's NOT called in this fallback scenario - llm_sampler._generate_via_prompt = MagicMock() - # --- Run generation --- - new_train_df, _ = llm_sampler.generate_data_pipe( + new_train_df, _ = llm_generator.generate_data_pipe( self.train_df.copy(), target=None, - test_df=self.test_df.copy(), - only_generated_data=True + test_df=None, + only_generated_data=True, ) # --- Assertions --- self.assertEqual(len(new_train_df), 2) mock_great_instance.sample.assert_called_once() - llm_sampler._generate_via_prompt.assert_not_called() + mock_generate_prompt.assert_not_called() # Check if the output matches the dummy_sampled_data pd.testing.assert_frame_equal(new_train_df.reset_index(drop=True), dummy_sampled_data.reset_index(drop=True)) -# TODO: Add TestSamplerLLMWithTarget to test scenarios where target is not None for LLM. -# TODO: Add test for novelty retry logic (more complex mock for _generate_via_prompt) -# TODO: Add test for edge cases (e.g. text_generating_columns or conditional_columns are empty/None after being set) +class TestSamplerLLMWithTarget(TestCase): + def setUp(self): + self.train_df = pd.DataFrame({ + "Name": ["Anna", "Maria", "Ivan", "Sergey"], + "Gender": ["F", "F", "M", "M"], + "Age": [25, 30, 35, 40], + "Occupation": ["Engineer", "Doctor", "Artist", "Teacher"], + }) + self.target_df = pd.DataFrame({"Y": [0, 1, 0, 1]}) + self.gen_params = {"batch_size": 32, "epochs": 3, "llm": "distilgpt2", "max_length": 50} + + @patch.object(SamplerLLM, "_fit_great_model") + @patch.object(SamplerLLM, "_generate_via_prompt") + def test_conditional_generation_with_target(self, mock_generate_prompt, mock_fit_great): + # Configure mocked GReaT instance + mock_great_instance = MagicMock() + + def mock_impute_logic(df_to_impute, max_length): + df_imputed = df_to_impute.copy() + # Ensure TEMP_TARGET is imputed so that generated targets are not all NaN + if "TEMP_TARGET" in df_imputed.columns and pd.isna(df_imputed.loc[0, "TEMP_TARGET"]): + df_imputed.loc[0, "TEMP_TARGET"] = 1 + # Fill numeric/text fields to avoid NaNs in generated features + for col in ["Age", "Occupation"]: + if col in df_imputed.columns and pd.isna(df_imputed.loc[0, col]): + df_imputed.loc[0, col] = {"Age": 33, "Occupation": "MockOccupation"}.get(col) + return df_imputed + + mock_great_instance.impute.side_effect = mock_impute_logic + mock_fit_great.return_value = (mock_great_instance, "cpu") + + # Simple prompt generation just to avoid calling the real model + mock_generate_prompt.return_value = "GeneratedName" + + llm_generator = LLMGenerator( + gen_x_times=0.5, + text_generating_columns=["Name"], + conditional_columns=["Gender"], + gen_params=self.gen_params, + is_post_process=False, + ) + llm_sampler = llm_generator.get_object_generator() + + # Call SamplerLLM.generate_data directly with a non-None target + new_train_df, new_target = llm_sampler.generate_data( + self.train_df.copy(), + self.target_df.copy(), + test_df=None, + only_generated_data=True, + ) + + # We expect 0.5 * 4 = 2 generated rows and aligned target + self.assertEqual(len(new_train_df), 2) + self.assertIsNotNone(new_target) + self.assertEqual(len(new_target), 2) + + # TEMP_TARGET should be present in the frame passed to _fit_great_model + passed_train_df = mock_fit_great.call_args[0][0] + self.assertIn("TEMP_TARGET", passed_train_df.columns) + # Original target values should be copied into TEMP_TARGET for training + self.assertTrue((passed_train_df["TEMP_TARGET"].reset_index(drop=True) == self.target_df["Y"]).all()) + + @patch.object(SamplerLLM, "_fit_great_model") + @patch.object(SamplerLLM, "_generate_via_prompt") + def test_novelty_retry_logic(self, mock_generate_prompt, mock_fit_great): + # Train data with a single unique name that should be treated as "non-novel" + train_df = pd.DataFrame({ + "Name": ["Anna", "Anna"], + "Gender": ["F", "F"], + "Age": [25, 30], + "Occupation": ["Engineer", "Doctor"], + }) + + mock_great_instance = MagicMock() + + def mock_impute_logic(df_to_impute, max_length): + # Just return the same frame; we only care about the text column here + return df_to_impute.fillna({"Age": 33, "Occupation": "MockOccupation"}) + + mock_great_instance.impute.side_effect = mock_impute_logic + mock_fit_great.return_value = (mock_great_instance, "cpu") + + # First call returns a non-novel name (present in original data), + # second call returns a novel one to exercise retry logic. + mock_generate_prompt.side_effect = ["Anna", "NewAnna"] + + llm_generator = LLMGenerator( + gen_x_times=0.5, # 1 new sample from 2 original rows + text_generating_columns=["Name"], + conditional_columns=["Gender"], + gen_params=self.gen_params, + is_post_process=False, + ) + llm_sampler = llm_generator.get_object_generator() + + new_train_df, _ = llm_sampler.generate_data( + train_df.copy(), + target=None, + test_df=None, + only_generated_data=True, + ) + + # Retry logic should cause at least two calls to _generate_via_prompt + self.assertGreaterEqual(mock_generate_prompt.call_count, 2) + + # The finally stored name must be the novel one, not the original "Anna" + self.assertEqual(len(new_train_df), 1) + self.assertEqual(new_train_df.iloc[0]["Name"], "NewAnna") + + def test_empty_text_or_conditional_columns_use_fallback_sampling(self): + llm_generator = LLMGenerator( + gen_x_times=0.5, + text_generating_columns=["Name"], + conditional_columns=["Gender"], + gen_params=self.gen_params, + is_post_process=False, + ) + llm_sampler = llm_generator.get_object_generator() + + dummy_generated = pd.DataFrame( + [ + ["SampledName1", "F", 50, "SampledOccupation1"], + ["SampledName2", "M", 55, "SampledOccupation2"], + ], + columns=self.train_df.columns, + ) + + # Case 1: text_generating_columns cleared to empty list -> fallback to standard sampling + llm_sampler.text_generating_columns = [] + with patch.object(SamplerLLM, "_fit_great_model", return_value=(MagicMock(), "cpu")) as mock_fit, \ + patch.object(SamplerLLM, "_conditional_text_generation") as mock_conditional, \ + patch.object(SamplerLLM, "_standard_llm_sampling", return_value=dummy_generated) as mock_standard: + new_train_df, _ = llm_sampler.generate_data( + self.train_df.copy(), + target=None, + test_df=None, + only_generated_data=True, + ) + + mock_fit.assert_called_once() + mock_standard.assert_called_once() + mock_conditional.assert_not_called() + pd.testing.assert_frame_equal(new_train_df.reset_index(drop=True), dummy_generated.reset_index(drop=True)) + + # Case 2: conditional_columns cleared to None -> fallback to standard sampling again + llm_sampler = llm_generator.get_object_generator() + llm_sampler.conditional_columns = None + with patch.object(SamplerLLM, "_fit_great_model", return_value=(MagicMock(), "cpu")) as mock_fit, \ + patch.object(SamplerLLM, "_conditional_text_generation") as mock_conditional, \ + patch.object(SamplerLLM, "_standard_llm_sampling", return_value=dummy_generated) as mock_standard: + new_train_df, _ = llm_sampler.generate_data( + self.train_df.copy(), + target=None, + test_df=None, + only_generated_data=True, + ) + + mock_fit.assert_called_once() + mock_standard.assert_called_once() + mock_conditional.assert_not_called() + pd.testing.assert_frame_equal(new_train_df.reset_index(drop=True), dummy_generated.reset_index(drop=True)) class TestSamplerSamplerDiffusion(TestCase): def setUp(self): From 20947faddad395744a8cca4f58f8252b45baaf5d Mon Sep 17 00:00:00 2001 From: Insaf Ashrapov Date: Sat, 7 Mar 2026 15:24:14 +0300 Subject: [PATCH 6/6] fixed test --- README.md | 331 ++++++++++++++++++++++++++++------------------- requirements.txt | 2 +- setup.cfg | 2 +- 3 files changed, 198 insertions(+), 137 deletions(-) diff --git a/README.md b/README.md index 6261032..1c92d6d 100644 --- a/README.md +++ b/README.md @@ -1,100 +1,132 @@ [![CodeFactor](https://www.codefactor.io/repository/github/diyago/tabular-data-generation/badge)](https://www.codefactor.io/repository/github/diyago/tabular-data-generation) -[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) +[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) +[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) +[![Python Version](https://img.shields.io/pypi/pyversions/tabgan)](https://pypi.org/project/tabgan/) [![Downloads](https://pepy.tech/badge/tabgan)](https://pepy.tech/project/tabgan) -# GANs and TimeGANs, Diffusions, LLM for tabular data +# TabGAN - Synthetic Tabular Data Generation + +A powerful library for generating high-quality synthetic tabular data using state-of-the-art generative models including GANs, Diffusion models, and Large Language Models. -Generative Networks are well-known for their success in realistic image generation. However, they can also be applied to generate tabular data. This library introduces major improvements for generating high-fidelity tabular data by offering a diverse suite of cutting-edge models, including Generative Adversarial Networks (GANs), specialized TimeGANs for time-series data, Denoising Diffusion Probabilistic Models (DDPM), and Large Language Model (LLM) based approaches. These enhancements allow for robust data generation across various dataset complexities and distributions, giving an opportunity to try GANs, TimeGANs, Diffusions, and LLMs for tabular data generation. -* Arxiv article: ["Tabular GANs for uneven distribution"](https://arxiv.org/abs/2010.00638) -* Medium post: GANs for tabular data [link broken] +## Overview -## How to use library +TabGAN provides a unified interface for generating synthetic tabular data using multiple generative approaches: -* Installation: `pip install tabgan` -* To generate new data to train by sampling and then filtering by adversarial training - call `GANGenerator().generate_data_pipe`. +- **GANs**: Conditional Tabular GAN (CTGAN) for modeling complex tabular distributions +- **Diffusion Models**: Forest Diffusion for high-quality synthetic data generation +- **LLMs**: GReaT framework for generating realistic tabular data using language models +- **Time-Series**: TimeGAN support for temporal data generation -### Data Format +*Related Research: [Tabular GANs for uneven distribution (arXiv)](https://arxiv.org/abs/2010.00638)* -TabGAN accepts data as a `numpy.ndarray` or `pandas.DataFrame` with columns categorized as: +## Installation -* **Continuous Columns**: Numerical columns with any possible value. -* **Discrete Columns**: Columns with a limited set of values (e.g., categorical data). +```bash +pip install tabgan +``` -Note: TabGAN does not differentiate between floats and integers, so all values are treated as floats. For integer requirements, round the output outside of TabGAN. +## Quick Start + +```python +import pandas as pd +import numpy as np +from tabgan.sampler import GANGenerator + +# Create sample data +train = pd.DataFrame(np.random.randint(-10, 150, size=(150, 4)), columns=list("ABCD")) +target = pd.DataFrame(np.random.randint(0, 2, size=(150, 1)), columns=list("Y")) +test = pd.DataFrame(np.random.randint(0, 100, size=(100, 4)), columns=list("ABCD")) + +# Generate synthetic data +new_train, new_target = GANGenerator().generate_data_pipe(train, target, test) +``` + +## Available Generators + +| Generator | Description | Best For | +|-----------|-------------|----------| +| `GANGenerator` | CTGAN-based generation | General tabular data with mixed types | +| `ForestDiffusionGenerator` | Diffusion models + tree-based methods | Complex tabular structures | +| `LLMGenerator` | Large Language Model based | Capturing complex dependencies | +| `OriginalGenerator` | Baseline sampler | Baseline comparisons | + +## API Reference ### Sampler Parameters -All samplers (`OriginalGenerator`, `GANGenerator`, `ForestDiffusionGenerator`, `LLMGenerator`) share the following input parameters: +All generators accept these common parameters: -* **gen_x_times**: `float` (default: `1.1`) - How much data to generate. The output might be less due to postprocessing and adversarial filtering. -* **cat_cols**: `list` (default: `None`) - A list of column names to be treated as categorical. -* **bot_filter_quantile**: `float` (default: `0.001`) - The bottom quantile for postprocess filtering. Values below this quantile will be filtered out. -* **top_filter_quantile**: `float` (default: `0.999`) - The top quantile for postprocess filtering. Values above this quantile will be filtered out. -* **is_post_process**: `bool` (default: `True`) - Whether to perform post-filtering. If `False`, `bot_filter_quantile` and `top_filter_quantile` are ignored. -* **adversarial_model_params**: `dict` (default: see below) - Parameters for the adversarial filtering model. Default values are optimized for binary classification tasks. - ```python - { - "metrics": "AUC", "max_depth": 2, "max_bin": 100, - "learning_rate": 0.02, "random_state": 42, "n_estimators": 100, - } - ``` -* **pregeneration_frac**: `float` (default: `2`) - For the generation step, `gen_x_times * pregeneration_frac` amount of data will be generated. However, after postprocessing, the aim is to return an amount of data equivalent to `(1 + gen_x_times)` times the size of the original dataset (if `only_generated_data` is `False`, otherwise `gen_x_times` times the size of the original dataset). -* **only_generated_data**: `bool` (default: `False`) - If `True`, only the newly generated data is returned, without concatenating the input training dataframe. -* **gen_params**: `dict` (default: see below) - Parameters for the underlying generative model training. Specific to `GANGenerator` and `LLMGenerator`. - * For `GANGenerator`: - ```python - {"batch_size": 500, "patience": 25, "epochs" : 500} - ``` - * For `LLMGenerator`: - ```python - {"batch_size": 32, "epochs": 4, "llm": "distilgpt2", "max_length": 500} - ``` - -The available samplers are: -1. **`GANGenerator`**: Utilizes the Conditional Tabular GAN (CTGAN) architecture, known for effectively modeling tabular data distributions and handling mixed data types (continuous and discrete). It learns the data distribution and generates synthetic samples that mimic the original data. -2. **`ForestDiffusionGenerator`**: Implements a novel approach using diffusion models guided by tree-based methods (Forest Diffusion). This technique is capable of generating high-quality synthetic data, particularly for complex tabular structures, by gradually adding noise to data and then learning to reverse the process. -3. **`LLMGenerator`**: Leverages Large Language Models (LLMs) using the GReaT (Generative Realistic Tabular data) framework. It transforms tabular data into a text format, fine-tunes an LLM on this representation, and then uses the LLM to generate new tabular instances by sampling from it. This approach is particularly promising for capturing complex dependencies and can generate diverse synthetic data. -4. **`OriginalGenerator`**: Acts as a baseline sampler. It typically returns the original training data or a direct sample from it. This is useful for comparison purposes to evaluate the effectiveness of more complex generative models. - - -### `generate_data_pipe` Method Parameters - -The `generate_data_pipe` method, available for all samplers, uses the following parameters: - -* **train_df**: `pd.DataFrame` - The training dataframe (features only, without the target variable). -* **target**: `pd.DataFrame` - The input target variable for the training dataset. -* **test_df**: `pd.DataFrame` - The test dataframe. The newly generated training dataframe should be statistically similar to this. -* **deep_copy**: `bool` (default: `True`) - Whether to make a copy of the input dataframes. If `False`, input dataframes will be modified in place. -* **only_adversarial**: `bool` (default: `False`) - If `True`, only adversarial filtering will be performed on the training dataframe; no new data will be generated. -* **use_adversarial**: `bool` (default: `True`) - Whether to perform adversarial filtering. -* **@return**: `Tuple[pd.DataFrame, pd.DataFrame]` - A tuple containing the newly generated/processed training dataframe and the corresponding target. - - -### Example Code +| Parameter | Type | Default | Description | +|-----------|------|---------|-------------| +| `gen_x_times` | float | 1.1 | Multiplier for data generation amount | +| `cat_cols` | list | None | Column names to treat as categorical | +| `bot_filter_quantile` | float | 0.001 | Bottom quantile for post-process filtering | +| `top_filter_quantile` | float | 0.999 | Top quantile for post-process filtering | +| `is_post_process` | bool | True | Enable post-filtering | +| `pregeneration_frac` | float | 2 | Pre-generation data multiplier | +| `only_generated_data` | bool | False | Return only generated data (no original) | +| `gen_params` | dict | See below | Generator-specific parameters | + +### Generator-Specific Parameters + +**GANGenerator:** +```python +{"batch_size": 500, "patience": 25, "epochs": 500} +``` + +**LLMGenerator:** +```python +{"batch_size": 32, "epochs": 4, "llm": "distilgpt2", "max_length": 500} +``` + +### generate_data_pipe Method + +| Parameter | Type | Description | +|-----------|------|-------------| +| `train_df` | pd.DataFrame | Training features | +| `target` | pd.DataFrame | Target variable | +| `test_df` | pd.DataFrame | Test features | +| `deep_copy` | bool | Make copy of input dataframes | +| `only_adversarial` | bool | Only perform adversarial filtering | +| `use_adversarial` | bool | Enable adversarial filtering | + +**Returns:** `Tuple[pd.DataFrame, pd.DataFrame]` - (new_train, new_target) + +## Data Format + +TabGAN accepts `numpy.ndarray` or `pandas.DataFrame` with: + +- **Continuous Columns**: Numerical columns with any possible value +- **Discrete Columns**: Columns with limited set values (categorical) + +> **Note:** TabGAN treats all values as floats. For integers, round the output after generation. + +## Examples + +### Basic Usage ```python from tabgan.sampler import OriginalGenerator, GANGenerator, ForestDiffusionGenerator, LLMGenerator import pandas as pd import numpy as np - -# random input data train = pd.DataFrame(np.random.randint(-10, 150, size=(150, 4)), columns=list("ABCD")) target = pd.DataFrame(np.random.randint(0, 2, size=(150, 1)), columns=list("Y")) test = pd.DataFrame(np.random.randint(0, 100, size=(100, 4)), columns=list("ABCD")) -# generate data -new_train1, new_target1 = OriginalGenerator().generate_data_pipe(train, target, test, ) -new_train2, new_target2 = GANGenerator(gen_params={"batch_size": 500, "epochs": 10, "patience": 5 }).generate_data_pipe(train, target, test, ) -new_train3, new_target3 = ForestDiffusionGenerator().generate_data_pipe(train, target, test, ) -new_train4, new_target4 = LLMGenerator(gen_params={"batch_size": 32, - "epochs": 4, "llm": "distilgpt2", "max_length": 500}).generate_data_pipe(train, target, test, ) +# Different generators +new_train1, new_target1 = OriginalGenerator().generate_data_pipe(train, target, test) +new_train2, new_target2 = GANGenerator(gen_params={"batch_size": 500, "epochs": 10, "patience": 5}).generate_data_pipe(train, target, test) +new_train3, new_target3 = ForestDiffusionGenerator().generate_data_pipe(train, target, test) +new_train4, new_target4 = LLMGenerator(gen_params={"batch_size": 32, "epochs": 4, "llm": "distilgpt2", "max_length": 500}).generate_data_pipe(train, target, test) +``` + +### Full Parameter Example -# example with all params defined -new_train_gan_all_params, new_target_gan_all_params = GANGenerator( +```python +new_train, new_target = GANGenerator( gen_x_times=1.1, cat_cols=None, bot_filter_quantile=0.001, @@ -113,108 +145,133 @@ new_train_gan_all_params, new_target_gan_all_params = GANGenerator( only_adversarial=False, use_adversarial=True ) +``` +### LLM Conditional Text Generation + +Generate synthetic data with LLMs while controlling text generation based on specific conditions. This uses the internal `_generate_via_prompt` method for novel text generation. + +```python +import pandas as pd +from tabgan.sampler import LLMGenerator + +# Create sample data with text and categorical columns +train = pd.DataFrame({ + "Name": ["Anna", "Maria", "Ivan", "Sergey", "Olga", "Boris"], + "Gender": ["F", "F", "M", "M", "F", "M"], + "Age": [25, 30, 35, 40, 28, 32], + "Occupation": ["Engineer", "Doctor", "Artist", "Teacher", "Manager", "Pilot"] +}) + +# Generate new names conditioned on Gender, with other features imputed +new_train, _ = LLMGenerator( + gen_x_times=1.5, # Generate 1.5x the original data + text_generating_columns=["Name"], # Generate novel names + conditional_columns=["Gender"], # Condition on Gender column + gen_params={"batch_size": 32, "epochs": 4, "llm": "distilgpt2", "max_length": 500}, + is_post_process=False # Disable post-processing for this example +).generate_data_pipe( + train, + target=None, + test_df=None, + only_generated_data=True # Return only generated data +) + +print(new_train) ``` -Thus, you may use this library to improve your dataset quality: +**Parameters for conditional generation:** +- `text_generating_columns`: List of column names to generate novel text for +- `conditional_columns`: List of column names that condition the text generation -``` python -def fit_predict(clf, X_train, y_train, X_test, y_test): - clf.fit(X_train, y_train) - return sklearn.metrics.roc_auc_score(y_test, clf.predict_proba(X_test)[:, 1]) +The model will: +1. Sample values for conditional columns from their distributions +2. Impute remaining non-text columns using the LLM +3. Generate novel text for text columns via prompt-based generation (using `_generate_via_prompt`) +4. Ensure generated text values are unique (not present in original data) +### Improving Model Performance +```python +import sklearn +from tabgan.sampler import GANGenerator +def evaluate(clf, X_train, y_train, X_test, y_test): + clf.fit(X_train, y_train) + return sklearn.metrics.roc_auc_score(y_test, clf.predict_proba(X_test)[:, 1]) + +# Load dataset dataset = sklearn.datasets.load_breast_cancer() clf = sklearn.ensemble.RandomForestClassifier(n_estimators=25, max_depth=6) X_train, X_test, y_train, y_test = sklearn.model_selection.train_test_split( - pd.DataFrame(dataset.data), pd.DataFrame(dataset.target, columns=["target"]), test_size=0.33, random_state=42) -print("initial metric", fit_predict(clf, X_train, y_train, X_test, y_test)) + pd.DataFrame(dataset.data), pd.DataFrame(dataset.target, columns=["target"]), + test_size=0.33, random_state=42) -new_train1, new_target1 = OriginalGenerator().generate_data_pipe(X_train, y_train, X_test, ) -print("OriginalGenerator metric", fit_predict(clf, new_train1, new_target1, X_test, y_test)) +# Compare performance +print("Baseline:", evaluate(clf, X_train, y_train, X_test, y_test)) -new_train1, new_target1 = GANGenerator().generate_data_pipe(X_train, y_train, X_test, ) -print("GANGenerator metric", fit_predict(clf, new_train2, new_target2, X_test, y_test)) # Corrected variable name +# Generate and evaluate +new_train, new_target = GANGenerator().generate_data_pipe(X_train, y_train, X_test) +print("With GAN:", evaluate(clf, new_train, new_target, X_test, y_test)) ``` -### Advanced Usage: Generating Time-Series Data with TimeGAN - -You can easily adjust the code to generate multidimensional time-series data. This approach primarily involves extracting day, month, and year components from a date column to be used as features in the generation process. Below is a demonstration: +### Time-Series Data Generation ```python import pandas as pd import numpy as np -from tabgan.utils import get_year_mnth_dt_from_date,make_two_digit,collect_dates -from tabgan.sampler import OriginalGenerator, GANGenerator +from tabgan.utils import get_year_mnth_dt_from_date, collect_dates +from tabgan.sampler import GANGenerator - -train_size = 100 -train = pd.DataFrame( - np.random.randint(-10, 150, size=(train_size, 4)), columns=list("ABCD") - ) -min_date = pd.to_datetime('2019-01-01') -max_date = pd.to_datetime('2021-12-31') +train = pd.DataFrame(np.random.randint(-10, 150, size=(100, 4)), columns=list("ABCD")) +min_date, max_date = pd.to_datetime('2019-01-01'), pd.to_datetime('2021-12-31') d = (max_date - min_date).days + 1 - -train['Date'] = min_date + pd.to_timedelta(np.random.randint(d, size=train_size), unit='d') +train['Date'] = min_date + pd.to_timedelta(np.random.randint(d, size=100), unit='d') train = get_year_mnth_dt_from_date(train, 'Date') -new_train, new_target = GANGenerator(gen_x_times=1.1, cat_cols=['year'], bot_filter_quantile=0.001, - top_filter_quantile=0.999, - is_post_process=True, pregeneration_frac=2, only_generated_data=False).\ - generate_data_pipe(train.drop('Date', axis=1), None, - train.drop('Date', axis=1) - ) +new_train, _ = GANGenerator( + gen_x_times=1.1, cat_cols=['year'], bot_filter_quantile=0.001, + top_filter_quantile=0.999, is_post_process=True, pregeneration_frac=2, + only_generated_data=False +).generate_data_pipe( + train.drop('Date', axis=1), None, train.drop('Date', axis=1) +) new_train = collect_dates(new_train) ``` -## Experiments -### Datasets and experiment design - -**Check for data generation quality** -Just use built-in function -``` -compare_dataframes(original_df, generated_df) # return between 0 and 1 -``` -**Running experiment** - -To run experiment follow these steps: +## Data Quality Validation -1. Clone the repository. All required datasets are stored in `./Research/data` folder. -2. Install requirements: `pip install -r requirements.txt` -3. Run experiments using `python ./Research/run_experiment.py`. You may - add more datasets, adjust validation type, and categorical encoders. -4. Observe metrics across all experiments in the console or in `./Research/results/fit_predict_scores.txt`. +Check generated data quality using the built-in function: +```python +from tabgan.utils import compare_dataframes -**Experiment design** +quality_score = compare_dataframes(original_df, generated_df) # Returns value between 0 and 1 +``` +### Experiment Workflow ![Experiment design and workflow](images/workflow.png) -**Picture 1.1** Experiment design and workflow +## Benchmark Results -## Results -The table below (Table 1.2) shows ROC AUC scores for different sampling strategies. To facilitate comparison across datasets with potentially different baseline AUC scores, the ROC AUC scores for each dataset were scaled using min-max normalization (where the maximum score achieved by any method on that dataset becomes 1, and the minimum becomes 0). These scaled scores were then averaged across all datasets for each sampling strategy. Therefore, a higher value in the table indicates better relative performance in generating data that is difficult for a classifier to distinguish from the original data, when compared to other methods on the same set of datasets. +The following table shows normalized ROC AUC scores (higher is better): -**Table 1.2** Averaged Min-Max Scaled ROC AUC scores for different sampling strategies across datasets. Higher is better (closer to 1 indicates performance similar to the best method on each dataset). - -| dataset_name | None | gan | sample_original | -|:-----------------------|-------------------:|------------------:|------------------------------:| -| credit | 0.997 | **0.998** | 0.997 | -| employee | **0.986** | 0.966 | 0.972 | -| mortgages | 0.984 | 0.964 | **0.988** | -| poverty_A | 0.937 | **0.950** | 0.933 | -| taxi | 0.966 | 0.938 | **0.987** | -| adult | 0.995 | 0.967 | **0.998** | +| Dataset | None | GAN | Sample Original | +|---------|------|-----|-----------------| +| credit | 0.997 | **0.998** | 0.997 | +| employee | **0.986** | 0.966 | 0.972 | +| mortgages | 0.984 | 0.964 | **0.988** | +| poverty_A | 0.937 | **0.950** | 0.933 | +| taxi | 0.966 | 0.938 | **0.987** | +| adult | 0.995 | 0.967 | **0.998** | ## Citation -If you use **tabgan** in a scientific publication, we would appreciate references to the following BibTex entry: -arxiv publication: +If you use TabGAN in your research, please cite: + ```bibtex @misc{ashrapov2020tabular, - title={Tabular GANs for uneven distribution}, + title={Tabular GANs for uneven distribution}, author={Insaf Ashrapov}, year={2020}, eprint={2010.00638}, @@ -227,8 +284,12 @@ arxiv publication: [1] Xu, L., & Veeramachaneni, K. (2018). *Synthesizing Tabular Data using Generative Adversarial Networks*. arXiv:1811.11264 [cs.LG]. -[2] Jolicoeur-Martineau, A., Fatras, K., & Kachman, T. (2023). *Generating and Imputing Tabular Data via Diffusion and Flow-based Gradient-Boosted Trees*. Retrieved from https://github.com/SamsungSAILMontreal/ForestDiffusion. +[2] Jolicoeur-Martineau, A., Fatras, K., & Kachman, T. (2023). *Generating and Imputing Tabular Data via Diffusion and Flow-based Gradient-Boosted Trees*. SamsungSAILMontreal/ForestDiffusion. [3] Xu, L., Skoularidou, M., Cuesta-Infante, A., & Veeramachaneni, K. (2019). *Modeling Tabular data using Conditional GAN*. NeurIPS. [4] Borisov, V., Sessler, K., Leemann, T., Pawelczyk, M., & Kasneci, G. (2023). *Language Models are Realistic Tabular Data Generators*. ICLR. + +## License + +Apache License 2.0 - See [LICENSE](LICENSE) file for details. diff --git a/requirements.txt b/requirements.txt index 7fb6002..4ac3b01 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,4 +9,4 @@ numpy>=1.23.1 python-dateutil>=2.8.2 tqdm>=4.61.1 xgboost>=2.0.0 -be-great==0.0.8 \ No newline at end of file +be-great==0.0.13 \ No newline at end of file diff --git a/setup.cfg b/setup.cfg index 46eb6d6..0ad8e13 100644 --- a/setup.cfg +++ b/setup.cfg @@ -47,7 +47,7 @@ install_requires = python-dateutil tqdm xgboost - be-great + be-great>=0.0.13 [options.packages.find] where = src