| --- |
| language: |
| - multilingual |
| - en |
| - pt |
| - fr |
| - es |
| - uk |
| - de |
| license: apache-2.0 |
| base_model: distilbert-base-multilingual-cased |
| pipeline_tag: text-classification |
| tags: |
| - multi-label-classification |
| - customer-feedback |
| - churn |
| - cloud-gaming |
| --- |
| |
| # Multi-label classification of cloud-gaming churn feedback |
|
|
| Fine-tuned `distilbert-base-multilingual-cased` that tags the **technical issue** a user complains |
| about in the free-text comment left when cancelling a cloud-gaming subscription. A single comment |
| may describe several problems at once, so this is a **multi-label** task over 6 classes. |
|
|
| Comments are short (median 73 characters) and multilingual β no translation step is used. |
|
|
| π **Live demo:** [multilingual-game-feedback-classification.streamlit.app](https://multilingual-game-feedback-classification.streamlit.app) |
|
|
| ## Labels |
|
|
| | label | meaning | |
| |---|---| |
| | `ping_latency` | network delay, high ping, input lag | |
| | `frames_drop` | low FPS, stuttering, unstable stream | |
| | `unable_launch` | the game or service does not start | |
| | `mouse_keyboard_headset` | peripherals: mouse, keyboard, headset, controller | |
| | `game_bug` | a defect inside the game itself | |
| | `failed_save` | progress is lost or not saved | |
|
|
| ## Usage |
|
|
| The model outputs 6 independent sigmoid probabilities. **Do not use a 0.5 threshold** β per-class |
| thresholds were tuned on the validation set and are shipped in `inference_config.json`. They give |
| macro-F1 0.620 on the test set versus 0.581 with a plain 0.5 threshold. |
|
|
| ```python |
| import json |
| |
| import torch |
| from huggingface_hub import hf_hub_download |
| from transformers import AutoModelForSequenceClassification, AutoTokenizer |
| |
| REPO = "dar1bi/cloud-gaming-feedback-multilabel" |
| |
| tokenizer = AutoTokenizer.from_pretrained(REPO) |
| model = AutoModelForSequenceClassification.from_pretrained(REPO).eval() |
| config = json.load(open(hf_hub_download(REPO, "inference_config.json"))) |
| |
| text = "Constant micro stutter and very low fps in The Finals" |
| encoded = tokenizer(text, truncation=True, padding="max_length", |
| max_length=config["max_len"], return_tensors="pt") |
| with torch.no_grad(): |
| probabilities = torch.sigmoid(model(**encoded).logits).numpy()[0] |
| |
| labels = [label for label, probability, threshold |
| in zip(config["labels"], probabilities, config["thresholds"]) |
| if probability >= threshold] |
| print(labels) # ['frames_drop'] |
| ``` |
|
|
| ## Training |
|
|
| - **Base model:** `distilbert-base-multilingual-cased` |
| - **Objective:** `BCEWithLogitsLoss` with `pos_weight` to compensate for class imbalance |
| - **Hyperparameters:** learning rate 8e-5 (grid over 2e-5 / 5e-5 / 8e-5), 5 epochs with best-epoch |
| selection by validation macro-F1, batch size 16, max sequence length 64 |
| - **Split:** iterative-stratified multi-label split 70 / 15 / 15 β 2760 / 584 / 612 examples |
| - **Hardware:** Apple MPS, ~290 s per configuration |
|
|
| ## Evaluation |
|
|
| Primary metric is **macro-F1** β it weights rare classes equally with frequent ones. |
|
|
| | split | macro-F1 | micro-F1 | macro ROC-AUC | mAP | |
| |---|---|---|---|---| |
| | validation | 0.681 | 0.717 | 0.828 | 0.727 | |
| | test | 0.620 | 0.678 | 0.817 | 0.685 | |
|
|
| Per-class F1 on the test set: `ping_latency` 0.78, `unable_launch` 0.70, |
| `mouse_keyboard_headset` 0.67, `frames_drop` 0.62, `game_bug` 0.49, `failed_save` 0.46. |
|
|
| The model was selected on the validation set among seven approaches, from TF-IDF with classical |
| classifiers to a zero-shot LLM. A most-frequent-class baseline scores 0.119 macro-F1. |
|
|
| ## Limitations |
|
|
| - **Noisy labels.** Labels are self-reported by users in the cancellation form, so they are neither |
| consistent nor mutually exclusive. Part of what looks like model error is actually label noise. |
| - **Rare classes.** `game_bug` and `failed_save` are recognised in fewer than half of real cases β |
| they are infrequent in the data and semantically overlap with the other classes. |
| - **Very short texts.** Comments under 30 characters often carry too little signal. |
| - **Single split, single seed.** Differences of 0.01β0.02 macro-F1 are within noise. |
|
|
| ## Training data |
|
|
| Internal user feedback of a cloud-gaming service, collected at subscription cancellation |
| (4 616 records, 3 956 after cleaning). The dataset is confidential and is **not published**. |
|
|