Instructions to use Kenpache/hs-code-classifier-en with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use Kenpache/hs-code-classifier-en with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-classification", model="Kenpache/hs-code-classifier-en", trust_remote_code=True)# Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("Kenpache/hs-code-classifier-en", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
HS Code Classifier (HS6, English)
Give it an English product description, get back the 6-digit Harmonized System (HS) code — the commodity code that drives customs tariff classification, duty rates, HTS lookups and trade compliance.
"men's cotton knitted t-shirt, short sleeve" → 610910 (0.998)
"portable laptop computer, 14 inch display, 1.2 kg" → 847130 (0.994)
"lithium-ion rechargeable battery, 3.7 V, 5000 mAh" → 850760 (0.929)
"roasted arabica coffee beans, not decaffeinated" → 090121 (0.811)
Fine-tuned end-to-end over the full 6,750-class HS6 space — not a toy subset of the most common chapters. HS4 (1,266 headings) and HS2 (97 chapters) come out of the same forward pass and are guaranteed consistent with the HS6 answer.
| Task | Product description → HS6 tariff code |
| Input language | English |
| Label space | 6,750 HS6 · 1,266 HS4 · 97 HS2 |
| Accuracy on full product descriptions | 71.94% top-1 · 91.08% top-5 |
| Parameters | 573.6M (fp32, 2.2 GB) |
| Context window | 1,024 tokens at inference |
What you get depends on what you give it: a full description runs at ~72% top-1, a two-word catalogue stub at ~38%. The complete breakdown — by input type, by length, by confidence — is right below.
Accuracy
Measured on a frozen held-out test set of 8,065 product descriptions that has zero overlap with training and was never used for tuning any hyperparameter or threshold.
Accuracy depends heavily on how much you tell it
This is the single most important table in this card:
| Input | Share of test | Top-1 | Top-5 |
|---|---|---|---|
| Full product description | 35% | 71.94% | 91.08% |
| Short subject line | 22% | 46.34% | 73.17% |
| Two- or three-word phrase | 43% | 38.01% | 61.70% |
By raw character length:
| Length | Top-1 |
|---|---|
| 0–40 chars | 39.00% |
| 40–100 | 45.15% |
| 100–200 | 46.98% |
| 200–500 | 73.75% |
| 500–1500 | 74.72% |
| 1500+ | 64.77% |
Do not truncate your inputs. Material, construction, and intended use are exactly
the features that separate one subheading from another; "two folding cots" does not
contain them and no model can recover them. Feed the whole description — the spec
sheet, the paragraph, the invoice line with attributes — and accuracy roughly doubles.
Averaged over the whole benchmark
The benchmark is deliberately hostile: 62% of its inputs are under 100 characters, so the average is dragged down by fragments that carry no classifiable features at all. Averaged over all 8,065 items:
| Metric | Score |
|---|---|
| HS6 top-1 (exact 6-digit match) | 51.70% |
| HS4 top-1 (heading) | 60.99% |
| HS2 top-1 (chapter) | 74.28% |
| HS6 top-5 recall | 74.48% |
Which of the two numbers applies to you is decided by your input, not by the model: feed full descriptions and expect the 72% row, feed catalogue stubs and expect the 38% row. Nothing is hidden here — both are stated so you can predict your own result before you download 2.2 GB.
Confidence is usable as a threshold
Top-1 softmax probability is monotonically informative, which makes a straight-through / review split practical:
| Confidence | Share of traffic | Accuracy |
|---|---|---|
| 0.8 – 1.0 | 62.8% | 63.7% |
| 0.6 – 0.8 | 12.6% | 28.4% |
| 0.4 – 0.6 | 12.3% | 21.6% |
| 0.2 – 0.4 | 9.1% | 12.0% |
| 0.0 – 0.2 | 3.2% | 3.1% |
With temperature T ≈ 1.75 applied to the logits, calibration improves further: you
can auto-accept 41.5% of the flow at 80.0% accuracy. Recommended pattern — auto-clear
high-confidence items, route the rest to a human with the top-5 list attached
(top-5 covers 74% of everything and 91% of full descriptions).
Where the errors go
| Outcome | Share |
|---|---|
| Correct at top-1 | 51.70% |
| Correct code present in top-5, but not ranked first | 22.78% |
| Correct code absent from top-5 | 25.52% |
Of the misses, 18.1% stay inside the correct HS4 heading and 26.6% inside the correct HS2 chapter — i.e. a large part of the error is near-miss, not nonsense.
Quick start
pip install transformers torch sentencepiece
Verified on transformers 5.5 / torch 2.11. The model code uses only long-stable
transformers APIs, so 4.4x and later should work as well.
from transformers import AutoModel, AutoTokenizer
REPO = "Kenpache/hs-code-classifier-en"
model = AutoModel.from_pretrained(REPO, trust_remote_code=True).eval()
tokenizer = AutoTokenizer.from_pretrained(REPO, trust_remote_code=True)
model.classify(["men's cotton knitted t-shirt, short sleeve"], tokenizer, top_k=5)
# [[{'hs6': '610910', 'score': 0.9983},
# {'hs6': '610990', 'score': 0.0010},
# {'hs6': '611020', 'score': 0.0005}, ...]]
classify() batches for you and accepts a list of any length:
codes = model.classify(descriptions, tokenizer, top_k=5, batch_size=32)
On GPU
model = AutoModel.from_pretrained(REPO, trust_remote_code=True).to("cuda").eval()
CUDA, Apple Silicon (mps) and CPU all work. Roughly 3 GB of VRAM at batch 16 /
length 1024; about 4 GB of RAM on CPU.
Leave the context window at 1,024 tokens. It is already the default in
config.json; lowering recommended_max_length costs about 2.9 points on texts longer
than 1,500 characters, and raising it to 2,048 adds nothing.
All three HS levels at once
import torch
enc = tokenizer(["woven cotton fabric, dyed, 200 g/m2"], truncation=True,
max_length=1024, return_tensors="pt")
with torch.no_grad():
out = model(**enc)
hs6 = model.config.id2label[out.logits.argmax(-1).item()] # '520839'
hs4 = model.config.id2hs4[out.logits_hs4.argmax(-1).item()] # '5208'
hs2 = model.config.id2hs2[out.logits_hs2.argmax(-1).item()] # '52'
hs4 and hs2 are marginals of the same distribution (logsumexp over the children
of each parent), so the levels can never contradict each other: the model cannot
return heading 6109 and a subheading that lives under 6110.
Limitations
- English only. The encoder is multilingual, but the head was trained on English product descriptions. Other languages are untested and expected to be much weaker.
- HS6 only. The first six digits are internationally harmonized; national 8–10 digit tariff lines are out of scope and this model does not predict them.
- Short inputs are hard, as the tables above show. Under ~40 characters, expect ~39% top-1.
- Coverage is uneven across the 6,750 classes. Rarely-seen codes are much weaker than the headline number suggests; roughly 3,800 codes carry the bulk of the model's competence.
- The ceiling is domain-imposed, not model-imposed. Identical descriptions legitimately receive different codes depending on context (end use, material composition, degree of processing), which caps any text-only classifier.
- Not legal or customs advice. Output is a ranked suggestion. Binding classification is a decision of the competent authority. Use this to triage, to pre-fill, and to route to a human — not to file unattended.
Intended use
Good fits:
- pre-filling HS6 on customs declarations, then human review of low-confidence rows
- catalogue / marketplace enrichment at scale
- landed-cost and duty estimation tooling
- deduplicating and sanity-checking existing classifications (flag rows where the model is confident and disagrees)
Poor fits: unattended filing, national tariff lines beyond 6 digits, non-English input.
Files
| File | What it is |
|---|---|
model.safetensors |
weights, fp32, 2.2 GB |
config.json |
encoder config + head config + id2label for all 6,750 HS6 codes |
modeling_hs6.py, configuration_hs6.py |
model definition (loaded via trust_remote_code=True) |
tokenizer.json, sentencepiece.bpe.model, … |
XLM-R tokenizer, model_max_length 1024 |
License
MIT, following the BAAI/bge-m3 base model.
Citation
@misc{hs6_classifier_en,
title = {HS Code Classifier (HS6, English)},
year = {2026},
note = {XLM-RoBERTa-large (bge-m3) with a flat 6,750-class HS6 head
and marginalized HS4/HS2 levels},
url = {https://huggingface.co/Kenpache/hs-code-classifier-en}
}
- Downloads last month
- 18
Model tree for Kenpache/hs-code-classifier-en
Base model
BAAI/bge-m3