Apakah Itu Analisis Sentimen? Adakah Kegunaannya?
Analisis Sentimen atau banyak orang yang menyebutnya Sentiment Analysis adalah sebuah analisis yang biasanya digunakan untuk mendapatkan sebuah informasi sentiment dari kalimat yang terdapat dari teks tersebut. Di dalam dunia Data Science, teknik atau metode yang dapat digunakan dalam analisis sentimen biasanya disebut dengan istilah Natural Language Processing (NLP). Hasil dari analisia sentimen dengan menggunakan NLP tersebut dapat dikelompokkan menjadi tiga kelompok tergantung pemanfaatannya, seperti:
Fine-grained: Tipe analisis ini memungkinkan seseorang untuk memberikan penilaian terhadap sebuah text dan penilaian tersebut memiliki range. analisis ini banyak digunakan untuk melakukan penilaian atau ulasan terhadap pelayanan sebuah restoran atau pelayanan dari sebuah toko e-commerce.
Emotion detection: Sesuai dengan namanya, analisis ini dimanfaatkan untuk mengetahui emosi dari seseorang misalkan seseorang tersebut sedang bahagia, sedih, marah atau frustasi. Akan tetapi tipe analisis ini sangatlah subjektif dikarenakan penggunaan kata pada setiap orang untuk meluapkan emosinya berbeda-beda, sebagai contoh: “Parah! Makanan ini enak banget”, kata parah dalam kalimat itu bisa digambarkan sebagai kata yang positif walaupun biasanya kata parah lebih cenderung memiliki makna negatif.
Aspect-based sentiment analysis: Teknik analis ini dapat digunakan untuk mengetahui apakah sebuah komentar atau kalimat mengandung aspek positif, negatif dan netral. Tipe analisis ini banyak digunakan untuk mengetahui apakah sebuah berita mengenai saham tertentu mengandung unsur negatif atau positif, karena sebuah berita yang mengandung unsur positif dapat mempengaruhi sebuah harga saham menjadi lebih tinggi begitu juga sebaliknya.
Sentiment Analysis
Dari ketiga pemanfaatan yang sudah dijelaskan di atas, fokus pemanfaatan dari analsia sentimen yang akan dibedah lebih mendalam pada Rpubs ini adalah aspect-based sentiment analysis. Tipe analisis ini akan kita coba gunakan untuk mengetahui apakah berita-berita yang berhubungan dengan emas memiliki aspek positif atau negatif yang akan memberikan dampak kepada pergerakan harga emas tersebut.
Sebelum membahas bagaimana mengimplementasikannya, mari coba pahami dulu mengenai investasi emas dan mengapa diperlukan untuk melakukan analisia sentimen. Emas tidak hanya digunakan sebagai sebuah aksesoris akan tetapi emas juga sudah dimanfaatkan sebagai salah satu pilihan investasi dan investasi emas merupakan salah satu pilihan yang paling populer untuk para investor pemula dikarenakan pergerakan harga emas relatif lebih stabil dan mekanismenya tidak serumit jika dibandingkan dengan investasi di forex atau saham. Walaupun mekanismenya tidak terlalu rumit bukan berarti seorang investor tidak perlu melakukan analisis sebelum membeli ataupun menjual emas.
Salah satu analisis yang dapat dilakukan oleh para investor pemula sebelum membeli atau menjual emas adalah analisis sentimen dari berita-berita yang diberitakan oleh media mengenai topik yang berhubungan. Berita-berita yang diberitakan oleh media sebenarnya dapat langsung diasumsikan oleh para pembacanya apakah berita tersebut memiliki aspek positif atau negatif dengan berpikir kritis, akan tetapi tidak jarang pembaca berita terkecoh dalam menafsirkan aspek yang terkandung dari berita tersebut yang dapat mengakibatkan kerugian terhadap para investor terutama bagi para investor yang hanya memanfaatkan analisis sentimen sebagai acuan berinvestasi emas. Dengan adanya aspect-based sentiment analysis dengan menggunakan NLP, diharapkan para investor tidak perlu repot-repot untuk menelaah apakah berita yang diberitakan media mengandung aspek positif yang dapat menaikan harga emas ataupun sebaliknya jika berita tersebut mengandung aspek negatif.
Bagaimana Melakukan Aspect Based Sentiment Analysis Dengan NLP
Ada beberapa pendekatan yang dapat dilakukan untuk melakukan analisis sentimen dengan NLP di R, dari setiap pendekatan yang dilakukan tentunya pasti ada kelebihan dan kekurangan. Sebelum membahas lebih mendalam mengenai kelebihan dan kekurangan dari setiap pendekatan yang akan dilakukan mari kita coba pahami bagaimana melakukan aspect-based sentiment analysis.
Secara garis besar untuk melakukan aspect-based sentiment analysis ada 2 langkah yang harus dilakukan yaitu, Data Pre-Processing & Model Preparation.
Data Pre-Processing: Text preprocessing adalah suatu proses untuk menyeleksi data text agar menjadi lebih terstruktur lagi dengan melalui serangkaian tahapan. Sedikit tambahan, teks preprocessing merupakan salah satu implementasi dari text mining. Text mining sendiri adalah suatu kegiatan menambang data, di mana data yang biasanya diambil berupa text yang bersumber dari dokumen-dokumen yang memiliki goals untuk mencari kata kunci yang mewakili dari sekumpulan dokumen tersebut sehingga nantinya dapat dilakukan analisis hubungan antara dokumen-dokumen tersebut.
Model Preparation: Langkah ini adalah langkah lanjutan, di sini kita akan mulai berkecimpung dengan model yang akan digunakan. Beberapa langkah yang akan dilakukan terlebih dahulu di sini adalah cross validation, model evaluation & model interpretation. Untuk detail dari setiap tahapan yang akan dilakukan pada langkah Model Preparation akan dijelaskan lebih mendetail lagi pada tiap sub-bagiannya.
# Data Wrangling
library(tidyverse)
library(rwhatsapp)
library(wordcloud)
# Text Preprocessing
library(textclean)
library(stringr)
library(tm)
# Cross Validation
library(rsample)
# Machine Learning
## Naive Bayes
library(e1071)
## LSTM
library(keras)
# Machine Learning Evaluation
library(caret)
Data yang akan digunakan di sini adalah data yang berasal dari kaggle.
gold <- read.csv("dataset/gold-dataset.csv")
head(gold, 3)
Dari beberapa kolom di atas sebenarnya yang paling penting adalah kolom News & Price.Sentiment, kolom News berisikan berita mengenai harga emas dan pada kolom Price.Sentiment beriskan informasi mengenai apakah berita tersebut memberikan aspek positif, negatif, netral, atau tidak memberikan efek apa-apa. Oleh karena itu mari kita hilangkan kolom-kolom yang lainnya sembari kita ubah tipe data untuk kolom Price.Sentiment menjadi factor dikarenakan memiliki unique value yang berulang-ulang.
gold_new <- gold %>%
select(News, Price.Sentiment) %>%
mutate(Price.Sentiment = as.factor(Price.Sentiment))
glimpse(gold_new)
## Rows: 11,412
## Columns: 2
## $ News <chr> "april gold down 20 cents to settle at $1,116.10/oz", ~
## $ Price.Sentiment <fct> negative, negative, positive, none, positive, positive~
Supaya kita bisa lebih memahami setiap pengaruh sentiment yang ada terhadap harga emas, berikut penjelasannya:
Positive Sentiment: Aspek positif pada berita mengenai harga emas akan cenderung meningkatkan harga emas tersebut.Negative Sentiment: Aspek negatif pada berita mengenai harga emas akan cenderung menurunkan harga emas tersebut.Neutral Sentiment: Aspek netral pada berita mengenai harga emas tidak akan memberikan efek apapun terhadap emas tersebut.None Sentiment: Aspek none pada berita mengenai harga emas sama seperti dengan aspek netral, akan tetapi aspek none itu hanya muncul pada kalimat yang mengandung unsur pertanyaan.gold$Price.Sentiment %>%
table() %>%
prop.table()
## .
## negative neutral none positive
## 0.35856993 0.04223624 0.18322818 0.41596565
Dari hasil observasi, kita mengetahui bahwa total observasi untuk setiap sentiment berbeda-beda. Sentiment yang paling banyak pada data kita adalah sentiment yang memiliki aspek positif, lalu diikuti dengan aspek negatif, aspek none dan aspek netral. Idealnya memang ketika kita menghadapi data yang tidak seimbang, kita akan melakukan penyeimbangan data dengan metode upsample ataupun downsample, akan tetapi kita akan membiarkan data yang kita tidak seimbang untuk mencari tahu apakah model yang kita gunakan dapat memprediksi dengan baik atau tidak terhadap data yang tidak seimbang proporsinya.
Untuk mengetahui teks atau token mana yang dapat mewakili apakah sebuah berita mengandung aspek adalah positif, negatif, netral atau none, kita bisa menggunakan library(wordcloud) karena wordcloud adalah alat visualisasi yang dapat membantu kita untuk menyajikan data teks dalam format yang sederhana dan jelas. Nantinya dalam visualiasi akan coba kita lihat 10 kata yang paling banyak muncul untuk setiap aspek sentiment yang ada pada berita kita.
pos <- gold %>%
filter(Price.Sentiment == "positive") %>%
select(News)
wordcloud(words = as.matrix(pos),
max.words = 10,
scale = c(2.5, 1.25),
random.order=FALSE,
rot.per=0.5,
colors=brewer.pal(2, "Dark2"))
neg <- gold %>%
filter(Price.Sentiment == "negative") %>%
select(News)
wordcloud(words = as.matrix(neg),
max.words = 10,
scale = c(2.5, 1.25),
random.order=FALSE,
rot.per=0.5,
colors=brewer.pal(2, "Dark2"))
neg <- gold %>%
filter(Price.Sentiment == "neutral") %>%
select(News)
wordcloud(words = as.matrix(neg),
max.words = 10,
scale = c(2.5, 1.25),
random.order=FALSE,
rot.per=0.5,
colors=brewer.pal(2, "Dark2"))
neg <- gold %>%
filter(Price.Sentiment == "none") %>%
select(News)
wordcloud(words = as.matrix(neg),
max.words = 10,
scale = c(2.5, 1.25),
random.order=FALSE,
rot.per=0.5,
colors=brewer.pal(2, "Dark2"))
Dari visualisasi di atas, ada 2 warna yang digunakan untuk mewakili kata-kata mana yang paling sering digunakan yaitu warna ungu dan hijau. Kata-kata yang berwarna ungu adalah kata yang paling banyak digunakan dalam teks berita untuk setiap aspek sentimentnya karena kata-kata yang berwarna ungu memiliki ukuran paling besar dan berada di tengah. Dari keempat sentiment yang ada, hanya kata gold saja yang diberikan warna ungu oleh fungsi wordcloud(), hal tersebut bisa dibilang wajar karena data yang kita gunakan adalan data teks berita yang membahas tentang emas.
Untuk kata-kata yang berwarna hijau bukan berarti tidak penting karena fungsi wordcloud() hanya menampilkan karakteristik teks berdasarkan frekuensi term setiap kata pada setiap klasifikasi berita. Kata-kata yang berwana hijau ini, merupakan 9 kata lainnya yang paling sering muncul untuk pada setiap aspeknya.
Pada pembahasan di atas, belum sempat disebutkan tahapan-tahapan apa saja yang harus dilakukan untuk membuat data teks kita lebih terstruktur. Tahapan tersebut meliputi tahapan case folding dan tokenizing, sebenarnya ada beberapa tahapan lainnya yang bisa dilakukan, akan tetapi tidak ada aturan pasti, semua itu tergantung dengan jenis serta kondisi data yang kita miliki.
Apa itu case folding dan tokenizing, untuk lebih memahami kedua tahapan tersebut mari kita memulai teks pre-processing.
Tahapan pertama yang biasanya dilakukan adalah tahapan case folding. Tahapan ini hampir selalu disertakan ketika melakukan text preprocessing. Mengapa? Karena data yang kita miliki tidak selalu terstruktur dan konsisten dalam penggunaan huruf kapital. Jadi, peran dari case folding adalah untuk menyamaratakan penggunaan huruf kapital. Misalnya data teks yang kita dapat berupa tulisan “DaTA SCIence” maka dengan case folding artinya kita mengubah semua huruf menjadi huruf kecil (lowercase) semua.
Selain mengubah semua huruf menjadi huruf kecil, kita akan mempersiapkan data teks menjadi bentuk yang bisa digunakan oleh machine learning, dengan melakukan beberapa hal ini.
Karakter lain yang bukan termasuk huruf, seperti angka, simbol dan tanda baca dianggap sebagai delimiter, delimiter itu bisa dihapus. Tujuan dari menghilangkan beberapa hal tersebut adalah, mesin tidak bisa memahami makna dari karakter-karakter tersebut.
Sebenarnya ada beberapa hal lainnya yang dapat dilakukan seperti menghilangkan URL & emoticon akan tetapi 2 hal tersebut tidak dilakukan, karena pada naskah teks tidak ada link URL dikarenakan sudah ada satu kolom yang mewakili link URL. Selain itu, biasanya dalam naskah teks berita juga tidak memiliki emoticon, terlebih lagi naskah teks berita yang kita gunakan adalah berita formal yang membahas tentang investasi emas. Akan tetapu untuk memastikan bahwa dalam naskah teks kita tidak terdapat 2 hal tersebut, kita bisa melakukan pengecekan dengan menggunakan cara di bawah ini.
Mengecek apakah ada URL pada kolom News
# Membuat sebuah object yang berisikan pattern yang biasanya ada pada sebuah link URL
url_pattern <- "http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\(\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+"
# Membuat object baru yang berisikan data dari object gold_new
check_url <- gold_new
# Menarik semua link URL yang ada dengan menggunakan fungsi di bawah ini
check_url$ContentURL <- str_extract(check_url$News, url_pattern)
head(check_url)
Dengan memanfaatkan sebuah fungsi str_extract() dari library(stringr), kita dapat memastikan apakah pada kolom News terdapat link URL, dikarenakan pada fungsi str_extract() dapat menarik semua isi pada teks di kolom News dengan memberitahu pattern yang biasanya terjadi pada sebuah link URL. Jika dilihat hasil yang muncul dari 6 data teratas value yang muncul adalah NA, dari situ kita bisa asumsikan bahwa jika value yang muncul adalah NA berarti tidak ada link URL. Untuk melihat apakah di sisa data yang ada memiliki link atau tidak, kita akan menggunakan fungsi base unique() untuk melihat apakah ada value lain selain NA.
unique(check_url$ContentURL)
## [1] NA
Dari hasil pengecekan di atas, tidak ada unique value selain NA oleh karena itu kita dapat menarik kesimpulan bahwa tidak ada link URL pada teks yang ada.
Mengecek apakah ada emoticon pada kolom News
Untuk memastikan apakah di dalam teks yang kita memiliki emoticon atau tidak, di sini kita akan memanfaatkan sebuah library(rwhatsapp). Nantinya di dalam library tersebut akan ada sebuah fungsi yang bernama lookup_emoji() yang dapat memeriksa apakah di dalam teks yang ada memiliki sebuah emoticon atau tidak.
# Implementasi dari fungsi lookup_emoji
check_emoticon <- rwhatsapp::lookup_emoji(gold_new, text_field = "News")
head(check_emoticon)
Fungsi lookup_emoji() nantinya akan membuat 2 kolom baru yaitu kolom emoji dan emoji_name, jika pada kedua kolom itu valuenya adalah <chr [sebuah angka]> maka di dalam sebuah kalimat itu memiliki emoticon akan tetapi jika valuenya adalah <NULL> maka di dalam sebuah kalimat itu tidak memiliki emoticon.
unique(check_emoticon$emoji)
## [[1]]
## NULL
unique(check_emoticon$emoji_name)
## [[1]]
## NULL
Dari hasil pengecekan di atas, tidak ada unique value selain NULL oleh karena itu kita dapat menarik kesimpulan bahwa tidak ada emoticon pada teks yang ada. Setelah mengecek apakah kita perlu menghilangkan link URL dan emoticon pada teks kita, kita bisa langsung memulai tahapan data pre-processing.
Dalam proses case folding kita akan menggunakan dua library yang berbeda yaitu library(stringr) & library(texclean), untuk mengetahui fungsi apa saja yang bisa kita manfaatkan, mari kita gunakan teks di bawah ini sebagai contoh.
example <- "Hey! w8 a minuteee, i'll come around 10..."
Hey! w8 a minute, LMGTFY right now…
Library(stringr)
example %>%
str_to_lower()
## [1] "hey! w8 a minuteee, i'll come around 10..."
example %>%
str_replace_all("[[:punct:]]", " ")
## [1] "Hey w8 a minuteee i ll come around 10 "
example %>%
str_replace_all("[[:digit:]]", " ")
## [1] "Hey! w a minuteee, i'll come around ..."
Library(textclean)
example %>%
replace_internet_slang(replacement = paste0('{{', lexicon::hash_internet_slang[[2]], '}}'))
## [1] "Hey! {{wait}} a minuteee, i'll come around 10..."
example %>%
replace_word_elongation()
## [1] "Hey! w8 a minute, i'll come around 10..."
example %>%
replace_contraction()
## [1] "Hey! w8 a minuteee, I will come around 10..."
example %>%
replace_white()
## [1] "Hey! w8 a minuteee, i'll come around 10..."
Semua yang kita lakukan di atas, hanya untuk memperlihatkan proses teks pre-processing yang terjadi satu per satu. Nantinya kita bisa merangkum, semua proses yang kita lakukan di atas dengan konsep piping.
teks_clean <- gold_new %>%
mutate(
News_Clean = News %>%
str_to_lower() %>%
replace_internet_slang(replacement = paste0('{{ ', lexicon::hash_internet_slang[[2]], ' }}')) %>%
replace_contraction() %>%
replace_word_elongation() %>%
str_replace_all("[[:punct:]]", " ") %>%
str_replace_all("[[:digit:]]", " ") %>%
replace_white() %>%
str_squish()
)
teks_clean %>%
select(News, News_Clean) %>%
head(5)
Jika dilihat dari observasi di atas, ada 1 simbol yang belum berhasil dibersihkan yaitu simbol $. Maka dari itu mari kita coba tambahkan sebuah fungsi str_replace_all("\\$", ""), fungsi tersebut nantinya akan bermanfaat untuk menghilangkan simbol $ yang ada.
teks_clean <- gold_new %>%
mutate(
News_Clean = News %>%
str_to_lower() %>%
replace_internet_slang(replacement = paste0('{{ ', lexicon::hash_internet_slang[[2]], ' }}')) %>%
replace_contraction() %>%
replace_word_elongation() %>%
replace_number(remove = T) %>%
str_replace_all("[[:punct:]]", " ") %>%
str_replace_all("[[:digit:]]", " ") %>%
str_replace_all("\\$", "") %>%
replace_white() %>%
str_squish()
)
teks_clean %>%
select(News, News_Clean) %>%
head(5)
Dengan menambahkan sebuah fungsi khusus, kita sudah berhasil menghilangkan simbol $ yang masih tersisa. Dari sini kita bisa menyimpulkan bahwa, terkadang kita harus lebih spesifik untuk membersihkan teks yang kita miliki. Dan tidak ada salahnya jika kedepannya kita menggabungkan beberapa fungsi dari library lainnya untuk membantu kita dalam melalui tahapan case folding ini, sehingga teks yang kita miliki benar-benar siap untuk diproses lebih lanjut.
Tahapan selanjutnya yang bisa kita lakukan ada tokenizing, tokenisasi pada dasarnya adalah pemisahan frasa, kalimat, paragraf, atau seluruh dokumen teks menjadi unit yang lebih kecil, seperti kata atau istilah individual. Masing-masing unit yang lebih kecil ini disebut token.
Berikut adalah contoh ilustrasi dari hasil tahapan tokenisasi,
Tokenisasi
Sebelum melakukan tahapan tokenisasi ini, ada 2 analisis yang bisa kita lakukan nantinya yaitu,
Pertama-tama yang akan kita bahas adalah menghitung frekuensi kata yang hadir dari total keseluruhan kata yang ada.
paste(teks_clean$News_Clean, collapse = " ") %>%
str_split(" ") %>%
unlist() %>%
n_distinct()
## [1] 4537
Tahapan yang dilakukan di atas adalah tahapan di mana kita menghitung jumlah kata yang berada dalam keseluruhan teks kita, total terdapat 4537 kata. Dari keseluruhan kata tersebut, kita bisa mengurangi menjadi setengah ataupun membiarkan mesin kita menggunakan keseluruhan kata yang ada. Penentuan banyaknya kata yang harus dipakai itu sendri belum ada peraturan yang pasti, di sini mari kita coba gunakan sepertiga dari total keseluruhan kata yang ada.
Untuk sementara waktu mari kita gunakan sepertiga dari total keseluruhan data yang ada, nantinya total kata yang akan kita gunakan akan berdasarkan jumlah frekuensi kemunculan terbanyak, fungsi yang akan kita gunakan di bawah ini dari library(keras) akan secara otomatis menghitung jumlah frekuensi kemunculan kata.
num_words = 1500
tokenizer <- text_tokenizer(num_words = num_words) %>%
fit_text_tokenizer(teks_clean$News_Clean)
Tujuan dari pengurangan kata itu sendiri adalah untuk menghilangkan kata-kata yang jarang muncul dalam teks kita, dengan harapan model kita hanya akan mempelajari atau mencari pola dari setiap kata yang sering digunakan untuk setiap target variable yang ada.
Selanjutnya mari coba kita bahas mengenai jumlah kata dalam sebuah teks. Untuk mengetahui seberapa panjang kata yang berada pada sebuah kalimat kita bisa menggunakan fungsi di bawah ini.
maxlen <- max(str_count(teks_clean$News_Clean, "\\w+")) + 1
maxlen
## [1] 21
Mungkin di sini masih cukup membingungkan kenapa kita memerlukan informasi panjang kata dalam sebuah teks, hal tersebut akan coba diperjelas pada saat kita masuk ke cross validasi, dikarenakan tahapan tokenisasi baru akan benar-benar kita lakukan setelah kita memisah data kita menjadi data train & data test.
Sebelum kita memisahkan data kita, ada satu tahapan yang perlu kita lakukan. Tahapan ini bisa dibilang sebuah tahapan yang tidak boleh kita tinggakan ketika kita ingin menggunakan sebuah model LSTM, dikarenakan pada model tersebut tidak bisa membaca target variabel yang berbentuk string. Maka dari itu kita akan megubahnya terlebih dahulu menjadi angka dengan menggunakan fungsi di bawah ini.
data <- teks_clean %>%
mutate(label = factor(Price.Sentiment, levels = c("negative", "positive", "neutral", "none")),
label = as.numeric(label),
label = label - 1) %>%
select(News_Clean, label) %>%
na.omit()
head(data, 5)
Tahapan cross validasi adalah metode statistik yang dapat digunakan untuk mengevaluasi kinerja model atau algoritma di mana data dipisahkan menjadi tiga subset yaitu data pembelajaran, data validasi dan data evaluasi. Fungsi dari ketiga data tersebut adalah
set.seed(100)
intrain <- initial_split(data = data, prop = 0.8, strata = "label")
data_train <- training(intrain)
data_test <- testing(intrain)
set.seed(100)
inval <- initial_split(data = data_test, prop = 0.5, strata = "label")
data_val <- training(inval)
data_test <- testing(inval)
Setelah berhasil memisahkan datanya menjadi tiga bagian, mari kita implementasikan hasil temuan pada bagian tokenisasi di atas dan penjelasan lanjutan mengenai kenapa kita harus mengetahui panjang maksimal dari kata pada sebuat kalimat akan dilanjutkan di bawah ini.
# prepare x
data_train_x <- texts_to_sequences(tokenizer, data_train$News_Clean) %>%
pad_sequences(maxlen = maxlen, padding = "pre", truncating = "post")
data_val_x <- texts_to_sequences(tokenizer, data_val$News_Clean) %>%
pad_sequences(maxlen = maxlen, padding = "pre", truncating = "post")
data_test_x <- texts_to_sequences(tokenizer, data_test$News_Clean) %>%
pad_sequences(maxlen = maxlen, padding = "pre", truncating = "post")
# prepare y
data_train_y <- to_categorical(data_train$label, num_classes = 4)
data_val_y <- to_categorical(data_val$label, num_classes = 4)
data_test_y <- to_categorical(data_test$label, num_classes = 4)
Fungsi texts_to_sequence(), akan membuat matriks hasil transformasi text ke bentuk urutan angka (integer). Setelah itu diwrap dengan fungsi pad_sequences(), fungsi tersebut harus digunakan karena panjang teks bisa berbeda, dengan menggunakan fungsi pad_sequences() untuk memastikan semua teks memiliki panjang yang sama dengan memasukkan nilai 0 jika teks terlalu pendek. Berikut contoh ilustrasinya:
texts_to_sequences(tokenizer, c("Excellent work!",
"Good job bro, keep hard work",
"Hey, how are you?")) %>%
pad_sequences(maxlen = 5, padding = "pre", truncating = "post")
## [,1] [,2] [,3] [,4] [,5]
## [1,] 0 0 0 0 0
## [2,] 0 0 393 1418 615
## [3,] 0 0 301 251 321
Setelah mempersiapkan data teks yang ada, sekarang kita akan masuk ke tahapan pembuatan model machine learning. Fokus model yang akan dibuat untuk melakukan analisis sentiment adalah model Long Short Term Memory (LSTM). Sebagai pembanding dari model LSTM, nantinya kita akan membuat sebuah model lagi, yaitu model Naive Bayes.
LSTM merupakan salah satu bagian dari Recurrent Neural Network (RNN). Jika LSTM adalah salah satu bagian dari RNN, kenapa kita tidak menggunakan RNN saja? Salah satu alasan kenapa kita menggunakan LSTM di sini dikarenakan LSTM bisa menampung informasi atau pola jauh lebih baik jika dibandingkan dengan RNN. Hal tersebut bisa terjadi karena adanya tambahan sinyal yang diberikan dari satu langkah waktu ke langkah waktu berikutnya, atau istilah yang bisanya digunakan untuk tambahan sinyal adalah cell state/memory cell. Selain dengan adanya cell state, didalam LSTM nantinya ada beberapa gate yang untuk memproses lebih lanjut setiap data yang ada.
Recurrent Neural Network (RNN)
Dari ilustrasi di atas, kita dapat melihat bahwa RNN sel hanya memiliki satu gate saja, jadinya setiap informasi informasi baru atau informasi dari RNN sel sebelumnya hanya akan diproses satu kali dengan menggunakan fungsi Tanh. Fungsi tanh digunakan untuk membantu mengatur nilai-nilai yang mengalir melalui jaringan. Fungsi tanh menekan nilai agar selalu antara -1 dan 1.
Fungsi tanh memastikan bahwa nilai tetap antara -1 dan 1, sehingga mengatur output dari jaringan saraf. Anda dapat melihat bagaimana nilai yang sama dari atas tetap berada di antara batas yang diizinkan oleh fungsi tanh.
Long Short Term Memory (LSTM)
LSTM Sel
Konsep inti LSTM adalah cell state, dan berbagai gerbangnya. Cell state bertindak sebagai jalan raya transportasi yang mentransfer informasi relatif sepanjang rantai urutan. Anda dapat menganggapnya sebagai “memori” jaringan. Keadaan sel, secara teori, dapat membawa informasi yang relevan selama pemrosesan urutan. Jadi, bahkan informasi dari langkah sebelumnya dapat diteruskan ke langkah berikutnya, yang dapat membantu untuk mengurangi efek memori jangka pendek. Saat cell state melanjutkan perjalanannya, informasi ditambahkan atau dihapus ke cell state melalui gerbang. Gerbang adalah jaringan saraf berbeda yang memutuskan informasi mana yang diizinkan pada keadaan sel. Gerbang dapat mempelajari informasi apa yang relevan untuk disimpan atau dilupakan selama pelatihan. Agar lebih mudah untuk dipahami, berikut ilustrasi dari proses yang terjadi pada setiap gerbang dan cell state
Pertama, kita memiliki forget gate. Gerbang ini memutuskan informasi apa yang harus dibuang atau disimpan. Informasi dari sel LSTM sebelumnya dan informasi dari input saat ini dilewatkan melalui fungsi Sigmoid.
Fungsi sigmoid nantinya akan menekan nilai input diantara 0 sampai 1. Itu berguna untuk memperbarui atau melupakan input data, karena angka apa pun yang dikalikan dengan 0 adalah 0, menyebabkan nilai menghilang atau “dilupakan.” Setiap angka dikalikan dengan 1 adalah nilai yang sama sehingga nilainya tetap sama atau “dipertahankan”. Jaringan dapat mempelajari data mana yang tidak penting sehingga dapat dilupakan atau data mana yang penting untuk disimpan. Jika nanti hasil yang dikeluarkan tidak bulat 0 atau 1, nilainya akan diperlakukan seperti ini, semakin mendekati 0 berarti akan dilupakan dan semakin mendekati 1 akan disimpan.
Pada bagian ini akan menentukan informasi apa yang dirasa relevan untuk dilanjutkan atau tidak, penentuannya dilakukan dengan melakukan perkalian antara hasil output tanh dengan output sigmoid. Hasil dari output sigmoid akan menentukan informasi mana yang penting untuk disimpan dari output tanh.
Seperti yang disampaikan di atas, salah satu keunggulan dari model LSTM adalah dapat memiliki tambahan sinyal baru atau cell state. Tambahan sinyal tersebut diperoleh dari hasil pengolahan informasi pada forget gate & input gate. Hasil tambahan sinyal baru ini akan diterus ke LSTM selanjutnya untuk diproses lebih lanjut lagi.
Selain informasi tambahan sinyal baru yang diteruskan, akan ada satu informasi lagi yang akan diteruskan ke LSTM sel selanjutnya, informasi tersebut adalah hasil dari output gate.
Untuk mendapatkan hasil dari output gate, kita akan memasukan informasi dari tambahan sinyal baru kedalam fungsi tanh lalu hasilnya akan dikalikan dengan infomasi dari LSTM sel sebelumnya yang sudah dimasukan kedalam fungsi sigmoid. Hasil dari perkaliannya itu yang akan dibawa ke langkat berikutnya.
Sedikit rangkuman dari penjelasan di atas, forget gate digunakan untuk memutuskan informasi apa yang relevan untuk disimpan dari langkah sebelumnya. Input gate digunakan untuk memutuskan informasi apa yang relevan untuk ditambahkan dari langkah saat ini. Output gate digunakan untuk menentukan informasi apa yang seharusnya diteruskan ke LSTM sel selanjutnya bedasarkan informasi cell state.
Dalam membuat model LSTM, kita akan meminjam library(keras) dari Tensorflow Python. Dari library tersebut, kita akan menggunakan fungsi keras_model_sequential() untuk membangun arstitektur model LSTM. Secara umum arsitektur pada setiap model Neural Network setidaknya harus memiliki 3 komponen berikut ini, Input Layer, Hidden Layer dan Output Layer. Selain dari 3 komponen yang sudah disebutkan, sebenarnya kita bisa menambahkan beberapa layer lagi sesuai dengan kebutuhan, akan tetapi untuk model LSTM yang akan kita buat, kita tidak akan menambahkan layer lainnya.
Layer Pertama: Input Layer
Layer utama yang akan dibuat adalah input layer atau biasanya juga disebut sebagai embedding layer. Pada layer ini nantinya akan diisi dengan kata-kata yang ada pada setiap berita. Pada lapisan ini juga akan mempelajari pengaruh dari posisi atau kedekatan anatara satu kata dengan kata yang lainnya. Sebagai contoh, kata raja biasanya ditempatkan di dekat kata pria dan kata ratu biasanya ditempatkan di dekat kata wanita.
Berikut ini adalah beberapa parameter yang dapat diisi pada input layer/embedding layer:
input_dim: Pada parameter ini bisa diisi dengan jumlah kosakata dalam data teks. Misalnya, jika data Anda adalah bilangan bulat yang dikodekan ke nilai antara 0-10, maka ukuran kosakatanya adalah 11 kata.input_length: Pada parameter ini bisa diisi dengan jumlah kosakata yang paling panjang yang terdapat pada satu kalimat. Misalnya, dalam 10 dokumen, 9 di antaranya hanya terdiri dari 50 kata dan satu dokumen terdiri 100 kata, maka parameter ini akan diisi ini akan menjadi 100.output_dim: Ini adalah ukuran ruang vektor di mana kata-kata akan disematkan. Ini mendefinisikan ukuran vektor output dari lapisan ini untuk setiap kata. Misalnya, bisa 32 atau 100 atau bahkan lebih besar. Sedikit catatan di sini, tidak ada aturan khusus dalam menentukan dimensi vektor.
Layer Kedua: Hidden Layer
Layer kedua adalah hidden layer dan pada layer ini kita bisa menambahkan berbagai macam layer, akan tetapi layer yang akan kita tambahkan di sini adalah LSTM layer karena model yang kita ingin buat adalah model LSTM. Pada layer ini nantinya setiap input atau infromasi yang berasal dari embedding layer akan proses lebih lanjut lagi.
Berikut ini adalah beberapa parameter yang dapat diisi pada layer LSTM:
units: Parameter ini nantinya bisa diisi dengan dengan jumlah memroy cell yang ingin disiapkan untuk mempelajari atau mengingat informasi yang dikeluarkan atau diberikan dari embedding layer. Sedikit catatan di sini, tidak ada aturan khusus dalam menentukan jumlah memory cell, akan tetapi jika terlalu banyak model LSTM akan beresiko untuk overfit.dropout: Parameter dropout ditambahkan untuk mengurangi risiko overfit, range nilai dropout antara 0 hingga 1. Nilai yang umum digunakan yaitu 0.2 hingga 0.5. Jika nilai makin mendekati 0 akan cenderung overfit, sedangkan makin mendekati 1 memiliki risiko underfit.
Layer ketiga: Output Layer
Layer ketiga adalah output layer atau sering juga disebut sebagai dense layer. Pada layer ini nantinya kita bisa mengatur berapa banyak kelas yang ingin dihasilkan, kelas di sini akan kita samakan dengan target variabel yang ingin kita klasifikasikan.
Berikut ini adalah beberapa parameter yang dapat diisi pada layer LSTM:
units: Parameter units di sini fungsinya berbeda dengan parameter unit pada layer lstm, parameter units di sini nantinya akan kita isi dengan jumlah target variabel dari data kita.activation: Parameter ini berfungsi untuk mengtransformasi nilai dari setiap input, sehingga nilainya nanti tidak terlalu besar dan dapat ditafsirkan menjadi sebuah kelas yang sesuai dengan jumlah target variable kita. Berikut adalah beberapa pilihan dari parameter activation yang dapat kita gunakan, sigmoid (hasil transformasi nilainya di antara 0-1 cocok digunakan untuk binary class), softmax (hasil transformasi menjadi nilai probabilitas antara 0-1 cocok dgunakan untuk multiclass) dan tanh (hasil transformasi nilainya di antara -1 hingga 1.)model <- keras_model_sequential() %>%
# layer input
layer_embedding(
name = "input",
input_dim = num_words,
input_length = maxlen,
output_dim = 32
) %>%
# layer lstm
layer_lstm(
name = "lstm",
units = 64,
dropout = 0.5,
return_sequences = FALSE,
kernel_initializer = initializer_random_uniform(minval = -0.05, maxval = 0.05)
) %>%
# layer output
layer_dense(
name = "output",
units = 4,
activation = "softmax"
)
Supaya lebih terbayang bagaimana hasil dari setiap layer yang kita buat, mari kita lihat ilustrasi di bawah ini.
Arsitektur
Setiap layer yang kita buat nantinya akan tersusun seperti ilustrasi di atas. Sedangkan untuk proses pengolahan datanya akan dimulai dari setiap unit embedding layer, lalu setiap data tersebut akan dikirim ke setiap unit LSTM yang terdapat pada bagian hidden layer untuk diproses lebih lanjut. Setelah itu hasilnya akan dikirimkan ke dense/output layer untuk ditentukan lebih cocok untuk masuk ke kelas yang mana dimasukan melalui fungsi aktifasi softmax. Semua proses tersebut akan terus diulang sampai semua data berhasil diproses.
Setelah berhasil membangun arsitektur, langkah terakhir yang harus kita lakukan adalah menambahkan beberapa parameter berikut ini, loss function, optimizer & metrics. Penambahan ketiga parameter tersebut biasanya disebut sebagai compilation/model compile.
Berikut penjelasan untuk masing-masing parameter,
loss function: Parameter ini digunakan untuk mengukur efektivitas model kita dalam melakukan prediksi pada tiap epoch (iterasi) dilihat dari gap error antara prediksi dan aktualnya. Pada kasus kategori 2 kelas, lost function yang digunakan adalah binary_crossentropy sedangkan untuk kasus multiclass menggunakan categorical_crossentropy.optimizer: Parameter ini nantinya akan diisi dengan metode algoritmik yang dapat membantu model kita memaksimalkan hasil prediksi. Variansi dari optimizer yang dapat digunakan ada banyak sekali. Berikut adalah variasi dari optimzer yang bisa digunakan.model %>% compile(
optimizer = optimizer_adam(learning_rate = 0.001),
metrics = "accuracy",
loss = "categorical_crossentropy"
)
summary(model)
## Model: "sequential"
## ________________________________________________________________________________
## Layer (type) Output Shape Param #
## ================================================================================
## input (Embedding) (None, 21, 32) 48000
## ________________________________________________________________________________
## lstm (LSTM) (None, 64) 24832
## ________________________________________________________________________________
## output (Dense) (None, 4) 260
## ================================================================================
## Total params: 73,092
## Trainable params: 73,092
## Non-trainable params: 0
## ________________________________________________________________________________
Sekarang kita sudah bisa memasuki tahapan training model. Kita dapat menggunakan fungsi fit(), nantinya dalam fungsi tersebut ada dua parameter yang harus kita perhatikan, yaitu:
epoch: parameter ini nantinya akan mengatur banyaknya iterasi pengulangan pada saat pelatihan model. Penentuan banyaknya iterasi juga tidak memiliki aturan khusus, akan tetapi semakin banyak epoch maka error bisa lebih kecil, namun proses training semakin lama dan rentan overfitting.batch_size: parameter ini nantinya akan mengatur banyak jumlah sampel yang dilatih pada tiap iterasi/epoch. Sama seperti epoch, penentuan jumlah batch size juga tidak memiliki aturan khusus, akan tetapi semakin sedikit batch size maka proses training semakin lama (karena proses optimasi model semakin banyak); namun bisa mencegah komputasi terlalu besar di 1 waktu sekaligus.model_lstm <- model %>% fit(
data_train_x, data_train_y,
batch_size = 256,
epochs = 10,
verbose = 1,
validation_data = list(
data_val_x, data_val_y
)
)
# model_lstm plot
plot(model_lstm)
## `geom_smooth()` using formula 'y ~ x'
Setelah berhasil membuat model LSTM, sekarang kita akan membuat model Naive Bayes sebagai model pembandingnya. Model Naive Bayes itu sendiri bisa dikatakan sebuah model yang sangat populer dikarenakan pembuatan model ini bisa dikategorikan cukup mudah dan tidak memerlukan waktu lama ataupun tenaga yang besar.
Jika kita menggunakan model naive bayes, kita memiliki opsi lain dalam melakukan tahapan tokenisasi. Dalam melakukan tokenisasi di sini kita bisa menggunakan fungsi dari library(tm) dan menggunakan fungsi yang bernama DocumentTermMatrix(), akan tetapi sebelum kita menggunakan fungsi tersebut kita harus mengubah format text kita menjadi corpus terlebih dahulu dengan menggunakan fungsi VCorpus(VectorSource).
trainx <- VCorpus(VectorSource(data_train$News_Clean))
testx <- VCorpus(VectorSource(data_test$News_Clean))
Dapat dilihat di atas, kita sudah berhasil mengubah data teks kita yang sudah dibersihkan menjadi bentuk corpus, sekarang kita bisa memulai tahapan tokenisasi.
trainx <- DocumentTermMatrix(trainx)
testx <- DocumentTermMatrix(testx)
Sekarang kita bisa menentukan jumlah kata yang digunakan, akan tetapi di sini penentuan jumlah kata yang akan digunakan sedikit berbeda dengan cara LSTM. di sini kita akan menentukan kata-katanya berdasarkan minimal jumlah kemunculan kata tersebut dari total keseluruhan teks kita.
freq_words <- findFreqTerms(trainx, lowfreq = 100)
trainx <- trainx[ , freq_words]
testx <- testx[ , freq_words]
Tidak berhenti sampai disitu, di sini kita akan menggunakan sebuah fungsi bernama Bernoulli Converter. Fungsi Bernoulli Converter digunakan untuk mengubah nilai frekuensi pada DTM menjadi 1 atau 0,
bernoulli_conv <- function(x){
x <- as.factor(ifelse(x > 0, 1, 0))
return(x)
}
trainbn <- apply(trainx, MARGIN = 2, bernoulli_conv)
testbn <- apply(testx, MARGIN = 2, bernoulli_conv)
Langkah terakhir yang perlu dilakukan adalah melakukan transformasi terhadap label numerik menjadi kategorikal.
convert_label <- function(x)
{
if( x == 0)
{
x <- "negative"
}
else if( x == 1)
{
x <- "postive"
}
else if( x == 2)
{
x <- "neutral"
}
else
{
x <- "none"
}
}
data_train$label_nb <- sapply(X = data_train$label, FUN = convert_label)
data_test$label_nb <- sapply(X = data_test$label, FUN = convert_label)
trainy <- as.factor(data_train$label_nb)
testy <- as.factor(data_test$label_nb)
Setelah melewati beberapa tahapan di atas, sekarang kita sudah siap untuk membuat model Naive Bayes.
nbclassifier <- naiveBayes(trainbn, trainy, laplace = 0)
Setelah melakukan serangkaian proses untuk membuat dua model yang dapat mengklasifikasikan teks berita, sekarang kita memasuki sebuah tahapan yang paling penting yaitu melakukan prediksi dan megevaluasi model yang sudah kita buat. Pada tahapan ini kita akan mengetahui bagaiamana peforma masing-masing model, selain itu kita akan melakukan komparasi dari kedua model.
test_pred <- model %>%
predict_classes(data_test_x) %>%
as.vector()
eval_lstm <- confusionMatrix(
factor(test_pred,labels = c("negative", "neutral", "positive", "none")),
factor(data_test$label,labels = c("negative", "neutral", "positive", "none"))
)
eval_lstm
## Confusion Matrix and Statistics
##
## Reference
## Prediction negative neutral positive none
## negative 359 11 4 16
## neutral 32 456 9 21
## positive 0 0 31 2
## none 15 10 12 164
##
## Overall Statistics
##
## Accuracy : 0.8844
## 95% CI : (0.8644, 0.9024)
## No Information Rate : 0.4177
## P-Value [Acc > NIR] : < 2.2e-16
##
## Kappa : 0.8239
##
## Mcnemar's Test P-Value : 5.798e-06
##
## Statistics by Class:
##
## Class: negative Class: neutral Class: positive Class: none
## Sensitivity 0.8842 0.9560 0.55357 0.8079
## Specificity 0.9579 0.9068 0.99816 0.9606
## Pos Pred Value 0.9205 0.8803 0.93939 0.8159
## Neg Pred Value 0.9375 0.9663 0.97746 0.9586
## Prevalence 0.3555 0.4177 0.04904 0.1778
## Detection Rate 0.3144 0.3993 0.02715 0.1436
## Detection Prevalence 0.3415 0.4536 0.02890 0.1760
## Balanced Accuracy 0.9211 0.9314 0.77586 0.8842
testpred <- stats::predict(nbclassifier, testbn)
eval_nb <- confusionMatrix(data = as.factor(testpred), reference = as.factor(testy))
eval_nb
## Confusion Matrix and Statistics
##
## Reference
## Prediction negative neutral none postive
## negative 321 2 11 37
## neutral 8 19 4 9
## none 29 7 150 28
## postive 48 28 38 403
##
## Overall Statistics
##
## Accuracy : 0.782
## 95% CI : (0.7569, 0.8056)
## No Information Rate : 0.4177
## P-Value [Acc > NIR] : < 2.2e-16
##
## Kappa : 0.6698
##
## Mcnemar's Test P-Value : 0.0003117
##
## Statistics by Class:
##
## Class: negative Class: neutral Class: none Class: postive
## Sensitivity 0.7906 0.33929 0.7389 0.8449
## Specificity 0.9321 0.98066 0.9318 0.8286
## Pos Pred Value 0.8652 0.47500 0.7009 0.7795
## Neg Pred Value 0.8898 0.96642 0.9429 0.8816
## Prevalence 0.3555 0.04904 0.1778 0.4177
## Detection Rate 0.2811 0.01664 0.1313 0.3529
## Detection Prevalence 0.3249 0.03503 0.1874 0.4527
## Balanced Accuracy 0.8614 0.65997 0.8354 0.8367
Untuk mengetahui bagaimana performa model, kita tidak hanya akan melihat dari nilai akurasinya saja karena jumlah observasi dari target kita tidak memiliki proporsi yang seimbang. Akan tetapi kita tidak usah khawatir, kita dapat memanfaatkan nilai presisi dan sensitifitas (recall), untuk mengetahui bagaimana performa model kita. Kedua nilai tersebut akan dikalkulasi secara bersamaan menjadi satu nilai evaluasi yang bernama F1 Score.
compare_lstm_acc <- data_frame(Model = "LSTM",
Accuracy = round((eval_lstm$overall[1] * 100), 2),
`F1 Score Neg` = 2 * (round((eval_lstm$byClass[9] * 100), 2) * round((eval_lstm$byClass[1] * 100), 2)) / (round((eval_lstm$byClass[9] * 100), 2) + round((eval_lstm$byClass[1] * 100), 2)),
`F1 Score Net` = 2 * ( round((eval_lstm$byClass[10] * 100), 2) * round((eval_lstm$byClass[2] * 100), 2)) / (round((eval_lstm$byClass[10] * 100), 2) + round((eval_lstm$byClass[2] * 100), 2)),
`F1 Score Pos` = 2 * (round((eval_lstm$byClass[11] * 100), 2) * round((eval_lstm$byClass[3] * 100), 2)) / (round((eval_lstm$byClass[11] * 100), 2) + round((eval_lstm$byClass[3] * 100), 2)),
`F1 Score Non` = 2 * (round((eval_lstm$byClass[4] * 100), 2) * round((eval_lstm$byClass[12] * 100), 2)) / (round((eval_lstm$byClass[4] * 100), 2) + round((eval_lstm$byClass[12] * 100), 2))
)
compare_nb_acc <- data_frame(Model = "Naive Bayes",
Accuracy = round((eval_nb$overall[1] * 100), 2),
`F1 Score Neg` = 2 * (round((eval_nb$byClass[9] * 100), 2) * round((eval_nb$byClass[1] * 100), 2)) / (round((eval_nb$byClass[9] * 100), 2) + round((eval_nb$byClass[1] * 100), 2)),
`F1 Score Net` = 2 * ( round((eval_nb$byClass[10] * 100), 2) * round((eval_nb$byClass[2] * 100), 2)) / (round((eval_nb$byClass[10] * 100), 2) + round((eval_nb$byClass[2] * 100), 2)),
`F1 Score Pos` = 2 * (round((eval_nb$byClass[11] * 100), 2) * round((eval_nb$byClass[3] * 100), 2)) / (round((eval_nb$byClass[11] * 100), 2) + round((eval_nb$byClass[3] * 100), 2)),
`F1 Score Non` = 2 * (round((eval_nb$byClass[4] * 100), 2) * round((eval_nb$byClass[12] * 100), 2)) / (round((eval_nb$byClass[4] * 100), 2) + round((eval_nb$byClass[12] * 100), 2))
)
rbind(compare_lstm_acc, compare_nb_acc)
Jika dilihat dari hasil komparasi di atas, kita mengetahui bahwa model LSTM lebih unggul hampir disetiap peforma, untuk setiap target variabelnya. Pada kasus ini, semua target variabel dianggap penting, karena setiap sentimen untuk berita emas akan mempengaruhi keputusan seseorang dalam berinvestasi emas.
Sedikit catatan di sini, walaupun model LSTM lebih unggul pada kasus ini, bukan berarti model Naive Bayes itu jelek atau tidak bisa digunakan dalam kebutuhan kita nantinya. Selain dilihat dari metrik evaluasi, kita juga bisa menentukan model yang akan kita gunakan bedasarkan kebutuhan.
Salah contoh kapan kita memerlukan model LSTM dalam melakukan analisis sentimen adalah ketika kita perlu memperhatikan letak atau posisi kata dalam sebuah kalimat.
Kalimat 1 (Sentimen Positif): Pelayanan di restoran ini sangat baik dan tidak mengecewakan
Kalimat 2 (Sentimen Negatif): Pelayanan di restoran ini tidak baik dan mengecewakan
Dari dua kalimat diatas, penempatakan posisi kata tidak sangat menentukan apakah kalimat tersebut memiliki aspek sentimen positif atau negatif. Proses pembelajaran posisi sebuah kata dalam kalimat bisa dilakukan dengan memanfaatkan embedding layer dari model LSTM.
Salah satu contoh kapan kita menggunakan model Naive Bayes adalah ketika kita sudah mengetahui beberapa kata yang sangat dominan dalam sebuah kelas target yang ingin kita prediksi, sehingga kita bisa menggunakan kata tersebut sebagai sebuah kata kunci utama untuk memprediksi. Dari hasil explorasi karakteristik untuk masing-masing aspek sentimen, kita mengetahui bahwa disetiap berita yang mengandung unsur kata fall pasti berita tersebut mengandung aspek negatif dan untuk setiap berita yang mengandung unsur kata gains pasti berita tersebut mengandung aspek positif.
Selain itu juga proses komputasi dengan model Naive Bayes tidak terlalu memakan banyak tenaga komputasi, sehingga ketika kita menghadapi data yang cukup banyak mungkin kita bisa menggunakan model Naive Bayes terlebih dahulu, dan jika memang hasilnya sudah memenuhi ekspektasi yang kita inginkan, kita tidak perlu membuat model yang jauh lebih kompleks yang memerlukan banyak tenaga komputasi.
Di sini kita dapat menarik sebuah kesimpulan bahwa model yang paling baik dalam mengklasifikasikan sentiment dari sebuah berita yang membahas harga emas adalah model LSTM. Walaupun memang memerlukan proses yang lebih rumit dan memakan waktu yang lebih lama tapi jika dilihat dari peforma yang dihasilkan memang memiliki perbedaan yang cukup signifikan dengan model pembandingnya model Naive Bayes.
Dalam kasus ini, implementasi dari model LSTM untuk melakukan Aspect Based Sentiment Analysis akan sangat berguna untuk investor emas dan media. Dari sudut pandang investor emas, para investor emas biasanya juga suka memanfaatkan berita untuk membantu mereka untuk menentukan apakah mereka akan menambah investasi atau menjual investasi emas mereka. Jika sebuah berita mengandung unsur negatif mengenai emas, berita tersebut akan memberikan dampak terhadap harga emas dipasaran, begitu juga sebaliknya. Maka dari itu, implementasi dari model LSTM ini dapat dimanfaatkan juga oleh media untuk lebih menekankan apakah berita yang disajikan memiliki aspek positif, negatif, netral atau tidak memiliki aspek apa-apa. Jika ada sebuah media yang dapat menekankan aspek beritanya terhadap pembaca atau penonton berita tersebut, para penyimaknya akan sangat terbantu apa lagi jika aspek yang disampaikannya cukup akurat.
Model LSTM yang sudah kita buat sebenarnya masih bisa dikembangkan lebih lanjut lagi dengan melakukan beberapa cara berikut ini,
Referensi
1. LSTM for Text Classification
2. Sentiment Analysis: A Definitive Guid
3. Pengenalan Long Short Term Memory (LSTM) dan Gated Recurrent Unit (GRU) – RNN Bagian 2
4.Text Classification With LSTM
5. The 5 Step Life-Cycle for Long Short-Term Memory Models in Keras
6. Overview of various Optimizers in Neural Networks
7. Illustrated Guide to LSTM’s and GRU’s: A step by step explanation