Upload train.py with huggingface_hub
Browse files
train.py
CHANGED
|
@@ -173,7 +173,7 @@ def parse_args() -> argparse.Namespace:
|
|
| 173 |
parser.add_argument(
|
| 174 |
"--hub_model_id",
|
| 175 |
type=str,
|
| 176 |
-
default="gr8monk3ys/paper-classifier
|
| 177 |
help="Repository id on the HuggingFace Hub (default: %(default)s).",
|
| 178 |
)
|
| 179 |
|
|
@@ -189,18 +189,19 @@ def build_label_mappings(label_names: list[str]) -> tuple[dict, dict]:
|
|
| 189 |
|
| 190 |
def load_and_prepare_dataset(
|
| 191 |
dataset_name: str,
|
| 192 |
-
|
| 193 |
max_train_samples: int | None = None,
|
| 194 |
max_eval_samples: int | None = None,
|
| 195 |
-
) -> DatasetDict:
|
| 196 |
"""Load the dataset and normalise the label column.
|
| 197 |
|
| 198 |
The function handles two common dataset layouts:
|
| 199 |
-
1. The dataset already has
|
| 200 |
-
|
| 201 |
-
2. The dataset has a string ``label`` column
|
|
|
|
| 202 |
|
| 203 |
-
Returns
|
| 204 |
"""
|
| 205 |
logger.info("Loading dataset: %s", dataset_name)
|
| 206 |
raw = load_dataset(dataset_name, trust_remote_code=True)
|
|
@@ -226,6 +227,17 @@ def load_and_prepare_dataset(
|
|
| 226 |
label_col = sample_columns[-1]
|
| 227 |
logger.info("Using label column: '%s'", label_col)
|
| 228 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 229 |
# Rename columns so downstream code can rely on 'text' and 'label' ---
|
| 230 |
def _rename(example):
|
| 231 |
return {"text": str(example[text_col]), "label": example[label_col]}
|
|
@@ -249,9 +261,7 @@ def load_and_prepare_dataset(
|
|
| 249 |
raw = raw.filter(lambda ex: ex["label"] != -1)
|
| 250 |
|
| 251 |
# Ensure we have a ClassLabel feature --------------------------------
|
| 252 |
-
label_feature = ClassLabel(
|
| 253 |
-
num_classes=len(label2id), names=list(label2id.keys())
|
| 254 |
-
)
|
| 255 |
raw = raw.cast_column("label", label_feature)
|
| 256 |
|
| 257 |
# Build train / validation splits ------------------------------------
|
|
@@ -274,7 +284,7 @@ def load_and_prepare_dataset(
|
|
| 274 |
len(raw["train"]),
|
| 275 |
len(raw["validation"]),
|
| 276 |
)
|
| 277 |
-
return raw
|
| 278 |
|
| 279 |
|
| 280 |
def tokenize_dataset(
|
|
@@ -348,19 +358,19 @@ def main() -> None:
|
|
| 348 |
device = "cuda" if torch.cuda.is_available() else ("mps" if torch.backends.mps.is_available() else "cpu")
|
| 349 |
logger.info("Using device: %s", device)
|
| 350 |
|
| 351 |
-
#
|
| 352 |
-
|
| 353 |
-
num_labels = len(LABEL_NAMES)
|
| 354 |
-
logger.info("Number of labels: %d", num_labels)
|
| 355 |
-
|
| 356 |
-
# Dataset
|
| 357 |
-
dataset = load_and_prepare_dataset(
|
| 358 |
dataset_name=args.dataset_name,
|
| 359 |
-
|
| 360 |
max_train_samples=args.max_train_samples,
|
| 361 |
max_eval_samples=args.max_eval_samples,
|
| 362 |
)
|
| 363 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 364 |
# Tokenizer
|
| 365 |
logger.info("Loading tokenizer: %s", MODEL_NAME)
|
| 366 |
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
|
|
@@ -405,7 +415,7 @@ def main() -> None:
|
|
| 405 |
args=training_args,
|
| 406 |
train_dataset=tokenized_dataset["train"],
|
| 407 |
eval_dataset=tokenized_dataset["validation"],
|
| 408 |
-
|
| 409 |
compute_metrics=build_compute_metrics_fn(),
|
| 410 |
callbacks=[
|
| 411 |
EarlyStoppingCallback(early_stopping_patience=args.early_stopping_patience),
|
|
|
|
| 173 |
parser.add_argument(
|
| 174 |
"--hub_model_id",
|
| 175 |
type=str,
|
| 176 |
+
default="gr8monk3ys/paper-classifier",
|
| 177 |
help="Repository id on the HuggingFace Hub (default: %(default)s).",
|
| 178 |
)
|
| 179 |
|
|
|
|
| 189 |
|
| 190 |
def load_and_prepare_dataset(
|
| 191 |
dataset_name: str,
|
| 192 |
+
fallback_label_names: list[str],
|
| 193 |
max_train_samples: int | None = None,
|
| 194 |
max_eval_samples: int | None = None,
|
| 195 |
+
) -> tuple[DatasetDict, list[str]]:
|
| 196 |
"""Load the dataset and normalise the label column.
|
| 197 |
|
| 198 |
The function handles two common dataset layouts:
|
| 199 |
+
1. The dataset already has a ``ClassLabel`` label column — its own
|
| 200 |
+
class names are authoritative and are returned as-is.
|
| 201 |
+
2. The dataset has a string ``label`` column, which is mapped via
|
| 202 |
+
``fallback_label_names``.
|
| 203 |
|
| 204 |
+
Returns ``(DatasetDict with train/validation splits, label_names)``.
|
| 205 |
"""
|
| 206 |
logger.info("Loading dataset: %s", dataset_name)
|
| 207 |
raw = load_dataset(dataset_name, trust_remote_code=True)
|
|
|
|
| 227 |
label_col = sample_columns[-1]
|
| 228 |
logger.info("Using label column: '%s'", label_col)
|
| 229 |
|
| 230 |
+
# Prefer the dataset's own class names over any hardcoded list — a
|
| 231 |
+
# mismatched hardcoded list makes the ClassLabel cast below explode.
|
| 232 |
+
orig_label_feature = next(iter(raw.values())).features[label_col]
|
| 233 |
+
if isinstance(orig_label_feature, ClassLabel):
|
| 234 |
+
label_names = list(orig_label_feature.names)
|
| 235 |
+
logger.info("Using dataset's ClassLabel names (%d classes).", len(label_names))
|
| 236 |
+
else:
|
| 237 |
+
label_names = list(fallback_label_names)
|
| 238 |
+
logger.info("Dataset has no ClassLabel; using fallback names (%d).", len(label_names))
|
| 239 |
+
label2id = {label: idx for idx, label in enumerate(label_names)}
|
| 240 |
+
|
| 241 |
# Rename columns so downstream code can rely on 'text' and 'label' ---
|
| 242 |
def _rename(example):
|
| 243 |
return {"text": str(example[text_col]), "label": example[label_col]}
|
|
|
|
| 261 |
raw = raw.filter(lambda ex: ex["label"] != -1)
|
| 262 |
|
| 263 |
# Ensure we have a ClassLabel feature --------------------------------
|
| 264 |
+
label_feature = ClassLabel(num_classes=len(label_names), names=label_names)
|
|
|
|
|
|
|
| 265 |
raw = raw.cast_column("label", label_feature)
|
| 266 |
|
| 267 |
# Build train / validation splits ------------------------------------
|
|
|
|
| 284 |
len(raw["train"]),
|
| 285 |
len(raw["validation"]),
|
| 286 |
)
|
| 287 |
+
return raw, label_names
|
| 288 |
|
| 289 |
|
| 290 |
def tokenize_dataset(
|
|
|
|
| 358 |
device = "cuda" if torch.cuda.is_available() else ("mps" if torch.backends.mps.is_available() else "cpu")
|
| 359 |
logger.info("Using device: %s", device)
|
| 360 |
|
| 361 |
+
# Dataset (label names come from the dataset itself when available)
|
| 362 |
+
dataset, label_names = load_and_prepare_dataset(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 363 |
dataset_name=args.dataset_name,
|
| 364 |
+
fallback_label_names=LABEL_NAMES,
|
| 365 |
max_train_samples=args.max_train_samples,
|
| 366 |
max_eval_samples=args.max_eval_samples,
|
| 367 |
)
|
| 368 |
|
| 369 |
+
# Label mappings
|
| 370 |
+
label2id, id2label = build_label_mappings(label_names)
|
| 371 |
+
num_labels = len(label_names)
|
| 372 |
+
logger.info("Number of labels: %d", num_labels)
|
| 373 |
+
|
| 374 |
# Tokenizer
|
| 375 |
logger.info("Loading tokenizer: %s", MODEL_NAME)
|
| 376 |
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
|
|
|
|
| 415 |
args=training_args,
|
| 416 |
train_dataset=tokenized_dataset["train"],
|
| 417 |
eval_dataset=tokenized_dataset["validation"],
|
| 418 |
+
processing_class=tokenizer,
|
| 419 |
compute_metrics=build_compute_metrics_fn(),
|
| 420 |
callbacks=[
|
| 421 |
EarlyStoppingCallback(early_stopping_patience=args.early_stopping_patience),
|