Two systematic bugs in examples/pytorch/*_no_trainer.py: broken --resume_from_checkpoint auto-discover branch, and wrong eval loss/perplexity on partial batches
Author: berkgungor
Pull request: no

### System Info

- `transformers`: `main` (as of 2026-07-16)
- Affected: **every `*_no_trainer.py` example** under `examples/pytorch/`
- No dependency-specific reproducer needed — these are pure Python control‑flow / accounting bugs.

I hit two independent, systematic bugs in the Accelerate‑based `no_trainer` examples. Both are copy‑pasted across ~15 example scripts, so filing one issue covering both. Happy to send a single PR that fixes them all.

## Bug 1 — `--resume_from_checkpoint` (no argument) is broken: "load most recent checkpoint" branch is dead code

### Where

Every `*_no_trainer.py` example, e.g.:

- [`examples/pytorch/language-modeling/run_clm_no_trainer.py#L595-L610`](https://github.com/huggingface/transformers/blob/main/examples/pytorch/language-modeling/run_clm_no_trainer.py#L595-L610)
- `run_mlm_no_trainer.py`, `run_fim_no_trainer.py`, `run_qa_no_trainer.py`, `run_qa_beam_search_no_trainer.py`, `run_translation_no_trainer.py`, `run_summarization_no_trainer.py`, `run_glue_no_trainer.py`, `run_ner_no_trainer.py`, `run_swag_no_trainer.py`, `run_image_classification_no_trainer.py`, `run_semantic_segmentation_no_trainer.py`, `run_instance_segmentation_no_trainer.py`, `run_object_detection_no_trainer.py`, `run_mim_no_trainer.py`

15 files, same code:

```python
if args.resume_from_checkpoint:
    if args.resume_from_checkpoint is not None or args.resume_from_checkpoint != "":
        checkpoint_path = args.resume_from_checkpoint
        path = os.path.basename(args.resume_from_checkpoint)
    else:
        # Get the most recent checkpoint
        dirs = [f.name for f in os.scandir(os.getcwd()) if f.is_dir()]
        dirs.sort(key=os.path.getctime)
        path = dirs[-1]
        checkpoint_path = path
        path = os.path.basename(checkpoint_path)
```

### Problem

The inner condition `args.resume_from_checkpoint is not None **or** args.resume_from_checkpoint != ""` is **always true**:

- If `args.resume_from_checkpoint is None` → left side is `False`, right side `None != ""` is `True` → overall `True`.
- If `args.resume_from_checkpoint == ""` → left side `True` → overall `True`.
- Any other string → overall `True`.

So the `else` branch (the "get the most recent checkpoint" path) is **dead code**. There is no code path in the example that can pick up the newest checkpoint automatically. It should be `and`, not `or` — this was almost certainly a typo when the branch was introduced.

Additionally, `if args.resume_from_checkpoint:` above already excludes both `None` and `""`, so passing `--resume_from_checkpoint ""` doesn't reach the `else` either. The intended UX (pass the flag with no value → auto‑discover latest) currently doesn't work anywhere.

### Repro

```bash
# Assume ./output/epoch_0/ was saved by a previous run.
python examples/pytorch/language-modeling/run_clm_no_trainer.py \
    --model_name_or_path sshleifer/tiny-gpt2 \
    --dataset_name wikitext --dataset_config_name wikitext-2-raw-v1 \
    --output_dir ./output \
    --resume_from_checkpoint ""     # or omit the value from a shell wrapper
```

The `if args.resume_from_checkpoint:` guard treats `""` as falsy and the block is skipped entirely — the "auto‑discover" flow can never fire.

### Suggested fix

```python
if args.resume_from_checkpoint is not None and args.resume_from_checkpoint != "":
    checkpoint_path = args.resume_from_checkpoint
    path = os.path.basename(args.resume_from_checkpoint)
else:
    # Get the most recent checkpoint
    dirs = [f.name for f in os.scandir(os.getcwd()) if f.is_dir()]
    dirs.sort(key=os.path.getctime)
    path = dirs[-1]
    checkpoint_path = path
    path = os.path.basename(checkpoint_path)
```

…and probably rework the outer `if args.resume_from_checkpoint:` to also accept a sentinel (e.g. `"latest"`) so the auto‑discover path is actually reachable. Two options — happy to defer to maintainer preference.

---

## Bug 2 — Perplexity / eval loss is silently wrong on the last (partial) eval batch

### Where

At least three files (identical line):

- [`examples/pytorch/language-modeling/run_clm_no_trainer.py#L668`](https://github.com/huggingface/transformers/blob/main/examples/pytorch/language-modeling/run_clm_no_trainer.py#L668)
- [`examples/pytorch/language-modeling/run_mlm_no_trainer.py#L698`](https://github.com/huggingface/transformers/blob/main/examples/pytorch/language-modeling/run_mlm_no_trainer.py#L698)
- [`examples/pytorch/language-modeling/run_fim_no_trainer.py#L858`](https://github.com/huggingface/transformers/blob/main/examples/pytorch/language-modeling/run_fim_no_trainer.py#L858)

```python
losses.append(accelerator.gather_for_metrics(loss.repeat(args.per_device_eval_batch_size)))
```

### Problem

`loss.repeat(args.per_device_eval_batch_size)` uses the **configured** eval batch size, not the size of the actual batch. On the last eval batch this is almost always wrong:

- With `drop_last=False` (the default here) the last batch is a **partial** batch. The tensor of "losses" for that batch is padded to `per_device_eval_batch_size` copies of the same scalar loss instead of being sized to the real number of examples.
- Then `gather_for_metrics` sees a fixed size on every rank and cannot correctly drop the trailing padding, so those repeated copies of the last mean loss get **over‑counted** in the final `torch.mean(losses)` and `math.exp(eval_loss)`.

Net effect: reported **perplexity and eval loss are biased** whenever the eval dataset size is not divisible by `world_size × per_device_eval_batch_size`. The bias is small on huge eval sets and dominant on small ones (a common case for unit tests and CI).
---


Comments:
This PR implements the fixes described in #47375. The issue specifically identifies the examples/pytorch/*_no_trainer.py scripts as the affected files. The current security gate appears to reject changes under examples/; please let me know if there's an alternative submission process or if the workflows can be approved for this PR.