topic_model_bc / src /streamlit_app.py
alzami's picture
Update src/streamlit_app.py
3eee6cd verified
"""
Topic Modelling menggunakan LDA (Latent Dirichlet Allocation) untuk Teks Bahasa Indonesia
"""
# 1. Import library yang diperlukan
import pandas as pd
import numpy as np
import re
import matplotlib.pyplot as plt
from pprint import pprint
# NLP processing
import nltk
from nltk.tokenize import word_tokenize
from Sastrawi.Stemmer.StemmerFactory import StemmerFactory
# Gensim
import gensim
import gensim.corpora as corpora
from gensim.models import CoherenceModel
import pyLDAvis
import pyLDAvis.gensim_models
# Scikit-learn
from sklearn.feature_extraction.text import CountVectorizer
# Memastikan paket NLTK yang diperlukan sudah terunduh
# nltk.download('punkt')
# 2. Load dataset
def load_data(file_path):
"""
Memuat data dari file CSV
"""
df = pd.read_csv(file_path, sep=';')
return df
# 3. Preprocessing text
def preprocess_text(text):
"""
Preprocessing teks:
- Mengubah ke lowercase
- Menghapus emoji dan karakter khusus
- Menghapus angka
- Menghapus URL
"""
if isinstance(text, str):
# Lowercase
text = text.lower()
# Hapus URL
text = re.sub(r'https?://\S+|www\.\S+', '', text)
# Hapus emoji dan karakter khusus
text = re.sub(r'[^\w\s]', '', text)
# Hapus angka
text = re.sub(r'\d+', '', text)
# Hapus multiple whitespace
text = re.sub(r'\s+', ' ', text).strip()
return text
return ""
# 4. Stopwords Bahasa Indonesia
def get_stopwords():
"""
Daftar stopwords Bahasa Indonesia
"""
stopwords = [
'ada', 'adalah', 'adanya', 'adapun', 'agak', 'agaknya', 'agar', 'akan', 'akankah', 'akhir',
'akhiri', 'akhirnya', 'aku', 'akulah', 'amat', 'amatlah', 'anda', 'andalah', 'antar', 'antara',
'antaranya', 'apa', 'apaan', 'apabila', 'apakah', 'apalagi', 'apatah', 'artinya', 'asal',
'asalkan', 'atas', 'atau', 'ataukah', 'ataupun', 'awal', 'awalnya', 'bagai', 'bagaikan',
'bagaimana', 'bagaimanakah', 'bagaimanapun', 'bagi', 'bagian', 'bahkan', 'bahwa', 'bahwasanya',
'baik', 'bakal', 'bakalan', 'balik', 'banyak', 'bapak', 'baru', 'bawah', 'beberapa', 'begini',
'beginian', 'beginikah', 'beginilah', 'begitu', 'begitukah', 'begitulah', 'begitupun', 'bekerja',
'belakang', 'belakangan', 'belum', 'belumlah', 'benar', 'benarkah', 'benarlah', 'berada',
'berakhir', 'berakhirlah', 'berakhirnya', 'berapa', 'berapakah', 'berapalah', 'berapapun',
'berarti', 'berawal', 'berbagai', 'berdatangan', 'beri', 'berikan', 'berikut', 'berikutnya',
'berjumlah', 'berkali-kali', 'berkata', 'berkehendak', 'berkeinginan', 'berkenaan', 'berlainan',
'berlalu', 'berlangsung', 'berlebihan', 'bermacam', 'bermacam-macam', 'bermaksud', 'bermula',
'bersama', 'bersama-sama', 'bersiap', 'bersiap-siap', 'bertanya', 'bertanya-tanya', 'berturut',
'berturut-turut', 'bertutur', 'berujar', 'berupa', 'besar', 'betul', 'betulkah', 'biasa',
'biasanya', 'bila', 'bilakah', 'bisa', 'bisakah', 'boleh', 'bolehkah', 'bolehlah', 'buat',
'bukan', 'bukankah', 'bukanlah', 'bukannya', 'bulan', 'bung', 'cara', 'caranya', 'cukup',
'cukupkah', 'cukuplah', 'cuma', 'dahulu', 'dalam', 'dan', 'dapat', 'dari', 'daripada',
'datang', 'dekat', 'demi', 'demikian', 'demikianlah', 'dengan', 'depan', 'di', 'dia',
'diakhiri', 'diakhirinya', 'dialah', 'diantara', 'diantaranya', 'diberi', 'diberikan',
'diberikannya', 'dibuat', 'dibuatnya', 'didapat', 'didatangkan', 'digunakan', 'diibaratkan',
'diibaratkannya', 'diingat', 'diingatkan', 'diinginkan', 'dijawab', 'dijelaskan', 'dijelaskannya',
'dikarenakan', 'dikatakan', 'dikatakannya', 'dikerjakan', 'diketahui', 'diketahuinya',
'dikira', 'dilakukan', 'dilalui', 'dilihat', 'dimaksud', 'dimaksudkan', 'dimaksudkannya',
'dimaksudnya', 'diminta', 'dimintai', 'dimisalkan', 'dimulai', 'dimulailah', 'dimulainya',
'dimungkinkan', 'dini', 'dipastikan', 'diperbuat', 'diperbuatnya', 'dipergunakan',
'diperkirakan', 'diperlihatkan', 'diperlukan', 'diperlukannya', 'dipersoalkan',
'dipertanyakan', 'dipunyai', 'diri', 'dirinya', 'disampaikan', 'disebut', 'disebutkan',
'disebutkannya', 'disini', 'disinilah', 'ditambahkan', 'ditandaskan', 'ditanya', 'ditanyai',
'ditanyakan', 'ditegaskan', 'ditujukan', 'ditunjuk', 'ditunjuki', 'ditunjukkan',
'ditunjukkannya', 'ditunjuknya', 'dituturkan', 'dituturkannya', 'diucapkan', 'diucapkannya',
'diungkapkan', 'dong', 'dua', 'dulu', 'empat', 'enggak', 'enggaknya', 'entah', 'entahlah',
'guna', 'gunakan', 'hal', 'hampir', 'hanya', 'hanyalah', 'hari', 'harus', 'haruslah',
'harusnya', 'hendak', 'hendaklah', 'hendaknya', 'hingga', 'ia', 'ialah', 'ibarat',
'ibaratkan', 'ibaratnya', 'ibu', 'ikut', 'ingat', 'ingat-ingat', 'ingin', 'inginkah',
'inginkan', 'ini', 'inikah', 'inilah', 'itu', 'itukah', 'itulah', 'jadi', 'jadilah',
'jadinya', 'jangan', 'jangankan', 'janganlah', 'jauh', 'jawab', 'jawaban', 'jawabnya',
'jelas', 'jelaskan', 'jelaslah', 'jelasnya', 'jika', 'jikalau', 'juga', 'jumlah',
'jumlahnya', 'justru', 'kala', 'kalau', 'kalaulah', 'kalaupun', 'kalian', 'kami',
'kamilah', 'kamu', 'kamulah', 'kan', 'kapan', 'kapankah', 'kapanpun', 'karena',
'karenanya', 'kasus', 'kata', 'katakan', 'katakanlah', 'katanya', 'ke', 'keadaan',
'kebetulan', 'kecil', 'kedua', 'keduanya', 'keinginan', 'kelamaan', 'kelihatan',
'kelihatannya', 'kelima', 'keluar', 'kembali', 'kemudian', 'kemungkinan', 'kemungkinannya',
'kenapa', 'kepada', 'kepadanya', 'kesamaannya', 'keseluruhan', 'keseluruhannya',
'keterlaluan', 'ketika', 'khususnya', 'kini', 'kinilah', 'kira', 'kira-kira', 'kiranya',
'kita', 'kitalah', 'kok', 'kurang', 'lagi', 'lagian', 'lah', 'lain', 'lainnya', 'lalu',
'lama', 'lamanya', 'lanjut', 'lanjutnya', 'lebih', 'lewat', 'lima', 'luar', 'macam',
'maka', 'makanya', 'makin', 'malah', 'malahan', 'mampu', 'mampukah', 'mana', 'manakala',
'manalagi', 'masa', 'masalah', 'masalahnya', 'masih', 'masihkah', 'masing', 'masing-masing',
'mau', 'maupun', 'melainkan', 'melakukan', 'melalui', 'melihat', 'melihatnya', 'memang',
'memastikan', 'memberi', 'memberikan', 'membuat', 'memerlukan', 'memihak', 'meminta',
'memintakan', 'memisalkan', 'memperbuat', 'mempergunakan', 'memperkirakan', 'memperlihatkan',
'mempersiapkan', 'mempersoalkan', 'mempertanyakan', 'mempunyai', 'memulai', 'memungkinkan',
'menaiki', 'menambahkan', 'menandaskan', 'menanti', 'menanti-nanti', 'menantikan',
'menanya', 'menanyai', 'menanyakan', 'mendapat', 'mendapatkan', 'mendatang', 'mendatangi',
'mendatangkan', 'menegaskan', 'mengakhiri', 'mengapa', 'mengatakan', 'mengatakannya',
'mengenai', 'mengerjakan', 'mengetahui', 'menggunakan', 'menghendaki', 'mengibaratkan',
'mengibaratkannya', 'mengingat', 'mengingatkan', 'menginginkan', 'mengira', 'mengucapkan',
'mengucapkannya', 'mengungkapkan', 'menjadi', 'menjawab', 'menjelaskan', 'menuju',
'menunjuk', 'menunjuki', 'menunjukkan', 'menunjuknya', 'menurut', 'menuturkan',
'menyampaikan', 'menyangkut', 'menyatakan', 'menyebutkan', 'menyeluruh', 'menyiapkan',
'merasa', 'mereka', 'merekalah', 'merupakan', 'meski', 'meskipun', 'meyakini', 'meyakinkan',
'minta', 'mirip', 'misal', 'misalkan', 'misalnya', 'mula', 'mulai', 'mulailah', 'mulanya',
'mungkin', 'mungkinkah', 'nah', 'naik', 'namun', 'nanti', 'nantinya', 'nyaris', 'nyatanya',
'oleh', 'olehnya', 'pada', 'padahal', 'padanya', 'pak', 'paling', 'panjang', 'pantas',
'para', 'pasti', 'pastilah', 'penting', 'pentingnya', 'per', 'percuma', 'perlu', 'perlukah',
'perlunya', 'pernah', 'persoalan', 'pertama', 'pertama-tama', 'pertanyaan', 'pertanyakan',
'pihak', 'pihaknya', 'pukul', 'pula', 'pun', 'punya', 'rasa', 'rasanya', 'rata', 'rupanya',
'saat', 'saatnya', 'saja', 'sajalah', 'saling', 'sama', 'sama-sama', 'sambil', 'sampai',
'sampai-sampai', 'sampaikan', 'sana', 'sangat', 'sangatlah', 'satu', 'saya', 'sayalah',
'se', 'sebab', 'sebabnya', 'sebagai', 'sebagaimana', 'sebagainya', 'sebagian', 'sebaik',
'sebaik-baiknya', 'sebaiknya', 'sebaliknya', 'sebanyak', 'sebegini', 'sebegitu', 'sebelum',
'sebelumnya', 'sebenarnya', 'seberapa', 'sebesar', 'sebetulnya', 'sebisanya', 'sebuah',
'sebut', 'sebutlah', 'sebutnya', 'secara', 'secukupnya', 'sedang', 'sedangkan', 'sedemikian',
'sedikit', 'sedikitnya', 'seenaknya', 'segala', 'segalanya', 'segera', 'seharusnya',
'sehingga', 'seingat', 'sejak', 'sejauh', 'sejenak', 'sejumlah', 'sekadar', 'sekadarnya',
'sekali', 'sekali-kali', 'sekalian', 'sekaligus', 'sekalipun', 'sekarang', 'sekarang',
'sekecil', 'seketika', 'sekiranya', 'sekitar', 'sekitarnya', 'sekurang-kurangnya',
'sekurangnya', 'sela', 'selain', 'selaku', 'selalu', 'selama', 'selama-lamanya',
'selamanya', 'selanjutnya', 'seluruh', 'seluruhnya', 'semacam', 'semakin', 'semampu',
'semampunya', 'semasa', 'semasih', 'semata', 'semata-mata', 'semaunya', 'sementara',
'semisal', 'semisalnya', 'sempat', 'semua', 'semuanya', 'semula', 'sendiri', 'sendirian',
'sendirinya', 'seolah', 'seolah-olah', 'seorang', 'sepanjang', 'sepantasnya', 'sepantasnyalah',
'seperlunya', 'seperti', 'sepertinya', 'sepihak', 'sering', 'seringnya', 'serta',
'serupa', 'sesaat', 'sesama', 'sesampai', 'sesegera', 'sesekali', 'seseorang',
'sesuatu', 'sesuatunya', 'sesudah', 'sesudahnya', 'setelah', 'setempat', 'setengah',
'seterusnya', 'setiap', 'setiba', 'setibanya', 'setidak-tidaknya', 'setidaknya',
'setinggi', 'seusai', 'sewaktu', 'siap', 'siapa', 'siapakah', 'siapapun', 'sini',
'sinilah', 'soal', 'soalnya', 'suatu', 'sudah', 'sudahkah', 'sudahlah', 'supaya',
'tadi', 'tadinya', 'tahu', 'tahun', 'tak', 'tambah', 'tambahnya', 'tampak', 'tampaknya',
'tandas', 'tandasnya', 'tanpa', 'tanya', 'tanyakan', 'tanyanya', 'tapi', 'tegas',
'tegasnya', 'telah', 'tempat', 'tengah', 'tentang', 'tentu', 'tentulah', 'tentunya',
'tepat', 'terakhir', 'terasa', 'terbanyak', 'terdahulu', 'terdapat', 'terdiri',
'terhadap', 'terhadapnya', 'teringat', 'teringat-ingat', 'terjadi', 'terjadilah',
'terjadinya', 'terkira', 'terlalu', 'terlebih', 'terlihat', 'termasuk', 'ternyata',
'tersampaikan', 'tersebut', 'tersebutlah', 'tertentu', 'tertuju', 'terus', 'terutama',
'tetap', 'tetapi', 'tiap', 'tiba', 'tiba-tiba', 'tidak', 'tidakkah', 'tidaklah',
'tiga', 'tinggi', 'toh', 'tunjuk', 'turut', 'tutur', 'tuturnya', 'ucap', 'ucapnya',
'ujar', 'ujarnya', 'umum', 'umumnya', 'ungkap', 'ungkapnya', 'untuk', 'usah',
'usai', 'waduh', 'wah', 'wahai', 'waktu', 'waktunya', 'walau', 'walaupun', 'wong',
'yaitu', 'yakin', 'yakni', 'yang', 'yg'
]
# Tambahkan stopwords khusus untuk dataset (dari analisis awal)
additional_stopwords = ['ya', 'nya', 'yg', 'aja', 'gw', 'ga', 'udah', 'kek', 'gak', 'nya',
'nih', 'sih', 'kalo', 'eh', 'aku', 'kau', 'lo', 'lu', 'kan', 'kok',
'juga', 'udh', 'eh', 'ah', 'kk', 'wkwk', 'wkwkwk', 'haha', 'hahaha',
'bang', 'banget', 'emang']
stopwords.extend(additional_stopwords)
return set(stopwords)
# 5. Stemming
def get_stemmer():
"""
Mendapatkan stemmer bahasa Indonesia dari Sastrawi
"""
factory = StemmerFactory()
return factory.create_stemmer()
# 6. Preprocessing langkah-langkah
def preprocess_data(df, text_column):
"""
Preprocessing data teks
"""
# Preprocessing teks
df['clean_text'] = df[text_column].apply(preprocess_text)
# Tokenisasi
df['tokens'] = df['clean_text'].apply(word_tokenize)
# Hapus stopwords
stopwords = get_stopwords()
df['tokens_without_stopwords'] = df['tokens'].apply(
lambda tokens: [word for word in tokens if word not in stopwords and len(word) > 2]
)
# Stemming
stemmer = get_stemmer()
df['stemmed_tokens'] = df['tokens_without_stopwords'].apply(
lambda tokens: [stemmer.stem(word) for word in tokens]
)
return df
# 7. Membuat korpus untuk LDA
def create_lda_corpus(df, tokens_column='stemmed_tokens'):
"""
Membuat korpus untuk LDA:
- Dictionary
- Bag of Words corpus
"""
# Buat dictionary
id2word = corpora.Dictionary(df[tokens_column])
# Buat corpus
corpus = [id2word.doc2bow(text) for text in df[tokens_column]]
return corpus, id2word
# 8. Membuat model LDA
def create_lda_model(corpus, id2word, num_topics=5, passes=10):
"""
Membuat model LDA
"""
lda_model = gensim.models.ldamodel.LdaModel(
corpus=corpus,
id2word=id2word,
num_topics=num_topics,
random_state=42,
passes=passes,
alpha='auto',
eta='auto'
)
return lda_model
# 9. Mengevaluasi model dengan coherence score
def compute_coherence_score(model, corpus, texts, dictionary):
"""
Menghitung coherence score
"""
coherence_model = CoherenceModel(
model=model,
texts=texts,
dictionary=dictionary,
coherence='c_v'
)
return coherence_model.get_coherence()
# 10. Mencari jumlah topik optimal
def find_optimal_topics(corpus, id2word, texts, start=2, limit=10, step=1):
"""
Mencari jumlah topik optimal berdasarkan coherence score
"""
coherence_values = []
model_list = []
for num_topics in range(start, limit, step):
model = create_lda_model(corpus=corpus, id2word=id2word, num_topics=num_topics)
model_list.append(model)
coherence_model = CoherenceModel(
model=model,
texts=texts,
dictionary=id2word,
coherence='c_v'
)
coherence_values.append(coherence_model.get_coherence())
# Plot coherence score
plt.figure(figsize=(12, 6))
plt.plot(range(start, limit, step), coherence_values)
plt.xlabel("Jumlah Topik")
plt.ylabel("Coherence Score")
plt.title("Coherence Score untuk Berbagai Jumlah Topik")
plt.grid(True)
plt.tight_layout()
plt.savefig('coherence_score.png')
# Temukan indeks dengan coherence score tertinggi
max_index = coherence_values.index(max(coherence_values))
optimal_topics = range(start, limit, step)[max_index]
return model_list[max_index], optimal_topics, coherence_values, 'coherence_score.png'
# 11. Visualisasi model LDA
def visualize_lda(lda_model, corpus, id2word):
"""
Visualisasi model LDA dengan pyLDAvis
"""
vis = pyLDAvis.gensim_models.prepare(lda_model, corpus, id2word)
pyLDAvis.save_html(vis, 'lda_visualization.html')
return 'lda_visualization.html'
# 12. Format hasil model
def format_topics_sentences(ldamodel, corpus, texts):
"""
Format hasil topic modeling
"""
# Init output - buat list untuk menampung data
topics_data = []
# Get main topic in each document
for i, row in enumerate(ldamodel[corpus]):
row = sorted(row, key=lambda x: (x[1]), reverse=True)
# Get the Dominant topic, Perc Contribution and Keywords for each document
for j, (topic_num, prop_topic) in enumerate(row):
if j == 0: # => dominant topic
wp = ldamodel.show_topic(topic_num)
topic_keywords = ", ".join([word for word, prop in wp])
# Simpan data dalam list
topics_data.append((int(topic_num), round(prop_topic, 4), topic_keywords))
else:
break
# Buat DataFrame sekaligus dari list data
sent_topics_df = pd.DataFrame(topics_data, columns=['Dominant_Topic', 'Perc_Contribution', 'Topic_Keywords'])
# Tambahkan teks asli
contents = pd.Series(texts)
sent_topics_df = pd.concat([sent_topics_df, contents], axis=1)
return sent_topics_df
# 13. Fungsi untuk menyimpan dan memuat hasil processing
def save_results(results, output_dir='output'):
"""
Menyimpan semua hasil processing ke dalam file CSV dan model
"""
import os
# Buat direktori output jika belum ada
if not os.path.exists(output_dir):
os.makedirs(output_dir)
# Simpan model LDA, dictionary, dan corpus
results['model'].save(os.path.join(output_dir, 'lda_model'))
results['id2word'].save(os.path.join(output_dir, 'id2word.dictionary'))
corpora.MmCorpus.serialize(os.path.join(output_dir, 'corpus.mm'), results['corpus'])
# Simpan dataframe hasil ke CSV
results['df_topic_keywords'].to_csv(os.path.join(output_dir, 'topic_keywords.csv'), index=False)
# Simpan informasi coherence score
coherence_df = pd.DataFrame({
'num_topics': list(range(2, 2 + len(results['coherence_values']))),
'coherence_score': results['coherence_values']
})
coherence_df.to_csv(os.path.join(output_dir, 'coherence_scores.csv'), index=False)
# Simpan dataframe preprocessing jika tersedia
if 'df_processed' in results:
results['df_processed'].to_csv(os.path.join(output_dir, 'preprocessed_data.csv'), index=False)
print(f"Semua hasil telah disimpan di direktori: {output_dir}")
return output_dir
def load_results(output_dir='output'):
"""
Memuat hasil yang telah disimpan sebelumnya
"""
import os
results = {}
# Muat model LDA, dictionary, dan corpus
if os.path.exists(os.path.join(output_dir, 'lda_model')):
results['model'] = gensim.models.ldamodel.LdaModel.load(os.path.join(output_dir, 'lda_model'))
if os.path.exists(os.path.join(output_dir, 'id2word.dictionary')):
results['id2word'] = corpora.Dictionary.load(os.path.join(output_dir, 'id2word.dictionary'))
if os.path.exists(os.path.join(output_dir, 'corpus.mm')):
results['corpus'] = corpora.MmCorpus(os.path.join(output_dir, 'corpus.mm'))
# Muat dataframe hasil
if os.path.exists(os.path.join(output_dir, 'topic_keywords.csv')):
results['df_topic_keywords'] = pd.read_csv(os.path.join(output_dir, 'topic_keywords.csv'))
# Muat informasi coherence score
if os.path.exists(os.path.join(output_dir, 'coherence_scores.csv')):
coherence_df = pd.read_csv(os.path.join(output_dir, 'coherence_scores.csv'))
results['coherence_values'] = coherence_df['coherence_score'].tolist()
results['optimal_topics'] = coherence_df.loc[coherence_df['coherence_score'].idxmax(), 'num_topics']
# Muat dataframe preprocessing
if os.path.exists(os.path.join(output_dir, 'preprocessed_data.csv')):
results['df_processed'] = pd.read_csv(os.path.join(output_dir, 'preprocessed_data.csv'))
# Rekonstruksi kolom list dari string
if 'tokens' in results['df_processed'].columns:
results['df_processed']['tokens'] = results['df_processed']['tokens'].apply(
lambda x: eval(x) if isinstance(x, str) else []
)
if 'tokens_without_stopwords' in results['df_processed'].columns:
results['df_processed']['tokens_without_stopwords'] = results['df_processed']['tokens_without_stopwords'].apply(
lambda x: eval(x) if isinstance(x, str) else []
)
if 'stemmed_tokens' in results['df_processed'].columns:
results['df_processed']['stemmed_tokens'] = results['df_processed']['stemmed_tokens'].apply(
lambda x: eval(x) if isinstance(x, str) else []
)
print(f"Hasil berhasil dimuat dari direktori: {output_dir}")
return results
def run_topic_modeling(file_path, text_column='text', save_intermediates=True, output_dir='output'):
"""
Menjalankan topic modeling
"""
print("Loading data...")
df = load_data(file_path)
print("Preprocessing data...")
df_processed = preprocess_data(df, text_column)
# Simpan hasil preprocessing jika diminta
if save_intermediates:
import os
if not os.path.exists(output_dir):
os.makedirs(output_dir)
# Konversi kolom list menjadi string untuk disimpan ke CSV
df_to_save = df_processed.copy()
for col in ['tokens', 'tokens_without_stopwords', 'stemmed_tokens']:
if col in df_to_save.columns:
df_to_save[col] = df_to_save[col].apply(str)
df_to_save.to_csv(os.path.join(output_dir, 'preprocessed_data.csv'), index=False)
print(f"Data preprocessing disimpan di {os.path.join(output_dir, 'preprocessed_data.csv')}")
print("Creating corpus...")
corpus, id2word = create_lda_corpus(df_processed)
# Simpan corpus dan dictionary jika diminta
if save_intermediates:
import os
if not os.path.exists(output_dir):
os.makedirs(output_dir)
id2word.save(os.path.join(output_dir, 'id2word.dictionary'))
corpora.MmCorpus.serialize(os.path.join(output_dir, 'corpus.mm'), corpus)
print(f"Corpus dan dictionary disimpan di direktori {output_dir}")
print("Finding optimal number of topics...")
best_model, optimal_topics, coherence_values, coherence_plot = find_optimal_topics(
corpus=corpus,
id2word=id2word,
texts=df_processed['stemmed_tokens']
)
print(f"Optimal number of topics: {optimal_topics}")
print(f"Best coherence score: {max(coherence_values)}")
# Simpan model jika diminta
if save_intermediates:
import os
if not os.path.exists(output_dir):
os.makedirs(output_dir)
best_model.save(os.path.join(output_dir, 'lda_model'))
# Simpan coherence scores
coherence_df = pd.DataFrame({
'num_topics': list(range(2, 2 + len(coherence_values))),
'coherence_score': coherence_values
})
coherence_df.to_csv(os.path.join(output_dir, 'coherence_scores.csv'), index=False)
print(f"Model LDA dan coherence scores disimpan di direktori {output_dir}")
print("Visualizing LDA model...")
vis_path = visualize_lda(best_model, corpus, id2word)
print("Topics and their keywords:")
topics = best_model.print_topics()
pprint(topics)
# Simpan topik dan kata kunci ke CSV
if save_intermediates:
import os
if not os.path.exists(output_dir):
os.makedirs(output_dir)
topics_df = pd.DataFrame({
'topic_id': [i for i, _ in topics],
'keywords': [keywords for _, keywords in topics]
})
topics_df.to_csv(os.path.join(output_dir, 'topics_keywords.csv'), index=False)
print(f"Topik dan kata kunci disimpan di {os.path.join(output_dir, 'topics_keywords.csv')}")
# Format hasil
df_topic_sents_keywords = format_topics_sentences(
ldamodel=best_model,
corpus=corpus,
texts=df_processed['clean_text']
)
# Dominant topic distribution
df_dominant_topic = df_topic_sents_keywords.reset_index()
df_dominant_topic.columns = ['Document_No', 'Dominant_Topic', 'Topic_Perc_Contrib', 'Keywords', 'Text']
# Simpan hasil pemetaan dokumen ke topik
if save_intermediates:
df_dominant_topic.to_csv(os.path.join(output_dir, 'document_topics.csv'), index=False)
print(f"Pemetaan dokumen ke topik disimpan di {os.path.join(output_dir, 'document_topics.csv')}")
print("\nDominant Topic Distribution:")
topic_counts = df_dominant_topic['Dominant_Topic'].value_counts().reset_index()
topic_counts.columns = ['Topic_Num', 'Count']
print(topic_counts)
# Simpan distribusi topik
if save_intermediates:
topic_counts.to_csv(os.path.join(output_dir, 'topic_distribution.csv'), index=False)
print(f"Distribusi topik disimpan di {os.path.join(output_dir, 'topic_distribution.csv')}")
# Plot distribusi topik
plt.figure(figsize=(10, 6))
plt.bar(topic_counts['Topic_Num'], topic_counts['Count'])
plt.xlabel('Topic Number')
plt.ylabel('Count')
plt.title('Distribution of Dominant Topics')
plt.xticks(topic_counts['Topic_Num'])
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig(os.path.join(output_dir, 'topic_distribution.png'))
results = {
'model': best_model,
'corpus': corpus,
'id2word': id2word,
'optimal_topics': optimal_topics,
'coherence_values': coherence_values,
'coherence_plot': coherence_plot,
'visualization': vis_path,
'topic_distribution': os.path.join(output_dir, 'topic_distribution.png'),
'df_topic_keywords': df_dominant_topic,
'df_processed': df_processed
}
print(f"\nSemua hasil telah disimpan di direktori: {output_dir}")
return results
if __name__ == "__main__":
# Ganti dengan path file CSV yang sesuai
results = run_topic_modeling("./src/review.csv", output_dir='./src/lda_output')
print("Topic modeling completed successfully!")
# Contoh cara memuat kembali hasil yang sudah disimpan
# loaded_results = load_results('lda_output')
# print(f"Loaded model with {loaded_results['optimal_topics']} topics")