Un texte signalé par un détecteur d’IA n’est pas automatiquement un texte écrit par une IA. Pour interpréter le signal, il faut comprendre les erreurs possibles et la fréquence des textes concernés dans la population examinée. C’est le rôle du taux de base.
Le calcul qui suit est une simulation pédagogique entièrement hypothétique. Aucun détecteur commercial, auteur, livre ou copie d’élève n’a été testé. Les taux de 90 % et 95 % sont choisis pour expliquer une idée ; ils ne décrivent pas les performances d’un produit réel.
Trois proportions qu’il faut distinguer
- Sensibilité : parmi les textes de la catégorie « IA » définie dans notre scénario, la proportion signalée.
- Spécificité : parmi les textes de la catégorie « humain », la proportion correctement laissée sans alerte. Son complément est le taux de faux positifs.
- Précision des alertes : parmi les textes signalés, la proportion appartenant réellement à la catégorie « IA » du scénario.
Cette dernière proportion est celle que l’on voudrait souvent connaître en lisant une alerte. Elle ne se déduit pas de la sensibilité seule. Dans la vie réelle, les catégories sont aussi moins nettes : rédaction, traduction, correction et réécriture assistées doivent être définies avant toute évaluation.
Premier scénario : vingt textes IA sur mille
Supposons 20 textes de la catégorie « IA » et 980 textes humains. Notre détecteur fictif signale 90 % des premiers et laisse correctement passer 95 % des seconds.
| Résultat fictif | Textes IA | Textes humains |
|---|---|---|
| Signalés | 18 vrais positifs | 49 faux positifs |
| Non signalés | 2 faux négatifs | 931 vrais négatifs |
Il y a donc 67 alertes : 18 + 49. Seulement 18 / 67 ≈ 26,9 % d’entre elles sont correctes. Les faux positifs dominent parce que les textes humains sont beaucoup plus nombreux : 5 % de 980 est plus grand que 90 % de 20.
Cela ne veut pas dire que le détecteur fictif s’est mis à fonctionner autrement. Nous avons appliqué exactement les taux choisis. Cela ne prouve pas non plus qu’une alerte réelle particulière serait fausse : notre simulation ne connaît ni ses données ni sa méthode.
Deuxième scénario : cinq cents textes IA sur mille
Gardons les mêmes performances hypothétiques, mais changeons la population : 500 textes IA et 500 textes humains. Nous obtenons 450 vrais positifs et 25 faux positifs. Parmi les 475 alertes, la part correcte devient 450 / 475 ≈ 94,7 %.

La formule résume ce mécanisme : précision = sensibilité × prévalence / [sensibilité × prévalence + (1 − spécificité) × (1 − prévalence)]. Elle suppose que les taux sont applicables à la population étudiée. Si la langue, la longueur ou le type de texte changent, cette hypothèse doit elle-même être vérifiée.
Un pourcentage affiché n’est pas toujours une probabilité
Il faut lire la définition du score de chaque outil. Par exemple, Turnitin décrit son pourcentage comme la part du texte admissible identifiée comme potentiellement générée ou modifiée par IA. Ce pourcentage ne correspond pas à la probabilité personnelle qu’un auteur ait triché. L’éditeur précise aussi que le résultat ne doit pas constituer l’unique fondement d’une décision défavorable à un étudiant.
Une étude de Liang et ses collègues publiée en 2023 a examiné des erreurs de détecteurs sur des textes d’anglophones natifs et non natifs. Elle concerne les outils et données de cette expérience historique ; elle ne mesure pas toutes les versions disponibles aujourd’hui. Son intérêt ici est de rappeler qu’un taux moyen ne décrit pas forcément chaque groupe de textes.
Refaire les calculs en Python
Télécharger la simulation, le tableau CSV et les cinq tests — ZIP gratuit. Les calculs utilisent des fractions pour éviter les arrondis intermédiaires sur les taux choisis. Il n’y a ni génération de textes, ni tirage aléatoire, ni appel à un service de détection. Une exécution locale du 20 octobre 2026 a produit les tableaux présentés.
Installez les dépendances du README, lancez python faux_soupcons.py, puis python test_exemple.py. Si vous choisissez d’autres taux, les valeurs calculées peuvent être des effectifs attendus fractionnaires ; elles ne représentent alors pas un décompte observé.
"""Simulation arithmétique hypothétique : aucun détecteur réel n'est interrogé."""
import csv, json
from fractions import Fraction
from pathlib import Path
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
OUT = Path(__file__).resolve().parent
def scenario(n, n_ia, sensibilite=Fraction(9, 10), specificite=Fraction(19, 20)):
if n <= 0 or not 0 <= n_ia <= n or not 0 <= sensibilite <= 1 or not 0 <= specificite <= 1:
raise ValueError("Effectifs et taux hors limites.")
vrais_positifs = n_ia * sensibilite
faux_negatifs = n_ia - vrais_positifs
faux_positifs = (n - n_ia) * (1 - specificite)
vrais_negatifs = n - n_ia - faux_positifs
alertes = vrais_positifs + faux_positifs
return {"textes": n, "textes_ia": n_ia, "vrais_positifs": float(vrais_positifs),
"faux_negatifs": float(faux_negatifs), "faux_positifs": float(faux_positifs),
"vrais_negatifs": float(vrais_negatifs), "alertes": float(alertes),
"part_vraie_parmi_alertes": float(vrais_positifs / alertes) if alertes else None}
def experience():
cas = [scenario(1000, 20), scenario(1000, 500)]
with (OUT / "scenarios_hypothetiques.csv").open("w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=list(cas[0]))
writer.writeheader()
writer.writerows(cas)
fig, ax = plt.subplots(figsize=(9, 5), layout="constrained")
ax.bar(["20 textes IA\nsur 1 000", "500 textes IA\nsur 1 000"],
[r["vrais_positifs"] for r in cas], label="Textes IA signalés", color="#167c80")
ax.bar(["20 textes IA\nsur 1 000", "500 textes IA\nsur 1 000"],
[r["faux_positifs"] for r in cas], bottom=[r["vrais_positifs"] for r in cas],
label="Textes humains signalés à tort", color="#e0a13b")
ax.set(ylabel="Nombre d’alertes", title="Hypothèse : sensibilité 90 %, spécificité 95 %")
for i, r in enumerate(cas):
ax.text(i, r["alertes"] + 12,
f'{r["part_vraie_parmi_alertes"]:.1%} d’alertes correctes', ha="center")
ax.set_ylim(0, 620)
ax.legend(loc="upper left")
fig.savefig(OUT / "figure.png", dpi=160)
plt.close(fig)
return {"hypothetique": True, "sensibilite": .9, "specificite": .95, "scenarios": cas}
if __name__ == "__main__":
resultats = experience()
(OUT / "resultats.json").write_text(json.dumps(resultats, indent=2), encoding="utf-8")
print(json.dumps(resultats, indent=2))
Comment lire une alerte de façon utile
- Identifier ce que le score mesure. Portion du texte, classe prédite et probabilité calibrée ne sont pas interchangeables.
- Vérifier le périmètre évalué. Langue, longueur, style et version de l’outil doivent correspondre au cas examiné.
- Revenir au processus de rédaction. Brouillons, sources, historique et explications de l’auteur apportent des éléments que le score ne contient pas.
- Garder une conclusion proportionnée. Une sortie incertaine peut justifier une vérification ; elle ne suffit pas à établir une provenance ou une intention.
La controverse littéraire évoquée dans notre article autour du Goncourt et de l’IA est un contexte de discussion, pas un jeu de données de ce calcul. Aucun verdict sur les personnes ou ouvrages concernés ne peut être déduit de notre exemple.
Pour comprendre une autre décision fondée sur un score, poursuivez avec le choix d’un seuil avec un budget de vérifications. Retrouvez les exemples exécutables dans les ressources Python gratuites.

