lord-amir26/dashboard_stance_mbg
0
Hybrid Stance Detection & Topic Modeling pada Komentar YouTube tentang Program Makan Bergizi Gratis (MBG)
Skripsi — Program Studi Teknologi Informasi
Penelitian ini merancang sistem Hybrid Analysis untuk mengklasifikasikan keberpihakan (stance) publik terhadap Program Makan Bergizi Gratis (MBG) berdasarkan komentar YouTube, sekaligus mengekstraksi topik diskusi spesifik di setiap kelompok stance.
Ringkasan
Arsitektur Sistem
┌─────────────────────────────────────────────────────────────┐
│ DATA COLLECTION │
│ YouTube Data API v3 → 4.390 komentar dari 93 video │
└────────────────────────────┬────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ PREPROCESSING │
│ Cleaning → Case Folding → Normalisasi Slang → Deduplikasi │
│ Hasil: 2.469 komentar bersih │
└────────────────────────────┬────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ MANUAL ANNOTATION (Streamlit UI) │
│ 840 komentar dilabeli: Favor | Against | Neutral │
│ Stratified Sampling + 2 gelombang anotasi │
└────────────┬───────────────────────────────────┬────────────┘
↓ ↓
┌────────────────────────┐ ┌──────────────────────────┐
│ SUPERVISED BRANCH │ │ UNSUPERVISED BRANCH │
│ IndoBERT Fine-Tuning │ │ BERTopic Stance- │
│ + Focal Loss (γ=2.0) │ │ Stratified │
│ + 5-Fold CV │ │ (per kelas stance) │
│ + Ablation Study │ │ │
│ (4 konfigurasi) │ │ 2.469 komentar → │
│ │ │ 40 topik bermakna │
└────────────┬───────────┘ └────────────┬─────────────┘
↓ ↓
┌─────────────────────────────────────────────────────────────┐
│ HYBRID INTEGRATION │
│ Topic-Stance Matrix → Policy Insights → Dashboard │
└─────────────────────────────────────────────────────────────┘Struktur Proyek
stance_mbg/
├── configs/ # Konfigurasi eksperimen
│ ├── channels.yaml # Daftar kanal YouTube target
│ ├── data_config.yaml # Parameter preprocessing
│ ├── model_config.yaml # Arsitektur model
│ └── training_config.yaml # Hyperparameter training
│
├── data/ # Dataset (tidak di-commit, lihat .gitignore)
│ ├── raw/ # Data mentah hasil scraping
│ ├── processed/ # Data setelah preprocessing
│ ├── annotated/ # Data berlabel manual (840 sampel)
│ ├── augmented/ # Cache Back-Translation
│ └── splits/ # Partisi train/test/fold
│
├── notebooks/ # Jupyter Notebooks eksperimen
│ ├── 00_setup_drive_mount.ipynb # Setup environment (Google Colab)
│ ├── 01_preprocessing_split.ipynb # Preprocessing dan data splitting
│ ├── 02_augmentation_bt.ipynb # Augmentasi Back-Translation
│ ├── 02b_baseline_logres_tfidf.ipynb # Baseline Logistic Regression
│ ├── 03_training_ablation_cv.ipynb # Training IndoBERT + Ablation Study
│ ├── 04_evaluation_metrics.ipynb # Evaluasi metrik dan visualisasi
│ ├── 05_bertopic_stance_stratified.ipynb # Topic modeling per stance
│ ├── 06_topic_stance_matrix_insight.ipynb # Integrasi Topic-Stance Matrix
│ └── utils/ # Helper modules untuk notebooks
│ ├── augmentation.py # Fungsi augmentasi data
│ ├── io_helpers.py # Utilitas baca/tulis file
│ ├── losses.py # Implementasi Focal Loss
│ └── metrics.py # Fungsi evaluasi metrik
│
├── scripts/ # Pipeline scripts (CLI)
│ ├── collect_data.py # Orkestrasi scraping YouTube
│ ├── annotation_tool.py # Streamlit UI untuk anotasi manual
│ ├── create_annotation_sample.py # Stratified sampling untuk anotasi
│ ├── create_splits.py # Pembagian data train/test
│ ├── augment_data.py # Eksekusi Back-Translation
│ ├── train_stance_model.py # Training IndoBERT stance detector
│ ├── train_topic_models.py # Training BERTopic per stance group
│ ├── run_hybrid_analysis.py # Pipeline hybrid (stance + topic)
│ ├── regenerate_figures_v2.py # Regenerasi grafik dari data JSON
│ └── regenerate_stance_figures.py # Regenerasi visualisasi stance/topic
│
├── src/ # Source code (modular library)
│ ├── data/
│ │ ├── youtube_scraper.py # YouTube Data API v3 scraper
│ │ ├── preprocessor.py # Text cleaning & normalisasi
│ │ ├── augmentation.py # Augmentasi data
│ │ └── back_translation.py # Pipeline Back-Translation
│ ├── models/
│ │ ├── stance_detector.py # IndoBERT fine-tuning wrapper
│ │ └── topic_modeler.py # BERTopic stance-stratified wrapper
│ ├── evaluation/
│ │ ├── metrics.py # Accuracy, F1, AUC, Confusion Matrix
│ │ └── topic_metrics.py # Koherensi topik, c-TF-IDF
│ └── analysis/
│ ├── hybrid_analyzer.py # Integrasi stance + topic
│ └── insight_generator.py # Generator policy insights
│
├── models/ # Bobot model tersimpan (tidak di-commit)
│ ├── best_model/ # Model terbaik (v3_focal_only)
│ ├── v1_baseline/ # IndoBERT + Cross-Entropy
│ ├── v2_bt_only/ # IndoBERT + BT + Cross-Entropy
│ ├── v3_focal_only/ # IndoBERT + Focal Loss ← TERBAIK
│ └── v4_bt_focal/ # IndoBERT + BT + Focal Loss
│
├── results/ # Output eksperimen (tidak di-commit)
│ ├── figures/ # Grafik dan visualisasi
│ ├── metrics/ # JSON metrik per fold & ablation
│ ├── reports/ # Rangkuman evaluasi & insights
│ ├── tables/ # CSV prediksi & analisis
│ └── topics/ # JSON topik per stance group
│
├── ui/
│ └── app.py # Dashboard Streamlit interaktif
│
├── docs/ # (Di-ignore dari Git) Naskah draft
│ └── draft_outline/
│
├── .env.example # Template environment variables
├── .gitignore # Daftar file yang diabaikan Git
└── requirements.txt # Dependensi PythonArsitektur Deployment (MLOps)
Proyek ini menggunakan pemisahan infrastruktur (Decoupled MLOps) untuk menjaga kebersihan repositori dan efisiensi ruang penyimpanan:
- GitHub (Source Code): Repositori utama (amirullahh/mbg-indobert-stance) hanya menyimpan source code Python. Data set privasi warganet dan model raksasa (IndoBERT) secara ketat diblokir oleh
.gitignore. - Hugging Face Model Hub (Artifacts): Bobot model IndoBERT terbaik disimpan secara terpisah di repository Hugging Face Model (lord-amir26/mbg-indobert-stance).
- Hugging Face Spaces (Application Server): Aplikasi interaktif Streamlit di-host di Hugging Face Spaces. Space ini terhubung langsung ke GitHub (Continuous Integration) dan akan mengunduh model dari Model Hub secara otomatis melalui secure token.
- Local Fallback: Jika aplikasi dijalankan di laptop lokal tanpa koneksi internet yang kencang, sistem cerdas di
app.pyakan otomatis menggunakan direktori model lokal (models/best_model) jika tersedia.
Teknologi dan Dependensi Utama
Cara Menjalankan
1. Persiapan Environment
# Clone repository
git clone https://github.com/amirullahh/mbg-indobert-stance.git
cd mbg-indobert-stance
# Buat virtual environment
python -m venv venv
source venv/bin/activate # Linux/Mac
venv\Scripts\activate # Windows
# Install dependensi
pip install -r requirements.txt2. Konfigurasi API Key
# Salin template environment
cp .env.example .env
# Isi API Key YouTube di file .env
# YOUTUBE_API_KEY=<kunci_api_youtube_anda>3. Pipeline Eksekusi
# Tahap 1: Scraping data YouTube
python scripts/collect_data.py
# Tahap 2: Sampling untuk anotasi
python scripts/create_annotation_sample.py
# Tahap 3: Anotasi manual via Streamlit
streamlit run scripts/annotation_tool.py
# Tahap 4: Pembagian data train/test
python scripts/create_splits.py
# Tahap 5: Augmentasi Back-Translation
python scripts/augment_data.py
# Tahap 6: Training IndoBERT (disarankan GPU/Google Colab)
python scripts/train_stance_model.py
# Tahap 7: Topic Modeling (BERTopic per stance)
python scripts/train_topic_models.py
# Tahap 8: Analisis Hybrid (stance + topic + insights)
python scripts/run_hybrid_analysis.py4. Menjalankan Dashboard
streamlit run ui/app.pyHasil Utama
Ablation Study (5-Fold Cross Validation)
Evaluasi Final (Held-out Test Set, n=126)
Temuan Kunci
- Focal Loss lebih unggul dibanding Back-Translation dalam menangani ketidakseimbangan kelas pada teks informal berbahasa Indonesia.
- Kelas Favor (minoritas) justru mencetak F1-Score tertinggi (84,51%), membuktikan efektivitas Focal Loss.
- BERTopic Stance-Stratified berhasil mengekstraksi 40 topik bermakna dan mengungkap bahwa kekhawatiran terbesar publik terletak pada aspek "Korupsi" dan "Anggaran".
Catatan Reproduksi
- Training model sebaiknya dilakukan pada GPU (Google Colab T4 atau setara) untuk efisiensi waktu.
- Notebook di folder
notebooks/berisi seluruh eksperimen lengkap dengan output, siap untuk direproduksi. - Data mentah tidak disertakan dalam repository ini demi privasi. Gunakan pipeline scraping (
scripts/collect_data.py) untuk mengumpulkan data secara independen. - Random seed ditetapkan di
42untuk seluruh eksperimen guna menjamin reproduktibilitas.
Lisensi
Proyek ini dikembangkan untuk keperluan akademik (Skripsi S1). Penggunaan lebih lanjut memerlukan izin dari penulis.
Kontak
Untuk pertanyaan terkait penelitian ini, silakan hubungi penulis melalui amirullahhidayat12@gmail.com
