Downloads · 30 days
82
59% of all-time downloads
AyoubChLin/distilbert-hc3-human-vs-ai
distilbert-hc3-human-vs-ai is a text classification model from AyoubChLin. Use it when you need a label for a piece of text. It is set up for transformers. The card lists the license as cc-by-sa-4.0.
This is a fully fine-tuned DistilBERT binary sequence classifier for distinguishing human-written answers from AI-generated answers. It was trained on the English all configuration of Hello-SimpleAI/HC3, using answer…
Downloads · 30 days
82
59% of all-time downloads
All-time downloads
138
Public
Parameters
67M
268 MB on disk
Likes
0
Public
Click a slice to open those files.
.safetensors268 MB · 100%
From the Hugging Face model README
This is a fully fine-tuned DistilBERT binary sequence classifier for distinguishing human-written answers from AI-generated answers. It was trained on the English all configuration of Hello-SimpleAI/HC3, using answer text only.
The data pipeline isolates the original HC3 questions across train, validation, and test splits before balancing. Consequently, answers derived from the same question cannot appear in more than one split.
Important: this model measures similarity to the human and early-ChatGPT writing patterns represented in HC3. Its output is a model score—not proof of authorship. Do not use it alone for grading, discipline, hiring, moderation, or accusations of AI use.
| Item | Value |
|---|---|
| Model | AyoubChLin/distilbert-hc3-human-vs-ai |
| Base model | distilbert/distilbert-base-uncased |
| Architecture | DistilBertForSequenceClassification |
| Language | English |
| Task | Binary text classification |
| Input | A standalone passage of text |
| Maximum input length | 512 tokens; longer inputs are truncated |
| Trainable parameters | 66,955,010 |
| Fine-tuning method | Full fine-tuning; not LoRA/PEFT |
| Output labels | HUMAN, AI_GENERATED |
| Training dataset | Hello-SimpleAI/HC3, configuration all |
| Framework | PyTorch + Hugging Face Transformers |
| License | CC BY-SA 4.0 |
| ID | Label | Meaning |
|---|---|---|
| 0 | HUMAN | Text resembles the human-answer class in HC3 |
| 1 | AI_GENERATED | Text resembles the early-ChatGPT-answer class in HC3 |
The final model was evaluated once on a balanced, question-group-isolated test set containing 5,306 examples: 2,653 human answers and 2,653 AI-generated answers.
| Metric | Score |
|---|---|
| Test loss | 0.017504 |
| Accuracy | 0.993592 |
Precision — AI_GENERATED | 0.989533 |
Recall — AI_GENERATED | 0.997738 |
F1 — AI_GENERATED | 0.993619 |
| ROC AUC | 0.999862 |
| Class | Precision | Recall | F1 | Support |
|---|---|---|---|---|
HUMAN | 0.9977 | 0.9894 | 0.9936 | 2,653 |
AI_GENERATED | 0.9895 | 0.9977 | 0.9936 | 2,653 |
| Macro average | 0.9936 | 0.9936 | 0.9936 | 5,306 |
| Weighted average | 0.9936 | 0.9936 | 0.9936 | 5,306 |
Rows are true labels; columns are predicted labels.
Predicted HUMAN | Predicted AI_GENERATED | |
|---|---|---|
True HUMAN | 2,625 | 28 |
True AI_GENERATED | 6 | 2,647 |
These results describe the held-out HC3 split only. They must not be interpreted as expected performance on newer language models, edited text, other languages, or unrelated domains.
The following cells load the published checkpoint, run single/batch inference, return both class probabilities, and perform a small smoke test.
%pip install -q "transformers==4.57.1" "accelerate>=1.2,<2"
If the notebook runtime asks for a restart after installation, restart it once before continuing.
import torch
from transformers import AutoModelForSequenceClassification, AutoTokenizer
MODEL_ID = "AyoubChLin/distilbert-hc3-human-vs-ai"
MAX_LENGTH = 512
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
tokenizer = AutoTokenizer.from_pretrained(MODEL_ID, use_fast=True)
model = AutoModelForSequenceClassification.from_pretrained(MODEL_ID)
model.to(device)
model.eval()
print(f"Loaded {MODEL_ID} on {device}")
print("Label mapping:", model.config.id2label)
def predict_texts(texts, batch_size=16, ai_threshold=0.50):
"""Classify one string or a list of strings.
`ai_threshold` applies to the AI_GENERATED score. The default 0.50
threshold is suitable for a basic demo; recalibrate it on representative
in-domain validation data before deploying the model.
"""
if isinstance(texts, str):
texts = [texts]
if not isinstance(texts, list) or not texts:
raise ValueError("texts must be a non-empty string or list of strings")
if not all(isinstance(text, str) and text.strip() for text in texts):
raise ValueError("every input must be a non-empty string")
if not 0.0 <= ai_threshold <= 1.0:
raise ValueError("ai_threshold must be between 0 and 1")
ai_id = int(model.config.label2id.get("AI_GENERATED", 1))
human_id = int(model.config.label2id.get("HUMAN", 0))
results = []
for start in range(0, len(texts), batch_size):
batch = texts[start : start + batch_size]
inputs = tokenizer(
batch,
padding=True,
truncation=True,
max_length=MAX_LENGTH,
return_tensors="pt",
).to(device)
with torch.inference_mode():
probabilities = model(**inputs).logits.softmax(dim=-1).cpu()
for text, probs in zip(batch, probabilities):
human_score = float(probs[human_id])
ai_score = float(probs[ai_id])
prediction = "AI_GENERATED" if ai_score >= ai_threshold else "HUMAN"
results.append({
"text": text,
"prediction": prediction,
"confidence": max(human_score, ai_score),
"human_probability": human_score,
"ai_probability": ai_score,
"truncated_to_max_length": len(
tokenizer(text, add_special_tokens=True)["input_ids"]
) > MAX_LENGTH,
})
return results
result = predict_texts(
"I tried the recipe yesterday. It was a little too salty, "
"but my family still finished everything."
)[0]
print(f"Prediction: {result['prediction']}")
print(f"Confidence: {result['confidence']:.4f}")
print(f"Human score: {result['human_probability']:.4f}")
print(f"AI score: {result['ai_probability']:.4f}")
print(f"Input truncated: {result['truncated_to_max_length']}")
samples = [
"I missed the bus this morning, so I walked to work in the rain.",
"Machine learning is a field of study that enables systems to learn patterns from data and make predictions.",
"The first version failed twice. I changed the parser, reran it, and finally got the output I expected.",
]
results = predict_texts(samples, batch_size=8)
assert len(results) == len(samples)
for item in results:
assert item["prediction"] in {"HUMAN", "AI_GENERATED"}
assert 0.0 <= item["confidence"] <= 1.0
assert abs(
item["human_probability"] + item["ai_probability"] - 1.0
) < 1e-5
print("-" * 80)
print(f"Prediction: {item['prediction']} | confidence={item['confidence']:.4f}")
print(f"HUMAN={item['human_probability']:.4f} | AI_GENERATED={item['ai_probability']:.4f}")
print(item["text"])
print("\nSmoke test passed.")
The sample labels are intentionally not asserted: an inference smoke test should verify that the checkpoint loads and returns valid probabilities, not treat a few hand-written sentences as ground truth.
from transformers import pipeline
classifier = pipeline(
task="text-classification",
model=MODEL_ID,
tokenizer=MODEL_ID,
device=0 if torch.cuda.is_available() else -1,
)
classifier(
"Paste the passage you want to inspect here.",
truncation=True,
max_length=512,
)
HC3 contains questions paired with lists of human answers and answers generated by an early ChatGPT system. The all configuration combines five English sources:
financemedicineopen_qareddit_eli5wiki_csaiThe preparation pipeline used the following procedure:
group_id.HUMAN and AI_GENERATED independently inside each split.There were 79,325 usable unique answers before per-split balancing.
| Split | Total examples | HUMAN | AI_GENERATED | Represented question groups |
|---|---|---|---|---|
| Train | 41,924 | 20,962 | 20,962 | 18,983 |
| Validation | 5,256 | 2,628 | 2,628 | 2,373 |
| Test | 5,306 | 2,653 | 2,653 | 2,379 |
The classification head was initialized for the downstream binary task, and all model parameters were updated.
| Hyperparameter | Run value |
|---|---|
| Maximum sequence length | 512 |
| Epoch limit | 5 |
| Epoch reached | 3.0 |
| Learning rate | 2e-5 |
| Per-device train batch size | 128 |
| Per-device evaluation batch size | 256 |
| Gradient accumulation steps | 1 |
| Effective train batch size | 128 |
| Weight decay | 0.01 |
| Warmup ratio | 0.10 |
| Padding | Dynamic, to a multiple of 8 |
| Evaluation strategy | Every epoch |
| Checkpoint strategy | Every epoch |
| Best-model metric | Validation F1, higher is better |
| Load best model at end | Yes |
| Early-stopping patience | 2 evaluation rounds |
| Maximum retained checkpoints | 2 |
| Logging interval | 50 steps |
| Random/data seed | 42 |
| Precision | BF16 |
| Training hardware | One NVIDIA A100-SXM4 80 GB |
| Transformers version | 4.57.1 |
| Experiment tracking | Disabled |
The configuration selected batch sizes from available GPU memory:
| Detected VRAM | Train batch | Evaluation batch |
|---|---|---|
| At least 70 GiB | 128 | 256 |
| At least 35 GiB | 64 | 128 |
| Less than 35 GiB / fallback | 16 | 32 |
| Statistic | Value |
|---|---|
| Training runtime | 233.6299 seconds |
| Samples/second | 897.231 |
| Steps/second | 7.020 |
| Training loss | 0.061305 |
| Total FLOPs | 1.655368e16 |
The notebook requested up to five epochs and reached epoch 3.0 with early stopping enabled. The final exported checkpoint was loaded from the best validation-F1 checkpoint.
This model is suitable for:
It is not suitable as a standalone authorship verifier or as the sole basis for consequential decisions.
For deployment, collect recent human and AI examples from the target domain, preserve author/source groups across splits, evaluate subgroup error rates, calibrate the threshold, and monitor drift and false positives continuously.
AI-text detectors can incorrectly accuse people, and stylistic differences may produce uneven error rates across writers, language backgrounds, accessibility needs, and levels of writing experience. Predictions should be treated as weak supporting signals and reviewed alongside transparent, independent evidence. Users should have a meaningful way to contest any consequential decision.
42MAX_SAMPLES_PER_CLASS = NoneAI_GENERATED, plus accuracy and ROC AUCIf you use this checkpoint, cite the HC3 dataset and the DistilBERT work in addition to referencing this model repository.
@inproceedings{guo2023hc3,
title = {How Close is ChatGPT to Human Experts? Comparison Corpus, Evaluation, and Detection},
author = {Guo, Biyang and Zhang, Xin and Wang, Ziyuan and Jiang, Minqi and Nie, Jinran and Ding, Yuxuan and Yue, Jianwei and Wu, Yupeng},
booktitle = {Proceedings of the 61st Annual Meeting of the Association for Computational Linguistics (Volume 1: Long Papers)},
year = {2023}
}
@inproceedings{sanh2019distilbert,
title = {DistilBERT, a distilled version of BERT: smaller, faster, cheaper and lighter},
author = {Sanh, Victor and Debut, Lysandre and Chaumond, Julien and Wolf, Thomas},
booktitle = {NeurIPS EMC2 Workshop},
year = {2019}
}
This model repository is released under CC BY-SA 4.0. Users are responsible for complying with the licenses and terms of the base model and HC3 dataset.