CoolFace
Modelpublic

faodl/agri-wheat-classifier

sourceHugging Faceupdated 4mo agoView on Hugging Face
0likes
Model Card

AMIS Commodity Classifier

This model repository contains artifacts from an AMIS commodity relevance classifier training run. It includes the Transformer model, any configured TF-IDF or sentence-embedding baselines, prediction files, and the training report.

  • —Dataset: faodl/amis-agri-wheat
  • —Dataset subset: ``
  • —Dataset revision: main
  • —Text column: chunk_text
  • —Label column: label
  • —Transformer: FacebookAI/xlm-roberta-base
  • —Generated at: 2026-05-29T18:13:08.384805+00:00

Dataset Summary

SplitRowsLabel 0Label 1Unique groupsMean text length
train3622216314591850644.8
validation759486273396636.7
test762470292397643.3

Threshold Comparison on Validation Split

Validation metrics document threshold selection and tuning behavior; test metrics remain the primary estimate of out-of-sample performance.

ModelThresholdAccuracyPrecisionRecallF1ROC AUCAverage precision
logistic_tfidf0.5000.8180.7180.8130.7630.9070.867
logistic_tfidf0.4700.8230.7090.8640.7790.9070.867
xgboost_tfidf0.5000.8680.8080.8320.8190.9350.892
xgboost_tfidf0.5200.8710.8160.8280.8220.9350.892
embedding-logisticsentenceembeddings0.5000.7830.6580.8240.7320.8620.780
embedding-logisticsentenceembeddings0.5210.7910.6730.8130.7360.8620.780
embedding-svmsentenceembeddings0.5000.8040.7140.7580.7350.8690.792
embedding-svmsentenceembeddings0.4730.8050.7040.7910.7450.8690.792
embedding-lightgbmsentenceembeddings0.5000.7910.6940.7470.7200.8680.786
embedding-lightgbmsentenceembeddings0.4330.8000.6930.7950.7410.8680.786
transformer0.5000.9250.8940.8970.8960.9560.914
transformer0.2030.9260.8830.9160.8990.9560.914

Threshold Comparison on Test Split

ModelThresholdAccuracyPrecisionRecallF1ROC AUCAverage precision
logistic_tfidf0.5000.8030.7150.8080.7590.8880.827
logistic_tfidf0.4700.7970.6880.8600.7640.8880.827
xgboost_tfidf0.5000.8350.7730.8050.7890.9100.831
xgboost_tfidf0.5200.8350.7770.7980.7870.9100.831
embedding-logisticsentenceembeddings0.5000.7820.6990.7570.7270.8770.821
embedding-logisticsentenceembeddings0.5210.7890.7130.7500.7310.8770.821
embedding-svmsentenceembeddings0.5000.8180.7780.7330.7550.8830.824
embedding-svmsentenceembeddings0.4730.8120.7580.7500.7540.8830.824
embedding-lightgbmsentenceembeddings0.5000.7980.7400.7290.7340.8920.847
embedding-lightgbmsentenceembeddings0.4330.8060.7350.7710.7530.8920.847
transformer0.5000.8850.8620.8320.8470.9430.915
transformer0.2030.8900.8540.8600.8570.9430.915

Confusion Matrices on Test Split

Rows are true labels and columns are predicted labels.

logistic_tfidf at threshold 0.500

True / PredictedNOT_RELEVANTRELEVANT
NOT_RELEVANT37694
RELEVANT56236

logistic_tfidf at threshold 0.470

True / PredictedNOT_RELEVANTRELEVANT
NOT_RELEVANT356114
RELEVANT41251

xgboost_tfidf at threshold 0.500

True / PredictedNOT_RELEVANTRELEVANT
NOT_RELEVANT40169
RELEVANT57235

xgboost_tfidf at threshold 0.520

True / PredictedNOT_RELEVANTRELEVANT
NOT_RELEVANT40367
RELEVANT59233

embedding-logisticsentenceembeddings at threshold 0.500

True / PredictedNOT_RELEVANTRELEVANT
NOT_RELEVANT37595
RELEVANT71221

embedding-logisticsentenceembeddings at threshold 0.521

True / PredictedNOT_RELEVANTRELEVANT
NOT_RELEVANT38288
RELEVANT73219

embedding-svmsentenceembeddings at threshold 0.500

True / PredictedNOT_RELEVANTRELEVANT
NOT_RELEVANT40961
RELEVANT78214

embedding-svmsentenceembeddings at threshold 0.473

True / PredictedNOT_RELEVANTRELEVANT
NOT_RELEVANT40070
RELEVANT73219

embedding-lightgbmsentenceembeddings at threshold 0.500

True / PredictedNOT_RELEVANTRELEVANT
NOT_RELEVANT39575
RELEVANT79213

embedding-lightgbmsentenceembeddings at threshold 0.433

True / PredictedNOT_RELEVANTRELEVANT
NOT_RELEVANT38981
RELEVANT67225

transformer at threshold 0.500

True / PredictedNOT_RELEVANTRELEVANT
NOT_RELEVANT43139
RELEVANT49243

transformer at threshold 0.203

True / PredictedNOT_RELEVANTRELEVANT
NOT_RELEVANT42743
RELEVANT41251

Validation-Tuned Thresholds

  • —logistic_tfidf: threshold 0.470 (validation F1 0.779); test F1 change vs 0.5: +0.005.
  • —xgboost_tfidf: threshold 0.520 (validation F1 0.822); test F1 change vs 0.5: -0.001.
  • —embedding-logistic_sentence_embeddings: threshold 0.521 (validation F1 0.736); test F1 change vs 0.5: +0.004.
  • —embedding-svm_sentence_embeddings: threshold 0.473 (validation F1 0.745); test F1 change vs 0.5: -0.001.
  • —embedding-lightgbm_sentence_embeddings: threshold 0.433 (validation F1 0.741); test F1 change vs 0.5: +0.018.
  • —transformer: threshold 0.203 (validation F1 0.899); test F1 change vs 0.5: +0.010.

Artifacts

  • —logistic_tfidf: /content/agri-wheat-classifier/baselines/logistic
  • —xgboost_tfidf: /content/agri-wheat-classifier/baselines/xgboost
  • —embedding-logistic_sentence_embeddings: /content/agri-wheat-classifier/baselines/embedding-logistic
  • —embedding-svm_sentence_embeddings: /content/agri-wheat-classifier/baselines/embedding-svm
  • —embedding-lightgbm_sentence_embeddings: /content/agri-wheat-classifier/baselines/embedding-lightgbm
  • —transformer: /content/agri-wheat-classifier/transformer

Inference

Install the runtime dependencies:

bash
pip install transformers torch huggingface_hub pandas joblib scikit-learn xgboost lightgbm

Transformer

python
import torch
from transformers import AutoModelForSequenceClassification, AutoTokenizer

MODEL_ID = "YOUR_USERNAME/YOUR_MODEL_REPO"

texts = [
    "Rice export prices increased after new procurement rules were announced.",
    "The finance ministry released its monthly fuel tax bulletin.",
]

tokenizer = AutoTokenizer.from_pretrained(MODEL_ID, subfolder="transformer")
model = AutoModelForSequenceClassification.from_pretrained(MODEL_ID, subfolder="transformer")
threshold = float(getattr(model.config, "threshold", 0.5))

encoded = tokenizer(
    texts,
    truncation=True,
    padding=True,
    max_length=256,
    return_tensors="pt",
)

with torch.no_grad():
    logits = model(**encoded).logits
    probabilities = torch.softmax(logits, dim=-1)[:, 1].tolist()

for text, probability in zip(texts, probabilities):
    label = model.config.id2label[int(probability >= threshold)]
    print({"text": text, "probability_positive": probability, "label": label})

TF-IDF Baselines

Available baseline names in this run: "logistic", "xgboost".

python
import json
import joblib
from huggingface_hub import hf_hub_download

MODEL_ID = "YOUR_USERNAME/YOUR_MODEL_REPO"
BASELINE = "logistic"

texts = [
    "Maize production forecasts were revised after delayed rains.",
    "The central bank published new exchange rate statistics.",
]

model_path = hf_hub_download(
    repo_id=MODEL_ID,
    repo_type="model",
    filename=f"baselines/{BASELINE}/{BASELINE}_tfidf.joblib",
)
report_path = hf_hub_download(
    repo_id=MODEL_ID,
    repo_type="model",
    filename="report.json",
)

pipeline = joblib.load(model_path)
with open(report_path, encoding="utf-8") as handle:
    report = json.load(handle)

threshold = next(
    result["validation_best_threshold"]["threshold"]
    for result in report["results"]
    if result["model_type"] == f"{BASELINE}_tfidf"
)

probabilities = pipeline.predict_proba(texts)[:, 1]
for text, probability in zip(texts, probabilities):
    label = "RELEVANT" if probability >= threshold else "NOT_RELEVANT"
    print({"text": text, "probability_positive": float(probability), "label": label})

Sentence-Embedding Baselines

Available embedding baseline names in this run: "embedding-logistic", "embedding-svm", "embedding-lightgbm".

python
import joblib
import torch
from huggingface_hub import hf_hub_download
from transformers import AutoModel, AutoTokenizer

MODEL_ID = "YOUR_USERNAME/YOUR_MODEL_REPO"
BASELINE = "embedding-logistic"

texts = [
    "Wheat export inspections rose as demand from importers increased.",
    "The sports ministry announced a new stadium renovation plan.",
]

model_path = hf_hub_download(
    repo_id=MODEL_ID,
    repo_type="model",
    filename=f"baselines/{BASELINE}/{BASELINE}.joblib",
)
artifact = joblib.load(model_path)
tokenizer = AutoTokenizer.from_pretrained(artifact["embedding_model_name"])
encoder = AutoModel.from_pretrained(artifact["embedding_model_name"])
encoder.eval()

encoded_batches = []
batch_size = artifact.get("embedding_batch_size", 64)
for start in range(0, len(texts), batch_size):
    batch_texts = texts[start : start + batch_size]
    inputs = tokenizer(
        batch_texts,
        padding=True,
        truncation=True,
        max_length=artifact.get("embedding_max_length", 256),
        return_tensors="pt",
    )
    with torch.no_grad():
        outputs = encoder(**inputs)
    token_embeddings = outputs.last_hidden_state
    attention_mask = inputs["attention_mask"].unsqueeze(-1).to(token_embeddings.dtype)
    embeddings = (token_embeddings * attention_mask).sum(dim=1)
    embeddings = embeddings / attention_mask.sum(dim=1).clamp(min=1e-9)
    if artifact.get("normalize_embeddings", True):
        embeddings = torch.nn.functional.normalize(embeddings, p=2, dim=1)
    encoded_batches.append(embeddings)
embeddings = torch.cat(encoded_batches).numpy()
probabilities = artifact["classifier"].predict_proba(embeddings)[:, 1]
threshold = artifact["validation_best_threshold"]["threshold"]

for text, probability in zip(texts, probabilities):
    label = "RELEVANT" if probability >= threshold else "NOT_RELEVANT"
    print({"text": text, "probability_positive": float(probability), "label": label})

Files

  • —REPORT.md: Markdown report for this training run.
  • —report.json: Machine-readable report containing metrics and thresholds.
  • —transformer/: Fine-tuned Transformer artifacts, when Transformer training is enabled.
  • —baselines/: TF-IDF and sentence-embedding baseline artifacts, when baseline training is enabled.
  • —*/validation_predictions.csv and */test_predictions.csv: Split-level predictions.