gr8monk3ys commited on
Commit
86dec80
·
verified ·
1 Parent(s): 392040f

Sync card and scripts from the monorepo

Browse files
Files changed (4) hide show
  1. README.md +31 -21
  2. data_generator.py +2 -17
  3. requirements.txt +7 -8
  4. train.py +2 -2
README.md CHANGED
@@ -11,16 +11,10 @@ metrics:
11
  - accuracy
12
  - f1
13
  pipeline_tag: text-classification
 
 
14
  language:
15
  - en
16
- library_name: transformers
17
- widget:
18
- - text: "B.S. in Computer Science, Stanford University, 2021. GPA: 3.9. Relevant coursework: Machine Learning, Distributed Systems."
19
- example_title: Education
20
- - text: "Senior Software Engineer at Stripe, 2019-Present. Led migration of payment infrastructure to Kubernetes, reducing deploy times by 60%."
21
- example_title: Experience
22
- - text: "Python, TypeScript, React, PostgreSQL, Docker, AWS, Terraform"
23
- example_title: Skills
24
  ---
25
 
26
  # Resume Section Classifier
@@ -76,23 +70,39 @@ Default configuration produces **1,920 examples** (80 base examples x 3 variants
76
 
77
  ## Metrics
78
 
79
- Evaluated on the held-out synthetic test set (192 examples, stratified, seed 42; run of 2026-07-12 on transformers 5.13):
80
 
81
- | Metric | Score |
82
- |--------|-------|
 
 
 
83
  | Accuracy | 1.000 |
84
  | F1 (macro) | 1.000 |
85
  | F1 (weighted) | 1.000 |
86
- | Test loss | 0.195 |
87
-
88
- > **Read these numbers with care.** The test split is drawn from the same
89
- > template-based generator as the training data, so perfect scores mainly
90
- > reflect that the synthetic distribution is easy to separate not
91
- > real-world performance. On a small spot-check of hand-written,
92
- > out-of-distribution snippets the model resolved 3/5 correctly, with
93
- > misclassifications skewing toward `summary` at low confidence. Expect
94
- > materially lower accuracy on real resumes; fine-tune on labeled
95
- > real-world sections for production use.
 
 
 
 
 
 
 
 
 
 
 
 
 
96
 
97
  ## Usage
98
 
 
11
  - accuracy
12
  - f1
13
  pipeline_tag: text-classification
14
+ datasets:
15
+ - custom-synthetic
16
  language:
17
  - en
 
 
 
 
 
 
 
 
18
  ---
19
 
20
  # Resume Section Classifier
 
70
 
71
  ## Metrics
72
 
73
+ > **These figures are INDICATIVE only.** They are measured on a held-out split of the model's own **synthetic, self-generated** data (192 examples, stratified) not a real-world benchmark. Because the train and test sets are produced by the same template-based generator, they share vocabulary and structure, so these scores **overstate** how the model will perform on real resumes.
74
 
75
+ Measured on the published checkpoint (4 epochs, seed 42, 192-example
76
+ stratified synthetic test split):
77
+
78
+ | Metric | Score (synthetic test set) |
79
+ |--------|----------------------------|
80
  | Accuracy | 1.000 |
81
  | F1 (macro) | 1.000 |
82
  | F1 (weighted) | 1.000 |
83
+ | Precision (weighted) | 1.000 |
84
+ | Recall (weighted) | 1.000 |
85
+ | Eval loss | 0.195 |
86
+
87
+ A perfect score here is evidence of the leak described above, not of quality:
88
+ the test split is generated by the same templates as the training split.
89
+
90
+ ### Out-of-distribution spot-check
91
+
92
+ To give the synthetic score some context, the checkpoint was run against eight
93
+ hand-written snippets in the style of real resumes, one per section type, none
94
+ drawn from the generator:
95
+
96
+ | Result | Count |
97
+ |--------|-------|
98
+ | Correct | 6 / 8 |
99
+
100
+ Both misses were low-confidence and collapsed toward the broader categories —
101
+ an `experience` bullet read as `summary` (0.39), and a `projects` bullet read
102
+ as `skills` (0.48). Treat **~0.75 on real text** as the more realistic
103
+ expectation, and treat predictions under ~0.5 confidence as unreliable.
104
+
105
+ > Note: exact metrics depend on the random seed and training run.
106
 
107
  ## Usage
108
 
data_generator.py CHANGED
@@ -10,9 +10,7 @@ Author: Lorenzo Scaturchio (gr8monk3ys)
10
 
11
  import csv
12
  import random
13
- import itertools
14
  from pathlib import Path
15
- from typing import Optional
16
 
17
  # ---------------------------------------------------------------------------
18
  # Entity pools – used to fill templates with realistic variation
@@ -854,33 +852,20 @@ def save_to_csv(dataset: list[dict], path: str) -> None:
854
 
855
  def load_as_hf_dataset(dataset: list[dict]):
856
  """Convert to HuggingFace Dataset with train/val/test splits."""
857
- from datasets import ClassLabel, Dataset, DatasetDict, Features, Value
858
 
859
  ds = Dataset.from_list(dataset)
860
 
861
- # Stratified splitting requires a ClassLabel column
862
- class_label = ClassLabel(names=sorted(set(d["label"] for d in dataset)))
863
- ds = ds.cast_column("label", class_label)
864
-
865
  # 80/10/10 split
866
  train_test = ds.train_test_split(test_size=0.2, seed=42, stratify_by_column="label")
867
  val_test = train_test["test"].train_test_split(test_size=0.5, seed=42, stratify_by_column="label")
868
 
869
- splits = DatasetDict({
870
  "train": train_test["train"],
871
  "validation": val_test["train"],
872
  "test": val_test["test"],
873
  })
874
 
875
- # Downstream tokenization maps label names via label2id, so restore strings.
876
- # Explicit output features are required: mapping into a ClassLabel column
877
- # would silently re-encode the names back to ints.
878
- return splits.map(
879
- lambda batch: {"label": class_label.int2str(batch["label"])},
880
- batched=True,
881
- features=Features({"text": Value("string"), "label": Value("string")}),
882
- )
883
-
884
 
885
  def get_label_mapping(dataset: list[dict]) -> tuple[dict, dict]:
886
  """Create label <-> id mappings."""
 
10
 
11
  import csv
12
  import random
 
13
  from pathlib import Path
 
14
 
15
  # ---------------------------------------------------------------------------
16
  # Entity pools – used to fill templates with realistic variation
 
852
 
853
  def load_as_hf_dataset(dataset: list[dict]):
854
  """Convert to HuggingFace Dataset with train/val/test splits."""
855
+ from datasets import Dataset, DatasetDict
856
 
857
  ds = Dataset.from_list(dataset)
858
 
 
 
 
 
859
  # 80/10/10 split
860
  train_test = ds.train_test_split(test_size=0.2, seed=42, stratify_by_column="label")
861
  val_test = train_test["test"].train_test_split(test_size=0.5, seed=42, stratify_by_column="label")
862
 
863
+ return DatasetDict({
864
  "train": train_test["train"],
865
  "validation": val_test["train"],
866
  "test": val_test["test"],
867
  })
868
 
 
 
 
 
 
 
 
 
 
869
 
870
  def get_label_mapping(dataset: list[dict]) -> tuple[dict, dict]:
871
  """Create label <-> id mappings."""
requirements.txt CHANGED
@@ -1,8 +1,7 @@
1
- transformers>=4.36.0
2
- datasets>=2.16.0
3
- torch>=2.1.0
4
- scikit-learn>=1.3.0
5
- accelerate>=0.25.0
6
- evaluate>=0.4.0
7
- pandas>=2.0.0
8
- huggingface_hub>=0.20.0
 
1
+ transformers>=4.36.0,<5.0.0
2
+ datasets>=2.16.0,<4.0.0
3
+ torch>=2.1.0,<3.0.0
4
+ scikit-learn>=1.3.0,<2.0.0
5
+ accelerate>=0.25.0,<2.0.0
6
+ evaluate>=0.4.0,<1.0.0
7
+ huggingface_hub>=0.20.0,<1.0.0
 
train.py CHANGED
@@ -16,7 +16,6 @@ Usage:
16
 
17
  import json
18
  import logging
19
- import os
20
  import sys
21
  from pathlib import Path
22
 
@@ -219,6 +218,7 @@ def train(
219
 
220
  training_args = TrainingArguments(
221
  output_dir=output_dir,
 
222
  # Training hyperparameters
223
  num_train_epochs=epochs,
224
  per_device_train_batch_size=batch_size,
@@ -261,7 +261,7 @@ def train(
261
  args=training_args,
262
  train_dataset=tokenized_dataset["train"],
263
  eval_dataset=tokenized_dataset["validation"],
264
- processing_class=tokenizer,
265
  data_collator=data_collator,
266
  compute_metrics=build_compute_metrics(id2label),
267
  callbacks=callbacks,
 
16
 
17
  import json
18
  import logging
 
19
  import sys
20
  from pathlib import Path
21
 
 
218
 
219
  training_args = TrainingArguments(
220
  output_dir=output_dir,
221
+ overwrite_output_dir=True,
222
  # Training hyperparameters
223
  num_train_epochs=epochs,
224
  per_device_train_batch_size=batch_size,
 
261
  args=training_args,
262
  train_dataset=tokenized_dataset["train"],
263
  eval_dataset=tokenized_dataset["validation"],
264
+ tokenizer=tokenizer,
265
  data_collator=data_collator,
266
  compute_metrics=build_compute_metrics(id2label),
267
  callbacks=callbacks,