Analisis Klasifikasi Komentar Hate Speech Pada Media Sosial Instagram Menggunakan Algoritma Random Forest dengan Seleksi Fitur Chi Square

Amalia Rachmadana Ismail
12 min readJun 13, 2024

--

sumber

Hai Data Enthusiast!

Kali ini kita akan membahas project machine learning yang pernah saya kerjakan yaitu analisis klasifikasi komentar hate speech menggunakan algoritma Random Forest dengan seleksi fitur chi square di platform Google Colab.

Introduction

Teknologi merupakan bidang yang mengalami perkembangan pesat. Selalu ada penemuan-penemuan baru yang dikembangkan oleh para teknologi setiap tahunnya. Salah satu kemajuan teknologi yang membantu komunikasi jarak jauh adalah munculnya media sosial. Platform media sosial memungkinkan pengguna untuk secara terbuka dan bebas bertukar ide dan informasi dengan orang-orang terdekat dan jauh melalui kekuatan internet. Meskipun media sosial dikembangkan dengan tujuan untuk memberikan kemudahan hidup manusia dan hal-hal baik lainnya, namun tidak dapat dipungkiri bahwa setiap perubahan yang terjadi pada manusia juga mempunyai sisi negatif (Harish, Faraby, & Dwifebri, 2021).

Problem Statement

Penyebaran ujaran kebencian dan kata-kata kasar melalui media sosial hanyalah sebagian kecil dari sisi negatif yang bisa terjadi. Meskipun pelanggaran dan penyalahgunaan media sosial diatur oleh undang-undang, tidak semua orang mengetahui atau mematuhi aturan tersebut. Pengguna sosial media seringkali tidak menyadari bahwa komentar mereka dapat mengandung hate speech yang dapat ditindak secara hukum.

Dataset

Pengambilan data dilakukan dengan metode crawling data menggunakan fitur phantombuster yaitu Phantom Instagram Post Commenters Export. Dimana dataset yang digunakan adalah 100 komentar pada tiap 50 postingan terakhir akun Instagram @lambe_turah sejak tanggal 18 agustus 2023, dan diperoleh sebanyak 4.916 komentar. (unduh dataset)

sampel data

Labelling

Data dikategorikan menjadi dua kelas yaitu ‘hate speech’ dan ‘bukan hate speech’ berdasarkan Surat Edaran Kapolri Nomor SE/6/X/2015 dengan ketentuan sebagai berikut.

(1) Penghinaan, pencemaran nama baik, penistaan, perbuatan tidak menyenangkan, memprovokasi, menghasut, dan penyebaran berita bohong. (2) Memiliki tujuan atau bisa berdampak pada tindak diskriminasi, kekerasan, penghilangan nyawa, dan/atau konflik sosial. (3) Menghasut dan menyulut kebencian terhadap individu dan/atau kelompok Masyarakat dalam berbagai komunitas dari aspek suku, agama, aliran kewarganegaraan, keyakinan/kepercayaan, ras, antargolongan, warna kulit, etnis, gender, kaum difabel (cacat), dan orientasi seksual.

Kemudian mengubah nilai dalam kolom label dari teks menjadi bentuk numerik menggunakan library LabelEncoder.

from sklearn.preprocessing import LabelEncoder

# Membuat objek LabelEncoder
label_encoder = LabelEncoder()

# Mengubah fitur label menjadi numerik
data['label'] = label_encoder.fit_transform(data['kategori'])
data setelah labelling

Komentar diberi label 0 untuk kategori ‘bukan hate speech’ dan diberi label 1 untuk kategori ‘hate speech’, diperoleh jumlah komentar pada kategori ‘bukan hate speech’ sebanyak 2.464 komentar dan kategori ‘hate speech’ sebanyak 2.270 komentar.

# Plot klasifikasi
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(8,4))
data.groupby('kategori').kategori.count().plot.bar(ylim=0)
plt.xticks(rotation=0)

for i in range(len(data.groupby('kategori').kategori.count())):
plt.text(i, data.groupby('kategori').kategori.count()[i],
data.groupby('kategori').kategori.count()[i], ha = 'center',
va = 'bottom')
grafik diagram batang data

Text Preprocessing

Remove Punctuation

Remove punctuation merupakan suatu proses yang dilakukan untuk menghapus karakter non-alphabet seperti simbol, angka, tanda baca, url, dan spasi ekstra dalam suatu teks karena tidak memiliki Informasi penting.

import re
def punctuation(text):
text = re.sub(r'https?://\S+|www\.\S+', '', text)
text = re.sub(r'[-+]?[0-9]+', '',text)
text = re.sub(r'[^\w\s]', '',text)
text = text.strip()
return text

data['x'] = data['x'].apply(lambda x: punctuation(x))
data['x'].head()
data hasil remove punctuation

Case Folding

Case folding merupakan suatu proses yang dilakukan untuk mengubah seluruh karakter huruf ke dalam bentuk huruf kecil atau lowercase dalam suatu teks agar lebih standar dan sesuai.

import re
def casefolding(text):
text = text.lower()
return text

data['x'] = data['x'].apply(lambda x: casefolding(x))
data['x'].head()
data hasil case folding

Normalization

Normalization merupakan suatu proses yang dilakukan untuk melakukan normalisasi kata dalam suatu teks. Tujuan normalization adalah mengubah kata tidak baku atau non-formal dalam teks menjadi kata baku atau formal untuk menyeragamkan bentuk kata.

key_norm =pd.read_csv("key_norm.csv")
def text_normalize(text):
text = ' '.join([key_norm[key_norm['singkat']== word]['hasil'].values[0]
if (key_norm['singkat']==word).any()
else word for word in text.split()
])
text =str.lower(text)
return text

data['x'] = data['x'].apply(lambda x: text_normalize(x))
data['x'].head()
data hasil normalization

Tokenizing

Tokenizing merupakan suatu proses yang dilakukan untuk memisahkan teks menjadi kata atau token dalam suatu teks agar mudah dipahami oleh komputer.

from nltk.tokenize import sent_tokenize, word_tokenize

data['x'] = data['x'].apply(lambda x: word_tokenize(x))
data['x'].head()
data hasil tokenizing

Stopword Removal

Stopword Removal merupakan suatu proses yang dilakukan untuk membersihkan kata-kata yang tidak berpengaruh pada proses analisis.

from nltk.corpus import stopwords
stopwords_ind = stopwords.words("indonesian")
stopwords_ind.remove("tidak")
stopwords_ind.remove("enggak")

#Menambahkan kata dalam kamus stopword
more_stopword = ['tsel','gb','rb','btw']
stopwords_ind = stopwords_ind + more_stopword

def remove_stop_word(text):
clean_words =[]
text = text.split()
for word in text:
if word not in stopwords_ind:
clean_words.append(word)
return " ".join(clean_words)
data hasil stopword removal

Lemmatization

Lemmatization merupakan suatu proses yang dilakukan untuk mengubah kata-kata menjadi bentuk kata dasar dengan cara mengidentifikasi akar kata yang sesuai dengan kamus yang digunakan.

import nltk
from nltk.stem import WordNetLemmatizer
nltk.download('wordnet')
lemmatizer = WordNetLemmatizer()

def lemmatize_text(text):
tokens = nltk.word_tokenize(text)
lemmatized_tokens = [lemmatizer.lemmatize(token) for token in tokens]
return ' '.join(lemmatized_tokens)
data hasil lemmatization

Setelah semua function text preprocessing dibentuk, selanjutnya menggabungkan seluruh function dalam satu function yaitu text_preprocessing_process.

#Mendefinisikan function untuk seluruh proses Text Preprocessing
def text_preprocessing_process(text):
# Remove punctuation
text = punctuation(text)

# Lowercase the text
text = casefolding(text)

#Text Normalization
text = text_normalize(text)

# Tokenize the text
tokens = word_tokenize(text)

# Remove stopwords
stop_words = set(stopwords.words('indonesian'))
stop_words.remove("tidak")
stop_words.remove("enggak")
tokens = [word for word in tokens if word not in stop_words]

# Lemmatize the tokens
lemmatizer = WordNetLemmatizer()
tokens = [lemmatizer.lemmatize(word) for word in tokens]

# Join the tokens back into a single string
text = ' '.join(tokens)

return text

Setelah Text Preprocessing

Setelah melalui text preprocessing data menjadi lebih terstruktur dibandingkan data sebelumnya. Data komentar juga telah dibagi dalam dua kategori yaitu ‘hate speech’ dan ‘bukan hate speech’. Komentar dengan kelas ‘hate speech’ diberi label 1, sedangkan komentar dengan kelas bukan ‘hate speech’ diberi label 0.

data setelah text preprocessing

Data setelah text preprocessing lebih mudah dipahami oleh komputer sehingga data tersebut sudah siap digunakan untuk dilakukan analisis lebih lanjut.

Pembobotan Kata TF-IDF

Data yang telah melalui tahapan text preprocessing akan dibagi menjadi beberapa bagian kata dengan gabungan pembentukan fitur dari unigram (N=1) dan bigram (N=2). Pecahan kata tersebut menghasilkan fitur-fitur yang diperlukan dalam klasifikasi data teks. Fitur atau kata yang dihasilkan dengan teknik kombinasi unigram dan bigram kemudian akan dihitung bobot nya dengan metode Term Frequency-Inverse Document Frequency (TF-IDF). Fitur yang diperoleh akan ditransformasi menjadi sekumpulan angka yang biasa disebut vektor. Pembobotan kata dilakukan untuk mengetahui seberapa penting sebuah kata dalam kumpulan komentar.

sampel komentar untuk pembobotan kata

Term Frequency (TF)

Langkah pertama yaitu mencari nilai Term Frequency (TF). TF dilakukan untuk menghitung frekuensi kemunculan sebuah kata (term) pada komentar. Semakin banyak kata yang muncul menunjukkan semakin penting kata tersebut. Jenis Term Frequency (TF) yang digunakan pada penelitian ini yaitu jenis raw count atau Term Frequency murni. Raw count adalah teknik menghitung frekuensi kata berdasarkan kemunculan kata pada sebuah komentar.

rumus nilai term frequency (TF)
sampel perhitungan nilai TF

Sebagai contoh, pada komentar ke-281 yang berbunyi “greget banget banget ketok ya barang alay banget norak” terlihat kata ‘banget’ memiliki nilai 3 yang berarti terdapat 3 kata (term) ‘banget’ dalam komentar ke-281.

Inverse Document Frequency (IDF)

Langkah kedua yaitu mencari nilai Inverse Document Frequency (IDF). IDF dilakukan untuk menghitung nilai seberapa penting sebuah kata pada komentar.

rumus nilai inverse document frequency (IDF)

𝐼𝐷𝐹𝑗 : Inverse document frequency dari term j

𝐷 : Total dokumen

𝑑𝑓𝑗 : Total dokumen dari term j

Sebagai contoh ingin menghitung nilai IDF kata ‘banget’. Pada total 4917 komentar, diketahui jumlah komentar yang mengandung kata ‘banget’ sebanyak 645 komentar. Sehingga untuk menghitung nilai IDF kata ‘banget’ digunakan perhitungan sebagai berikut.

menghitung nilai IDF kata ‘banget’
sampel perhitungan nilai IDF

Term Frequency — Inverse Document Frequency (TF — IDF)

Langkah ketiga yaitu mencari nilai Term Frequency-Inverse Document Frequency (TF-IDF). TF-IDF dilakukan untuk menghitung nilai seberapa penting sebuah kata (term) pada komentar dengan mengalikan nilai TF dan IDF.

rumus nilai term frequency-inverse document frequency (TF-IDF)

𝑊𝑖𝑗 : Bobot dari term j terhadap dokumen i

𝑇𝐹𝑖𝑗 : Frekuensi munculnya term j di dalam dokumen i

𝐷 : Total dokumen

𝑑𝑓𝑗 : Total dokumen dari term

terlihat bahwa berapapun nilai dari 𝑇𝐹𝑖𝑗 akan bernilai 0 jika nilai 𝐷=𝑑𝑓𝑗, maka ditambahkan nilai 1 pada sisi IDF agar menghindari nilai 𝑊𝑖𝑗 tidak menjadi 0.

rumus nilai term frequency-inverse document frequency (TF-IDF)

Sebagai contoh ingin menghitung nilai TF-IDF kata ‘banget’ pada komentar ke-265. Pada perhitungan TF sebelumnya diperoleh nilai TF kata’banget’ pada komentar ke-265 sebesar 2, sedangkan untuk perhitungan IDF kata ’banget’ sebesar 2.0310. Sehingga perhitungan akhir pembobotan TF-IDF kata ‘banget’ pada komentar ke-265 adalah sebagai berikut.

menghitung nilai TF-IDF kata ‘banget’ pada komentar ke-265
sampel perhitungan nilai TF-IDF
# Save Model
import pickle

#TF-IDF
from sklearn.feature_extraction.text import TfidfVectorizer

#Unigram dan bigram
vec_TF_IDF = TfidfVectorizer(ngram_range=(1,2))
vec_TF_IDF.fit(x)

x_tf_idf =vec_TF_IDF.transform(x)
pickle.dump(vec_TF_IDF.vocabulary_,open("feature_tf-idf.sav", "wb"))

Konversi matriks TF-IDF menjadi sebuah DataFrame pandas. Ini memungkinkan representasi data teks dalam bentuk tabel tabular yang dapat lebih mudah dipahami dan diolah dalam analisis data.

#Mengubah teks menjadi representasi numerik menggunakan metode TF-IDF
x1 = vec_TF_IDF.transform(x).toarray()
data_tabular_tf_idf =pd.DataFrame(x1,columns=vec_TF_IDF.get_feature_names_out())

#Data TF-IDF diubah menjadi array untuk melanjutkan pengolahan data dengan ML
x_train =np.array(data_tabular_tf_idf)
y_train =np.array(y)

Seleksi Fitur Chi Square

Seleksi fitur adalah proses pemilihan fitur yang relevan dengan tujuan mendapatkan fitur yang optimal dan mengurangi dimensi data. Dari ribuan fitur yang telah didapat, seringkali terdapat sejumlah fitur yang tidak informatif karena tidak relevan dengan kelas yang dicari, sehingga penghapusan fitur yang tidak relevan dan berlebihan ini dapat meningkatkan kinerja klasifikasi (Irfan, Widiyanto, & Jayanti, 2022).

Pada project kali ini, akan digunakan seleksi fitur chi-square untuk memilih fitur atau kata terbaik berdasarkan skor chi square.

#Seleksi fitur menggunakan metode Chi-Square
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2

chi2_features =SelectKBest(chi2)
x_kbest_features =chi2_features.fit_transform(x_train, y_train)

print("Original Feature Number : ", x_train.shape[1])
print("Reduced Feature Number: ",x_kbest_features.shape[1])
#Membuat DataFrame dari skor Chi-Square untuk setiap fitur
Data = pd.DataFrame(chi2_features.scores_, columns=['Nilai'])

#Menggabungkan informasi skor dan nama fitur
feature =vec_TF_IDF.get_feature_names_out()
Data['Fitur'] = feature

#Boolean mask menunjukkan fitur yang dipilih berdasarkan skor Chi-Square
mask =chi2_features.get_support()

#Menampilkan fitur yang terpilih berdasarkan mask atau nilai tertinggi
new_feature=[]
for bool, f in zip(mask, feature):
if bool :
new_feature.append(f)
selected_feature=new_feature

#Membuat vocabulary baru berdasarkan fitur yang terseleksi
new_selected_feature = {}
for (k,v) in vec_TF_IDF.vocabulary_.items():
if k in selected_feature:
new_selected_feature[k]=v

#Menyimpan fitur yang dipilih
pickle.dump(new_selected_feature,open("new_selected_feature_tf-idf.sav", "wb"))

Bagaimana perhitungan manual seleksi fitur Chi-Square?

rumus chi square

𝑡 : Fitur atau kata

𝑐 : Kelas atau kategori

𝑁 : Jumlah seluruh dokumen

𝐴 : Jumlah banyaknya dokumen pada kategori (𝑐) yang memuat (𝑡)

𝐵 : Jumlah banyaknya dokumen bukan kategori (𝑐) yang memuat (𝑡)

𝐶 : Jumlah banyaknya dokumen pada kategori yang tidak memuat (𝑡)

𝐷 : Jumlah banyaknya dokumen bukan kategori yang tidak memuat (𝑡)

Sebagai contoh akan dilakukan perhitungan manual nilai chi square untuk kata ‘anjing’ pada 13 sampel data komentar yang terdiri dari 8 kategori ‘hate speech’ dan 5 kategori ‘bukan hate speech’.

sampel komentar untuk seleksi fitur chi square

Sampel komentar di atas dibentuk ke dalam tabel kontingensi untuk mempermudah proses perhitungan nilai chi square kata ‘anjing’ secara manual.

tabel kontingensi sampel komentar
nilai chi square kata ‘anjing’ pada sampel data

Bagaimana seleksi fitur Chi Square bekerja?

Seleksi fitur chi square bekerja dengan membandingkan nilai chi square yang telah dihitung dengan nilai p-value chi square yang sesuai dengan tingkat signifikansi. Dimana digunakan tingkat signifikansi 15% serta uji hipotesis H0 yaitu fitur dalam dokumen tidak memiliki hubungan yang signifikan dengan kategori kelas.

sampel data untuk keputusan uji chi square
sampel data kesimpulan untuk uji chi square

Setelah melakukan uji hipotesis nilai chi square pada setiap fitur, diperoleh jumlah fitur dalam dokumen yang memiki hubungawhan signifikan kategori kelas sebanyak 276 fitur.

Pembagian Data Training dan Data Testing

Perbandingan antara pembagian data training dan data testing adalah 80%:20% dari total data.

from sklearn.model_selection import train_test_split

x =x_kbest_features
y =data.label
x_train, x_test, y_train, y_test = train_test_split(x,y, test_size=0.2, random_state=0)
pembagian data training dan data testing

Klasifikasi Random Forest

Akan digunakan model machine learning untuk mengklasifikasikan komentar ke dalam kategori ‘hate speech’ dan ‘bukan hate speech’ berdasarkan 276 fitur yang telah diambil dari data komentar, dengan model klasifikasi pada penelitian ini menggunakan algoritma random forest.

#Inisiasi model random forest
import random
from sklearn.ensemble import RandomForestClassifier
text_algorithm = RandomForestClassifier()
model =text_algorithm.fit(x_train, y_train)

#Test Model
from sklearn.metrics import classification_report, confusion_matrix, accuracy_score
predicted =model.predict(x_test)

#Confusion Matrix
CM =confusion_matrix(y_test, predicted)
print(confusion_matrix(y_test,predicted))
print(classification_report(y_test, predicted))
print(accuracy_score(y_test, predicted))

# Menyimpan model
pickle.dump(model,open("model_fraud_chi2.sav", "wb"))

Model random forest yang terbentuk akan diukur kinerja model klasifikasi menggunakan confusion matrix untuk mendapatkan nilai akurasi, precision, recall, dan f1 score.

confusion matrix data testing model random forest
evaluasi kinerja model random forest

Berdasarkan metrik-metrik tersebut, model random forest memberikan hasil yang baik dalam mengklasifikasikan data menjadi kelas ‘bukan hate speech’ dan ‘hate speech’. Nilai accuracy yang tinggi disertai nilai precision, recall, dan f1-score yang cukup seimbang antara kedua kelas menunjukkan bahwa model ini memiliki kinerja yang baik dalam tugas klasifikasi yang diberikan.

Selanjutnya akan dilakukan proses klasifikasi menggunakan metode random forest, kemudian diberikan sampel visualisasi pohon random forest dalam estimator pohon keputusan ke-14 dengan membatasi jumlah sampel dan fitur dalam data train dan data test menjadi 100 sampel dengan 100 fitur serta kedalaman maksimum pohon keputusan sebesar 5.

visualisasi sampel pohon random forest

sampel visualisasi pohon random forest yang memiliki banyak data sebanyak 100. Diperoleh hasil pohon random forest pada root node yaitu fitur ’ngomong ngomong’ dengan skor ≤0.044 yang merupakan aturan pemisahan node. Nilai Gini pada node ini sebesar 0.484 menunjukkan tingkat kemurnian yang cukup tinggi dalam node. Samples sebesar 63 yang menunjukkan keseluruhan jumlah sampel yang mencapai node tersebut adalah 63. Namun, distribusi kelas pada simpul tersebut adalah [41,59] yang menunjukkan bahwa dari 63 sampel tersebut, 41 termasuk dalam kelas “hate speech” dan 59 termasuk dalam kelas ”bukan hate speech”. Dalam melakukan pemisahan node, apabila sampel tidak memenuhi kondisi fitur ’ngomong ngomong’ ≤0.044, maka sampel akan masuk ke node “bukan hate speech”. Namun jika sampel memenuhi kondisi fitur ’ ngomong ngomong’ ≤0.044 maka akan masuk ke kelas “bukan hate speech” kemudian lanjut ke decision node selanjutnya yaitu fitur ’ng*we’. Split node akan terus dilakukan berulang-ulang pada fitur-fitur terlampir lainnya.

Prediksi Data

Selanjutnya, mari kita coba inputkan contoh teks baru untuk dideteksi apakah terindikasi hate speech atau tidak untuk mencoba keakuratan model. Sebagai contoh disini saya menginputkan kalimat “anjing lucu banget”.

data_input =("anjing lucu banget")
data_input =text_preprocessing_process(data_input)

tfidf =TfidfVectorizer
loaded_vec =TfidfVectorizer(decode_error="replace", vocabulary=set(pickle.load(open("new_selected_feature_tf-idf_chi2.sav", "rb"))))
hasil =model.predict(loaded_vec.fit_transform([data_input]))

if(hasil==0):
s ="Komentar tidak terindikasi Hate Speech"
elif(hasil==1):
s ="Komentar terindikasi Hate Speech"
else:
s ="inputan salah"

print("Hasil Prediksi : \n", s)

Hasil input data teks di atas berhasil diprediksi oleh model bahwa teks tersebut tidak terindikasi hate speech.

Deploy

Terakhir, saya implementasikan model kedalam sebuah web untuk memprediksi sebuah teks. Script rancangan desain web dibuat dengan bantuan software Visual Studio Code menggunakan bahasa pemrograman python. Rancangan web app yang telah dibuat akan di deploy pada internet menggunakan streamlit pada laman https://share.streamlit.io/ agar bisa diakses secara online oleh publik. Setelah berhasil melakukan deploy web app streamlit, website untuk mendeteksi komentar hate speech pada Instagram bisa diakses pada laman https://deteksihatespeech.streamlit.app/ .

Demikian penjelasan project kali ini mengenai Klasifikasi Komentar Hate Speech Menggunakan Algoritma Random Forest dengan Seleksi Fitur Chi Square. Semoga bermanfaat!

Referensi

Surat Edaran kapolri No.SE/6/X/2015. (2015). Jakarta.

Irfan, M., Widiyanto, D., & Jayanti. (2022). Analisis Sentimen Pada Ulasan Aplikasi Samsat Mobile Jawa Barat (Sambara) Menggunakan algoritma Naive bayes Classifier dengan seleksi fitur Chi Square. Seminar Nasional Mahasiswa Ilmu Komputer dan APlikasinya (SENAMIKA), 640–649.

Ernayanti, T., Mustafid, Rusgiyono, A., & Hakim, A. R. (2022). PENGGUNAAN SELEKSI FITUR CHI-SQUARE DAN ALGORITMA MULTINOMIAL NAIVE BAYES UNTUK ANALISIS SENTIMEN PELANGGAN TOKOPEDIA. JURNAL GAUSSIAN, 11(4), 562–571.

Harish, H. N., Faraby, S. A., & Dwifebri, M. (2021). Klasifikasi Multi Label Pada Hadis Bukhari Terjemahan Bahasa Indonesia menggunakan Random Forest, Mutual Information, dan Chi-Square. e-Proceeding of Engineering, 8(5), 10583–10593.

Kencana, C. G., & Sibaron, Y. (2019). Klasifikasi Sentiment Analysis pada Review Buku Novel Berbahasa Inggris dengan Menggunakan Metode Support Vector Machine (SVM). eProceeding of Engineering, 6(3), 10451–10462.

--

--