| # Hate Speech Detection β Multilingual Sequential Transfer Learning |
| ### GloVe Embeddings + Bidirectional LSTM (BiLSTM) |
|
|
| --- |
|
|
| ## What is this project about? |
|
|
| This project builds a system that can automatically detect **hate speech** in text written in three languages: |
| - **English** β standard English text |
| - **Hindi** β Hindi text (transliterated or native script) |
| - **Hinglish** β a mix of Hindi and English (very common in Indian social media) |
|
|
| The core question we are trying to answer is: |
|
|
| > **Does the order in which you teach a model different languages matter for how well it performs?** |
|
|
| For example β is a model that learns English first, then Hindi, then Hinglish better or worse than one that learns Hinglish first? |
|
|
| --- |
|
|
| ## The Dataset |
|
|
| | Property | Value | |
| |---|---| |
| | Total samples | 29,505 | |
| | English samples | 14,994 (50.8%) | |
| | Hindi samples | 9,738 (33.0%) | |
| | Hinglish samples | 4,774 (16.2%) | |
| | Hate speech (label=1) | 13,707 (46.5%) | |
| | Non-hate speech (label=0) | 15,799 (53.5%) | |
|
|
|  |
|
|
| The dataset was split into three parts: |
| - **Training set** β 17,704 samples (used to teach the model) |
| - **Validation set** β 2,950 samples (used to monitor learning during training) |
| - **Test set** β 8,852 samples (used only at the end to measure real performance) |
|
|
| --- |
|
|
| ## The Model β What is GloVe + BiLSTM? |
|
|
| Think of the model like a two-part reading machine: |
|
|
| ### Part 1: GloVe Embeddings (the dictionary) |
| Before the model can understand words, it needs to know what words *mean* relative to each other. GloVe (Global Vectors) is a pre-trained lookup table of **300,000+ English words**, where each word is represented as a list of 300 numbers that capture its meaning. Words with similar meanings end up with similar numbers. |
|
|
| - We used `glove.6B.300d.txt` β 6 billion word training corpus, 300 dimensions |
| - The embedding layer is **frozen** (not updated during training) β we keep GloVe's knowledge as-is and only train the layers on top |
|
|
| ### Part 2: Bidirectional LSTM (the reader) |
| An LSTM (Long Short-Term Memory) is a type of neural network designed to read sequences β like sentences β and remember what it read. **Bidirectional** means it reads the sentence both forwards and backwards, so it understands context from both directions. |
|
|
| ``` |
| Input sentence |
| β |
| GloVe Embeddings (300d, frozen) |
| β |
| BiLSTM (128 units, reads leftβright AND rightβleft) |
| β |
| Dropout (50% β randomly switches off neurons to prevent overfitting) |
| β |
| Dense layer (64 neurons, ReLU activation) |
| β |
| Output (1 neuron, Sigmoid β gives a probability 0 to 1) |
| β |
| > 0.5 = Hate Speech, β€ 0.5 = Not Hate Speech |
| ``` |
|
|
| --- |
|
|
| ## The Training Strategy β What is Transfer Learning? |
|
|
| **Transfer learning** means the model carries what it learned from one task into the next. Like a student who already knows French β learning Spanish is easier because both share Latin roots. |
|
|
| In our case, we train the model on one language, and instead of starting fresh for the next language, we **keep all the weights (knowledge)** from the previous training. The model continues learning from where it left off. |
|
|
| ### The Bug We Fixed |
| The original code was creating a **brand new model** for every language β resetting all the weights each time. That is not transfer learning, it's just training three separate models. We fixed this by building the model **once** and sequentially fine-tuning it. |
|
|
| ```python |
| # WRONG β model reset every loop iteration |
| for lang in languages: |
| model = Sequential() # β new model = no transfer learning |
| model.fit(...) |
| |
| # CORRECT β model built once, weights carry forward |
| model = build_model() # β built once |
| for lang in languages: |
| model.fit(...) # β continues learning from previous language |
| ``` |
|
|
| --- |
|
|
| ## Plan B β The Experiment |
|
|
| We ran all **6 possible orderings** of the three languages, each followed by a final training round on the complete shuffled dataset: |
|
|
| | # | Strategy | |
| |---|---| |
| | 1 | English β Hindi β Hinglish β Full | |
| | 2 | English β Hinglish β Hindi β Full | |
| | 3 | Hindi β English β Hinglish β Full | |
| | 4 | Hindi β Hinglish β English β Full | |
| | 5 | Hinglish β English β Hindi β Full | |
| | 6 | Hinglish β Hindi β English β Full | |
|
|
| For each strategy, training happens in 4 phases. **After each phase**, we immediately evaluate the model on that specific language's test data and record all metrics. This tells us how well the model performs at each stage of the learning journey. |
|
|
| ``` |
| Phase 1: Train on Language A β Test on Language A test set β Record metrics + plots |
| Phase 2: Train on Language B β Test on Language B test set β Record metrics + plots |
| Phase 3: Train on Language C β Test on Language C test set β Record metrics + plots |
| Phase 4: Train on Full data β Test on Full test set β Record metrics + plots |
| ``` |
|
|
| Each phase used **8 epochs** with batch size 32 (64 for the full phase). |
|
|
| --- |
|
|
| ## Metrics β What do we measure? |
|
|
| | Metric | What it means in plain English | |
| |---|---| |
| | **Accuracy** | Out of all predictions, how many were correct? | |
| | **Balanced Accuracy** | Accuracy adjusted for class imbalance (more fair) | |
| | **Precision** | Of everything the model flagged as hate speech, how much actually was? | |
| | **Recall** | Of all actual hate speech, how much did the model catch? | |
| | **Specificity** | Of all non-hate speech, how much did the model correctly ignore? | |
| | **F1 Score** | Balance between Precision and Recall (harmonic mean) | |
| | **ROC-AUC** | Overall ability to distinguish hate from non-hate (1.0 = perfect) | |
|
|
| --- |
|
|
| ## Results Summary |
|
|
| Full results are in `output/results_tables/all_strategies_results.csv`. Key highlights: |
|
|
| ### English phase performance across strategies (best language) |
|
|
| | Strategy | Accuracy | F1 | ROC-AUC | |
| |---|---|---|---| |
| | English β Hindi β Hinglish β Full | 0.7701 | 0.7696 | 0.8504 | |
| | English β Hinglish β Hindi β Full | 0.7721 | 0.7743 | 0.8525 | |
| | Hindi β English β Hinglish β Full | 0.7780 | 0.7830 | 0.8549 | |
| | Hindi β Hinglish β English β Full | 0.7780 | 0.7816 | 0.8563 | |
| | Hinglish β English β Hindi β Full | 0.7716 | 0.7829 | 0.8484 | |
| | Hinglish β Hindi β English β Full | 0.7765 | 0.7811 | 0.8534 | |
|
|
| ### Full dataset phase (final performance) |
|
|
| | Strategy | Accuracy | F1 | ROC-AUC | |
| |---|---|---|---| |
| | English β Hindi β Hinglish β Full | 0.6796 | 0.5923 | 0.7599 | |
| | English β Hinglish β Hindi β Full | 0.6813 | 0.6244 | 0.7535 | |
| | Hindi β English β Hinglish β Full | 0.6854 | 0.6419 | 0.7528 | |
| | Hindi β Hinglish β English β Full | 0.6865 | 0.6364 | 0.7507 | |
| | Hinglish β English β Hindi β Full | 0.6778 | 0.6285 | 0.7521 | |
| | Hinglish β Hindi β English β Full | 0.6845 | 0.6301 | 0.7548 | |
|
|
| ### Key observations |
| - **English** consistently achieves the highest accuracy (~77%) regardless of when it is trained β likely because GloVe embeddings are English-centric |
| - **Hindi** is the hardest language β accuracy hovers around 55β59% across all strategies |
| - **Hinglish** sits in the middle (~66β70%) which makes sense as it borrows heavily from English |
| - Strategies that train **Hindi first** (`Hindi β English β Hinglish`) tend to recover better in later phases, suggesting the model benefits from tackling the hardest language early |
| - The **Full phase** shows consistent ~68% accuracy across all strategies, suggesting the final shuffled training normalises the differences introduced by ordering |
|
|
| --- |
|
|
| ## Plots by Strategy |
|
|
| ### Strategy 1: English β Hindi β Hinglish β Full |
|
|
| | Phase | Training Curves | Confusion Matrix | ROC Curve | PR Curve | F1 Curve | |
| |---|---|---|---|---|---| |
| | English |  |  |  |  |  | |
| | Hindi |  |  |  |  |  | |
| | Hinglish |  |  |  |  |  | |
| | Full |  |  |  |  |  | |
|
|
| --- |
|
|
| ### Strategy 2: English β Hinglish β Hindi β Full |
|
|
| | Phase | Training Curves | Confusion Matrix | ROC Curve | PR Curve | F1 Curve | |
| |---|---|---|---|---|---| |
| | English |  |  |  |  |  | |
| | Hinglish |  |  |  |  |  | |
| | Hindi |  |  |  |  |  | |
| | Full |  |  |  |  |  | |
|
|
| --- |
|
|
| ### Strategy 3: Hindi β English β Hinglish β Full |
|
|
| | Phase | Training Curves | Confusion Matrix | ROC Curve | PR Curve | F1 Curve | |
| |---|---|---|---|---|---| |
| | Hindi |  |  |  |  |  | |
| | English |  |  |  |  |  | |
| | Hinglish |  |  |  |  |  | |
| | Full |  |  |  |  |  | |
|
|
| --- |
|
|
| ### Strategy 4: Hindi β Hinglish β English β Full |
|
|
| | Phase | Training Curves | Confusion Matrix | ROC Curve | PR Curve | F1 Curve | |
| |---|---|---|---|---|---| |
| | Hindi |  |  |  |  |  | |
| | Hinglish |  |  |  |  |  | |
| | English |  |  |  |  |  | |
| | Full |  |  |  |  |  | |
|
|
| --- |
|
|
| ### Strategy 5: Hinglish β English β Hindi β Full |
|
|
| | Phase | Training Curves | Confusion Matrix | ROC Curve | PR Curve | F1 Curve | |
| |---|---|---|---|---|---| |
| | Hinglish |  |  |  |  |  | |
| | English |  |  |  |  |  | |
| | Hindi |  |  |  |  |  | |
| | Full |  |  |  |  |  | |
|
|
| --- |
|
|
| ### Strategy 6: Hinglish β Hindi β English β Full |
|
|
| | Phase | Training Curves | Confusion Matrix | ROC Curve | PR Curve | F1 Curve | |
| |---|---|---|---|---|---| |
| | Hinglish |  |  |  |  |  | |
| | Hindi |  |  |  |  |  | |
| | English |  |  |  |  |  | |
| | Full |  |  |  |  |  | |
|
|
| --- |
|
|
| ## Output Files |
|
|
| ``` |
| output/ |
| βββ dataset_splits/ |
| β βββ train.csv # 17,704 training samples |
| β βββ val.csv # 2,950 validation samples |
| β βββ test.csv # 8,852 test samples |
| β |
| βββ results_tables/ |
| β βββ all_strategies_results.csv # All 24 rows (6 strategies Γ 4 phases) |
| β βββ english_to_hindi_to_hinglish_results.csv |
| β βββ english_to_hinglish_to_hindi_results.csv |
| β βββ hindi_to_english_to_hinglish_results.csv |
| β βββ hindi_to_hinglish_to_english_results.csv |
| β βββ hinglish_to_english_to_hindi_results.csv |
| β βββ hinglish_to_hindi_to_english_results.csv |
| β |
| βββ figures/ |
| βββ language_distribution.png # Pie chart of dataset languages |
| β |
| βββ english_to_hindi_to_hinglish/ # One folder per strategy |
| β βββ *_[english]_curves.png # Train/Val accuracy + loss |
| β βββ *_[english]_cm.png # Confusion matrix |
| β βββ *_[english]_roc.png # ROC curve |
| β βββ *_[english]_pr.png # Precision-Recall curve |
| β βββ *_[english]_f1.png # F1 vs Threshold curve |
| β βββ *_[hindi]_curves.png |
| β βββ *_[hindi]_cm.png ... |
| β βββ *_[hinglish]_curves.png |
| β βββ *_[hinglish]_cm.png ... |
| β βββ *_[Full]_curves.png |
| β βββ *_[Full]_cm.png ... |
| β |
| βββ english_to_hinglish_to_hindi/ |
| βββ hindi_to_english_to_hinglish/ |
| βββ hindi_to_hinglish_to_english/ |
| βββ hinglish_to_english_to_hindi/ |
| βββ hinglish_to_hindi_to_english/ |
| ``` |
|
|
| --- |
|
|
| ## How to Run |
|
|
| ### Requirements |
| ```bash |
| pip install tensorflow scikit-learn pandas seaborn matplotlib |
| ``` |
|
|
| You also need GloVe embeddings (`glove.6B.300d.txt`) placed at `/root/glove.6B.300d.txt`: |
| ```bash |
| wget http://nlp.stanford.edu/data/glove.6B.zip && unzip glove.6B.zip |
| ``` |
|
|
| ### Run |
| ```bash |
| python main.py |
| ``` |
|
|
| Training was performed on an NVIDIA H200 GPU (Vast.ai) β total runtime approximately 15β20 minutes for all 6 strategies. |
|
|
| --- |
|
|
| ## Project Structure |
|
|
| ``` |
| SASC/ |
| βββ main.py # Full training + evaluation pipeline |
| βββ dataset.csv # Raw dataset (29,505 samples) |
| βββ README.md # This file |
| βββ output/ # All results, figures, and model checkpoints |
| ``` |
|
|