diff options
Diffstat (limited to 'split_dataset.py')
| -rw-r--r-- | split_dataset.py | 66 |
1 files changed, 52 insertions, 14 deletions
diff --git a/split_dataset.py b/split_dataset.py index 9ac7bbf..a161cc1 100644 --- a/split_dataset.py +++ b/split_dataset.py | |||
| @@ -7,10 +7,12 @@ def split_dataset( | |||
| 7 | input_filepath: str, | 7 | input_filepath: str, |
| 8 | train_filepath: str = "train.jsonl", | 8 | train_filepath: str = "train.jsonl", |
| 9 | validation_filepath: str = "validation.jsonl", | 9 | validation_filepath: str = "validation.jsonl", |
| 10 | split_ratio: float = 0.95 | 10 | split_ratio: float = 0.95, |
| 11 | balance_ratio: float = 1.0 | ||
| 11 | ): | 12 | ): |
| 12 | """ | 13 | """ |
| 13 | Reads a .jsonl file, shuffles it, and splits it into training and validation files. | 14 | Reads a .jsonl file, balances the positive/negative examples, shuffles, |
| 15 | and splits it into training and validation files. | ||
| 14 | """ | 16 | """ |
| 15 | print(f"Loading data from {input_filepath}...") | 17 | print(f"Loading data from {input_filepath}...") |
| 16 | try: | 18 | try: |
| @@ -20,23 +22,51 @@ def split_dataset( | |||
| 20 | print(f"Error: Input file not found at {input_filepath}", file=sys.stderr) | 22 | print(f"Error: Input file not found at {input_filepath}", file=sys.stderr) |
| 21 | sys.exit(1) | 23 | sys.exit(1) |
| 22 | 24 | ||
| 23 | # Shuffle the dataset to ensure random distribution | 25 | # 1. Separate into positive and negative examples |
| 24 | print("Shuffling data...") | 26 | positive_examples = [] |
| 25 | random.shuffle(lines) | 27 | negative_examples = [] |
| 28 | for line in lines: | ||
| 29 | try: | ||
| 30 | entry = json.loads(line) | ||
| 31 | if entry.get("target", "").strip(): | ||
| 32 | positive_examples.append(line) | ||
| 33 | else: | ||
| 34 | negative_examples.append(line) | ||
| 35 | except json.JSONDecodeError: | ||
| 36 | print(f"Warning: Skipping malformed JSON line: {line.strip()}", file=sys.stderr) | ||
| 26 | 37 | ||
| 27 | # Determine the split point | 38 | print(f"Found {len(positive_examples)} positive examples and {len(negative_examples)} negative examples.") |
| 28 | split_index = int(len(lines) * split_ratio) | ||
| 29 | 39 | ||
| 30 | # Split the data | 40 | # 2. Shuffle both lists independently |
| 31 | train_lines = lines[:split_index] | 41 | random.shuffle(positive_examples) |
| 32 | validation_lines = lines[split_index:] | 42 | random.shuffle(negative_examples) |
| 43 | |||
| 44 | # 3. Balance the dataset based on the ratio | ||
| 45 | num_positives = len(positive_examples) | ||
| 46 | num_negatives_to_keep = int(num_positives * balance_ratio) | ||
| 47 | |||
| 48 | if len(negative_examples) < num_negatives_to_keep: | ||
| 49 | print(f"Warning: Not enough negative examples to meet a {balance_ratio}:1 ratio. " | ||
| 50 | f"Using all {len(negative_examples)} negative examples.", file=sys.stderr) | ||
| 51 | num_negatives_to_keep = len(negative_examples) | ||
| 52 | |||
| 53 | print(f"Balancing dataset with {num_positives} positive and {num_negatives_to_keep} negative examples.") | ||
| 54 | |||
| 55 | balanced_lines = positive_examples + negative_examples[:num_negatives_to_keep] | ||
| 56 | |||
| 57 | # 4. Final shuffle to mix positive and negative examples | ||
| 58 | print("Shuffling final balanced dataset...") | ||
| 59 | random.shuffle(balanced_lines) | ||
| 60 | |||
| 61 | # 5. Determine the split point and write files | ||
| 62 | split_index = int(len(balanced_lines) * split_ratio) | ||
| 63 | train_lines = balanced_lines[:split_index] | ||
| 64 | validation_lines = balanced_lines[split_index:] | ||
| 33 | 65 | ||
| 34 | # Write the training file | ||
| 35 | print(f"Writing {len(train_lines)} lines to {train_filepath}...") | 66 | print(f"Writing {len(train_lines)} lines to {train_filepath}...") |
| 36 | with open(train_filepath, 'w', encoding='utf-8') as f: | 67 | with open(train_filepath, 'w', encoding='utf-8') as f: |
| 37 | f.writelines(train_lines) | 68 | f.writelines(train_lines) |
| 38 | 69 | ||
| 39 | # Write the validation file | ||
| 40 | print(f"Writing {len(validation_lines)} lines to {validation_filepath}...") | 70 | print(f"Writing {len(validation_lines)} lines to {validation_filepath}...") |
| 41 | with open(validation_filepath, 'w', encoding='utf-8') as f: | 71 | with open(validation_filepath, 'w', encoding='utf-8') as f: |
| 42 | f.writelines(validation_lines) | 72 | f.writelines(validation_lines) |
| @@ -44,7 +74,9 @@ def split_dataset( | |||
| 44 | print("\nSplitting complete.") | 74 | print("\nSplitting complete.") |
| 45 | 75 | ||
| 46 | if __name__ == "__main__": | 76 | if __name__ == "__main__": |
| 47 | parser = argparse.ArgumentParser(description="Split a .jsonl dataset into training and validation sets.") | 77 | parser = argparse.ArgumentParser( |
| 78 | description="Balance and split a .jsonl dataset into training and validation sets." | ||
| 79 | ) | ||
| 48 | parser.add_argument("input_file", type=str, help="Path to the input .jsonl file.") | 80 | parser.add_argument("input_file", type=str, help="Path to the input .jsonl file.") |
| 49 | parser.add_argument( | 81 | parser.add_argument( |
| 50 | "--split", | 82 | "--split", |
| @@ -52,6 +84,12 @@ if __name__ == "__main__": | |||
| 52 | default=0.95, | 84 | default=0.95, |
| 53 | help="Ratio for the training set split (e.g., 0.95 for a 95/5 split). Default is 0.95." | 85 | help="Ratio for the training set split (e.g., 0.95 for a 95/5 split). Default is 0.95." |
| 54 | ) | 86 | ) |
| 87 | parser.add_argument( | ||
| 88 | "--ratio", | ||
| 89 | type=float, | ||
| 90 | default=1.0, | ||
| 91 | help="Ratio of negative to positive examples (e.g., 1.0 for 1:1, 2.0 for 2:1). Default is 1.0." | ||
| 92 | ) | ||
| 55 | 93 | ||
| 56 | args = parser.parse_args() | 94 | args = parser.parse_args() |
| 57 | 95 | ||
| @@ -59,4 +97,4 @@ if __name__ == "__main__": | |||
| 59 | print("Error: Split ratio must be between 0 and 1.", file=sys.stderr) | 97 | print("Error: Split ratio must be between 0 and 1.", file=sys.stderr) |
| 60 | sys.exit(1) | 98 | sys.exit(1) |
| 61 | 99 | ||
| 62 | split_dataset(args.input_file, split_ratio=args.split) \ No newline at end of file | 100 | split_dataset(args.input_file, split_ratio=args.split, balance_ratio=args.ratio) \ No newline at end of file |
