Documentation
Docs

Documentation

Technical reference for the FIG-Loneliness NLP Pipeline

Project Overview

This project builds and evaluates an NLP pipeline for detecting loneliness self-disclosure in Reddit posts using the FIG-Loneliness dataset. Loneliness self-disclosure is often subtle and indirect, expressed through linguistic markers of social disconnection and relational dissatisfaction rather than direct statements. The pipeline compares five text representations and three classical classifiers, plus a fine-tuned DistilBERT model.

Dataset

FIG-Loneliness contains 5,633 Reddit posts annotated for loneliness self-disclosure by trained undergraduate research assistants and MTurk workers. Posts were collected from four subreddits (r/loneliness, r/lonely, r/youngadults, r/college) between 2018–2020 using the Pushshift API.

Preprocessing

All posts pass through a reproducible 8-step preprocessing pipeline before feature extraction. Preprocessing choices are kept minimal to avoid removing loneliness-relevant linguistic cues.

python
# Core preprocessing steps
text = ftfy.fix_text(raw_text)                  # 1. Unicode normalisation
text = unicodedata.normalize("NFKC", text)
text = bleach.clean(text, tags=[], strip=True)  # 2. HTML stripping
text = URL_PATTERN.sub(" ", text)               # 3. URL removal
text = MENTION_PATTERN.sub(" ", text)           # 3. Reddit mention removal
text = emoji.replace_emoji(text, " ")           # 3. Emoji removal
text = text.lower()                             # 4. Lowercasing
text = REPEATED_PATTERN.sub(r"\1\1", text)   # 4. Char normalisation
doc = nlp(text)                                 # 5. spaCy tokenisation
tokens_no_stop = [                              # 6. Stopword removal
    t.lemma_ for t in doc
    if not t.is_stop or t.text in NEGATIONS     # preserve negations!
]
→ Explore the preprocessing pipeline and sample posts

Text Representations

RepresentationTypeDimensionsLibraryNotes
Linguistic OnlySparse / Handcrafted13-dspaCyFully interpretable; direct coefficient attribution
TF-IDFSparse / BoW≤15,000-dscikit-learnReadable n-gram tokens; large vocabulary
TF-IDF + LinguisticSparse / Combined≤15,013-dscikit-learnBest of both sparse approaches
Word2VecDense / Averaged200-dgensimContext-aware token semantics; no direct interpretation
Sentence-BERTDense / Contextual384-dsentence-transformersWhole-sentence semantics; near-SOTA without fine-tuning
DistilBERTNeural / End-to-end—Hugging FaceBest performance; GPU required; attention-based

Models & Training

Classical classifiers (LR, SVM, RF) were trained on each of the 5 non-neural representations, yielding 15 classical experiments. DistilBERT was fine-tuned end-to-end for 3 epochs with early stopping (patience=2) on validation F1.

python
# DistilBERT fine-tuning
training_args = TrainingArguments(
    eval_strategy="epoch",
    save_strategy="epoch",
    num_train_epochs=3,
    learning_rate=2e-5,
    weight_decay=0.01,
    load_best_model_at_end=True,
    metric_for_best_model="f1",
)
trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=tokenized["train"],
    eval_dataset=tokenized["validation"],
    compute_metrics=compute_metrics,
    callbacks=[EarlyStoppingCallback(patience=2)],
)

Evaluation

All models are evaluated using Precision, Recall, F1-Score, Accuracy, and ROC-AUC. The binary task targets the Lonely class (label=1). The optimal classification threshold is derived from the Youden J statistic (maximises TPR − FPR on the validation ROC curve) and applied at inference.

Precision

TP / (TP + FP) — what fraction of predicted-lonely posts are truly lonely

Recall

TP / (TP + FN) — what fraction of truly lonely posts are identified

F1-Score

Harmonic mean of Precision and Recall

ROC-AUC

Area under the ROC curve — model discrimination ability across all thresholds

API Reference

The FastAPI backend is a read-only results server. All endpoints return pre-computed results from the pipeline. The API base URL is https://codenameberyl-fig-lone.hf.space/docs.

MethodPathDescription
GET/api/statusPipeline completion status and results availability
GET/api/eda/datasetDataset split sizes and class balance
GET/api/eda/class_distributionClass counts per split
GET/api/eda/length_statsWord/char/sentence count statistics
GET/api/eda/linguistic_stats13 linguistic feature statistics
GET/api/eda/ngramsTop-20 unigrams and bigrams by class
GET/api/eda/pos_distributionPOS tag proportions by class
GET/api/eda/plots/{name}Serve EDA plot PNG by filename
GET/api/eda/preprocessing/samplesSample preprocessed posts (split, label, n params)
GET/api/models/resultsAll 16 experiment results (val + test metrics)
GET/api/models/best_per_representationBest model per representation
GET/api/models/test_reportFull test report for the best overall model
GET/api/models/confusion_matrix/{key}Confusion matrix JSON for a model
GET/api/models/roc_curve/{key}ROC curve data for a model
GET/api/models/interpretability/summaryCross-representation interpretability summary
GET/api/models/interpretability/coefficients/{rep}LR coefficients for linguistic_only / tfidf / tfidf_ling
GET/api/models/interpretability/attentionDistilBERT attention weights
GET/api/models/error_analysis/summaryAggregated FP/FN analysis across all models
GET/api/models/error_analysis/{key}Detailed FP/FN examples for a model
GET/api/models/plots/{name}Serve evaluation or interpretability PNG
POST/api/predictClassify a single text { text: string }
POST/api/predict/batchClassify up to 100 texts string[]

Deployment

The pipeline must run once offline (on a machine with GPU access for DistilBERT). Results are then uploaded to HuggingFace Spaces which serves the FastAPI backend. This Next.js app connects to that API.

bash
# 1. Clone the Space repository
!git clone https://huggingface.co/spaces/your-username/fig-loneliness
%cd fig-loneliness

# 2. Install dependencies
!pip install -r requirements.txt

# 3. Run the full pipeline (requires T4 GPU for DistilBERT)
!python run_pipeline.py

# 4. Commit results back to the Space
!git add results/
!git commit -m "Add pipeline results"
!git push
DistilBERT fine-tuning requires ~30 minutes on a T4 GPU. The pipeline caches all intermediate results to disk, so individual stages can be re-run independently.

Limitations

  • —English-only: all models and features are trained on English Reddit text
  • —Reddit-specific: vocabulary, style, and discourse patterns may not generalise to other platforms
  • —Temporal: data covers 2018–2020 only; language patterns may have shifted
  • —Construct overlap: loneliness shares linguistic features with depression and anxiety
  • —No demographic data: fairness analysis across subgroups is not possible
  • —GPU dependency: DistilBERT fine-tuning requires a GPU; CPU inference is very slow
  • —Annotation noise: some posts have ambiguous loneliness status (majority vote used)

Citation

Jiang, Y., Jiang, Y., Leqi, L., & Winkielman, P. (2022). Many Ways to Be Lonely: Fine-Grained Characterization of Loneliness and Its Potential Changes in COVID-19. Proceedings of the International AAAI Conference on Web and Social Media, 16(1), 405–416. https://ojs.aaai.org/index.php/ICWSM/article/view/19302

Dataset licence: CC BY-NC 4.0