Proposal Data Career Day 16
Background
Perkembangan teknologi informasi yang pesat membuat sebuah informasi tentang suatu peristiwa tersaji dengan sangat cepat. Dahulu ketika kita ingin mendapatkan sebuah informasi atau berita kita bisa mendapatkannya melalui koran, radio, maupun televisi. Saat ini kita berada di era digital, kita dapat mendapatkan berita tersebut dengan mudah hanya dengan mengetikan kata kunci yang diinginkan pada mesin pencarian. Untuk satu topik atau peristiwa akan muncul berbagai berita dengan konten yang sama namun dengan sentimen yang berbeda. Berita-berita tersebut tersebar di berbagai website berita dan sebagian berita tersebut berbentuk sebuah teks. Dari berbagai data berita teks tersebut sekitar 80% sampai 85% adalah dalam format tidak terstruktur (Bridge, 2011). Tentunya sebuah perusahaan media memerlukan strategi pemasaran untuk produk-produk berita yang ditulis, salah satunya dapat menerapkan sebuah startegi digital marketing.
Digital marketing adalah suatu strategi pemasaran menggunakan media digital dan internet. Konsep dan penerapan digital marketing untuk mendongkrak pemasaran produk dari suatu usaha. Dimana pada perusahaan penyedia berita ingin berita yang sudah disajikan/dihasilkan memiliki jumlah pembaca yang banyak. Salah satu contoh dari media digital adalah situs berita online, media sosial, blog, dll. Tentunya dalam melakukan pemasaran di media digital kita memerlukan sebuah judul maupun headline dari berita yang dihasilkan. Tetapi apakah hal tersebut sudah memberikan sentimen yang tepat terhadap berita yang kita tulis? Untuk mengetahui hal tersebut kita bisa memanfaatkan sebuah analisa, yaitu analisa sentimen.
Analisa sentimen merupakan proses memahami,mengestrak dan mengolah data tekstual secara otomatis untuk mendapatkan informasi sentimen yang terkandung dalam suatu teks. Analisis sentimen dilakukan untuk melihat kecenderungan opini terhadap sebuah objek oleh seseorang, apakah cenderung berpandangan negatif atau positif. Selain dapat melihat kecenderungan dari data teks tersebut, kita bisa mendapatkan atau melakukan ekstrasi keyword yang dapat digunakan dalam SEO. SEO atau Search Engine Optimization adalah sebuah teknik untuk mengoptimasi website agar mendapat ranking teratas di hasil pencarian pada search engine. Dengan SEO, website akan mudah orang temukan sehingga berpotensi meningkatkan traffic pengunjung.
Problem Statement & Project Idea
Dalam ingin meningkatkan jumlah traffic pembaca pada berita yang kita tulis, kita harus memastikan sentimen yang kita tulis sudah sesuai dengan topiknya. Maka dari itu, ide dari project ini adalah membuat model machine learning yang dapat mengklasifikasi sentimen sebuah berita dan memberikan sebuah keluaran hasil interpretasi analisa sentimen sehingga bisa digunakan untuk evaluasi penulisan beserta dengan rekomendasi keyword.
Problem Scope
Pada project ini akan menggunakan data Title and Headline Sentiment Prediction dari situs Kaggle. Dataset ini mengandung informasi sebagai berikut:
| Kolom | Deskripsi |
|---|---|
| IDlink | Unique id tiap post |
| Title | Judul dari post |
| Headline | Headline dari post |
| Source | Sumber berita |
| Topic | Kategori topik |
| PublishDate | Tanggal di publish nya berita |
| Berada di facebook atau tidak | |
| GooglePlus | Berada di GooglePlus atau tidak |
| Berada di LinkedIn atau tidak | |
| SentimentTitle | Nilai sentiment pada judul |
| SentimentHeadline | Nilai sentiment pada headline |
Informasi yang akan digunakan lebih lanjut pada project ini adalah
kolom Title, Headline,
SentimentTitle dan SentimentHeadline.
Selanjutnya, kebutuhan dalam pembuatan model machine learning untuk
melakukan klasifikasi sentimen pada sebuah berita, kolom
SentimentTitle dan SentimentHeadline akan
dilakukan labeling. Model machine learning yang akan digunakan adalah
Naive Bayes, Random Forest, dan LSTM.
Output
Keluaran dari project ini adalah sebuah dashboard, yang akan dibuat dengan R shiny. Pada dashboard ini akan terdapat satu bagian yaitu sentiment analysis, dimana pada bagian tersebut adalah inti dari project ini.
Secara garis besar pada dashboard ini terbagi menjadi 2 bagian, yaitu input dan Hasil. Tiap bagian tersebut memiliki beberapa fitur yang akan dijelaskan sebagai berikut:
Input
Pada bagian ini terdapat 3 buah inputan yang akan digunakan untuk
analisa, yaitu 2 buah textInput dan 1 buah
radioButtons:
- Pada
textInputakan digunakan untuk memasukan judul dan berita yang ingin kita analisa menggunakan model yang sudah dibuat. - Sedangkan pada
radioButtonsakan diisi dengan tujuan dari berita yang ditulis memiliki sentiment positive atau negative, yang nantinya akan digunakan sebagai kontrol dengan hasil klasifikasi dari model. Sebagai contoh ketika ada sebuah berita terkait bencana alam yang merupakan sebuah berita duka atau memberikan sentimen yang negatif maka kita akan mengisi pada inputan sentiment goal adalah negatif.
Hasil
Pada bagian ini terdapat 3 output, yaitu analysis result, classification result dan keyword recommendation.
- Pada bagian analysis result akan memberikan informasi dari interpretasi metode LIME pada judul dan headline dari berita, sehingga user dapat melakukan evaluasi kata mana yang tidak sesuai dengan tujuan dari berita tersebut.
- Tentunya pada bagian ini terdapat hasil klasifikasi sentimen menggunakan model yang sudah dibuat.
- Sedangkan pada bagian keyword recommendation akan menampilkan hasil ektrasi keyword berdasarkan dari teks inputan yang akan muncul ketika hasil klasifikasi sentimen sudah sesuai dengan sentiment goal. Lanjutan dari contoh pada bagian input, Seperti yang kita ketahui ketika berita yang memberikan informasi terkait suatu bencana alam akan merangkum beberapa informasi seperti kerugian, korban jiwa, atau kerusakan yang terjadi. Dimana informasi-informasi tersebut sudah tepat dengan tujuan dari penyampaian berita dengan topik bencana alam tetapi akan memberikan hasil klasifikasi sentimen yang negatif. Karena sudah sesuai antara hasil klasifikasi dan sentiment goal maka akan menghasilkan sebuah keyword recommendation.
Business Impact
Business impact yang diharapkan oleh penulis sebagai berikut:
- Project ini dapat mengklasifikasi sentimen pada judul dan headline sebuah berita.
- Dapat memberikan sebuah masukan/evaluasi yang merupakan hasil dari metode LIME sehingga jika hasil dari klasifikasi sentimen tidak sesuai dengan harapan sentimen pada berita tersebut kita dapat mengetahui kata/bagian mana yang perlu diperbaiki.
- Dapat menghasilkan rekomendasi keyword menggunakan algoritma RAKE, sehingga dapat digunakan lebih lanjut untuk membuat strategi marketing.
- Project ini kedepannya dapat dikembangkan untuk industri lain, seperti untuk kegiatan marketing suatu produk pada e-commerce. Dalam pengembangan tersebut tentunya diperlukan data-data yang mendukung dalam pembuatan model machine learning.
Data Wrangling & Exploratory Data Analysis
Library
Berikut adalah library yang digunakan untuk data wrangling dan text pre-processing pada project ini :
# Data Wrangling
library(tidyverse)
library(wordcloud)
# Text Pre-Processing
library(tm)
library(textclean)
library(stringr)
library(caret)Import Data
Langkah pertama adalah melakukan import dataset Title and Headline
Sentiment Prediction, dalam pembuat model machine learning ini kita akan
memasukan file train_file.csv menggunakan fungsi
read.csv() dah menyimpannya pada variabel
news.
news <- read.csv('data/train_file.csv')
head(news)Untuk melihat struktur data secara general kita dapat menggunakan
fungsi glimpse() dari library dplyr.
glimpse(news)#> Rows: 55,932
#> Columns: 11
#> $ IDLink <chr> "Tr3CMgRv1N", "Wc81vGp8qZ", "zNGH03CrZH", "3sM1H0W8t…
#> $ Title <chr> "Obama Lays Wreath at Arlington National Cemetery", …
#> $ Headline <chr> "Obama Lays Wreath at Arlington National Cemetery. P…
#> $ Source <chr> "USA TODAY", "Bloomberg", "Bloomberg", "RTT News", "…
#> $ Topic <chr> "obama", "economy", "economy", "economy", "economy",…
#> $ PublishDate <chr> "2002-04-02 00:00:00", "2008-09-20 00:00:00", "2012-…
#> $ Facebook <int> -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -…
#> $ GooglePlus <int> -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -…
#> $ LinkedIn <int> -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -…
#> $ SentimentTitle <dbl> 0.00000000, 0.20833333, -0.42521003, 0.00000000, 0.0…
#> $ SentimentHeadline <dbl> -0.053300179, -0.156385811, 0.139754249, 0.026064302…
Dapat pada hasil diatas bahwa data news memiliki 55,932
observasi/baris dan 11 kolom, untuk deskripsi kolom dapat dilihat pada
tabel dibawah:
| Kolom | Deskripsi |
|---|---|
| IDlink | Unique id tiap post |
| Title | Judul dari post |
| Headline | Headline dari post |
| Source | Sumber berita |
| Topic | Kategori topik |
| PublishDate | Tanggal di publish nya berita |
| Berada di facebook atau tidak | |
| GooglePlus | Berada di GooglePlus atau tidak |
| Berada di LinkedIn atau tidak | |
| SentimentTitle | Nilai sentiment pada judul |
| SentimentHeadline | Nilai sentiment pada headline |
Tidak lupa juga kita harus melakukan pengecekan terhadap missing
value pada data news, untuk melakukan pengecekan tersebut
kita dapat mengkombinasikan dua fungsi yaitu is.na() dan
colSums().
colSums(is.na(news))#> IDLink Title Headline Source
#> 0 0 0 0
#> Topic PublishDate Facebook GooglePlus
#> 0 0 0 0
#> LinkedIn SentimentTitle SentimentHeadline
#> 0 0 0
Pada data news tidak memiliki missing values,
selanjutnya kita juga melakukan pengecekan duplicate value pada data
kita menggunakan kombinasi fungsi duplicated() dan
sum().
sum(duplicated(news)) #> [1] 0
Data kita tidak memiliki observasi yang merupakan duplikasi dari observasi lain, dimana kita dapat melanjutkan ke tahap selanjutnya yaitu melakukan labeling sentiment.
Sentiment Labeling
Kedepannya kita hanya akan menggunakan 4 kolom yaitu
Title, Headline. SentimentTitle,
dan SentimentHeadline untuk melakukan subsetting pada
keempat kolom tersebut kita akan menggunakan fungsi
select(). Selanjutnya kita akan membuat kolom baru yang
berisikan informasi label nilai sentimen menggunakan fungsi
mutate() dalam pembagian label tersebut kita akan dibantu
dengan fungsi ifelse() jika nilai sentimen lebih besar dari
0 (> 0) maka akan diberikan label ‘positive’, jika kurang dari 0
(< 0) akan diberikan label ‘negative’ sedangkan jika nila sentimennya
sama dengan 0 maka labelnya adalah ‘neutral’. Kolom label tersebut akan
kita ubah tipe data nya menjadi factor menggunakan fungsi
as.factor(). Dikarenakan kita sudah memiliki kolom yang
berisikan informasi sentimen berupa label, maka diakhir kita akan
mendrop kolom SentimentHeadline dan
SentimentTitle menggunakan fugnsi select()
agar tidak terdapat informasi yang mirip antar kolom pada data kita.
Fungsi-fungsi tersebut akan digunakan menggunakan metode
piping dari library dplyr agar memudahkan
kita.
news <- news %>%
select(Title, Headline, SentimentTitle, SentimentHeadline) %>%
mutate(SentimentTitleLable = as.factor(ifelse(SentimentTitle > 0, 'positive',
ifelse(SentimentTitle == 0, 'neutral', 'negative'))),
SentimentHeadlineLable = as.factor(ifelse(SentimentHeadline > 0, 'positive',
ifelse(SentimentHeadline == 0, 'neutral', 'negative')))) %>%
select(-c(SentimentHeadline, SentimentTitle))
head(news)Class Propotion
Dalam pembuatan classfication machine learning, kita perlu untuk
mengetahui proporsi kelas/label apakah sudah balance atau belum
dikarenakan akan mempengaruhi model yaitu condong ke salah satu kelas.
Untuk mengetahui proporsi kelas kita akan menggunakan fungsi
table() untuk menjumlahkan jumlah data per kelas dan fungsi
prop.table() untuk mengubahnya kedalam satuan persen.
Proporsi kelas pada kolom SentimentTitleLable sebagai
berikut :
news$SentimentTitleLable %>%
table() %>%
prop.table() #> .
#> negative neutral positive
#> 0.4095866 0.2021383 0.3882750
Sedangkan proporsi kelas pada kolom
SentimentHeadlineLable sebagai berikut :
news$SentimentHeadlineLable %>%
table() %>%
prop.table()#> .
#> negative neutral positive
#> 0.57121147 0.03046557 0.39832296
Dapat dilihat dari hasil proporsi kelas data kita belum balance atau seimbang, sehingga kedepannya kita perlu melakukan downsampling atau upsampling untuk membuat seimbang kelas nya.
Text Characteristics
Dalam rangka melakukn eksplorasi data, kita dapat melihat kata mana
yang paling sering muncul pada tiap label. Untuk memudahkan kita untuk
melakukan hal tersebut kita akan menggunakan fungsi
wordcloud() dari library wordcloud yang akan
menghasilkan sebuah plot yang nantinya menampilkan 20 kata dengan
frekuensi tertinggi.
- Karakteristik teks pada kolom
Titledengan label positive
title_pos <- news %>%
filter(SentimentTitleLable == 'positive') %>%
select(Title)
wordcloud(words = as.matrix(title_pos),
max.words = 20,
scale = c(2.5, 1.25),
random.order = F,
rot.per = 0.5,
colors = brewer.pal(2, 'Set1'))- Karakteristik teks pada kolom
Titledengan label neutral
title_neu <- news %>%
filter(SentimentTitleLable == 'neutral') %>%
select(Title)
wordcloud(words = as.matrix(title_neu),
max.words = 20,
scale = c(2.5, 1.25),
random.order = F,
rot.per = 0.5,
colors = brewer.pal(2, 'Set1'))- Karakteristik teks pada kolom
Titledengan label negative
title_neg <- news %>%
filter(SentimentTitleLable == 'negative') %>%
select(Title)
wordcloud(words = as.matrix(title_neg),
max.words = 20,
scale = c(2.5, 1.25),
random.order = F,
rot.per = 0.5,
colors = brewer.pal(2, 'Set1'))- Karakteristik teks pada kolom
Headlinedengan label positive
headline_pos <- news %>%
filter(SentimentHeadlineLable == 'positive') %>%
select(Headline)
wordcloud(words = as.matrix(headline_pos),
max.words = 20,
scale = c(2.5, 1.25),
random.order = F,
rot.per = 0.5,
colors = brewer.pal(2, 'Set1'))- Karakteristik teks pada kolom
Headlinedengan label neutral
headline_neu <- news %>%
filter(SentimentHeadlineLable == 'neutral') %>%
select(Headline)
wordcloud(words = as.matrix(headline_neu),
max.words = 20,
scale = c(2.5, 1.25),
random.order = F,
rot.per = 0.5,
colors = brewer.pal(2, 'Set1'))- Karakteristik teks pada kolom
Headlinedengan label negative
headline_neg <- news %>%
filter(SentimentHeadlineLable == 'negative') %>%
select(Headline)
wordcloud(words = as.matrix(headline_neg),
max.words = 20,
scale = c(2.5, 1.25),
random.order = F,
rot.per = 0.5,
colors = brewer.pal(2, 'Set1'))Jika dilihat dari hasil plot bahwa kata yang sering muncul pada kolom
Title dan Headline adalah
economy, microsoft, dan
obama.
HTML Entity Check
Selanjutnya kita akan melakukan pengecekan pada data kita apakah
terdapat HTML entity, untuk melakukan tersebut kita
akan menggunakan fungsi mutate() untuk membuat kolom baru
yang menampung informasi apakah data kita memiliki HTML entity atau
tidak. Sedangkan untuk nilai pada kolom tersebut kita akan menggunakan
fugsi str_extract() dari library stringr.
html_pattern <- '&([a-z0-9]+|#[0-9]{1,6}|#x[0-9a-fA-F]{1,6});'
check_html <- news %>% select(Title, Headline)
check_html <- check_html %>%
mutate(
contentHTML_title = str_extract(Title, html_pattern),
contentHTML_headline = str_extract(Headline, html_pattern)
)
head(check_html)Kita dapat menggunakan fungsi unique() untuk melihat
HTML entity pada data kita.
unique(check_html$contentHTML_title)#> [1] NA "&" """ ">"
unique(check_html$contentHTML_headline)#> [1] NA """ "&" "·" ">" "’" "("
#> [8] "“" "—"
Jumlah observasi yang memiliki HTML entity sebagai berikut :
sum(!is.na(check_html$contentHTML_title))#> [1] 619
sum(!is.na(check_html$contentHTML_headline))#> [1] 5267
Kedepannya kita akan menghilangkan HTML entity ini pada tahap data preparation.
Url Check
Kita juga akan melakukan pengecekan apakah data kita memiliki sebuah url, untuk melakukan hal ini sama seperti pada tahap pengecekan HTML entity.
url_pattern <- 'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\(\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+'
check_url <- news %>% select(Title, Headline)
check_url <- check_url %>%
mutate(
contentURL_title = str_extract(Title, url_pattern),
contentURL_headline = str_extract(Headline, url_pattern)
)
head(check_url)Berikut adalah url yang terdapat data kita.
unique(check_url$contentURL_title)#> [1] NA
unique(check_url$contentURL_headline)#> [1] NA
#> [2] "http://www.prweb.com/releases/2016/03/prweb13238571.htm"
#> [3] "http://www.thestar.com.my"
#> [4] "https://t.co/xPcry19sS8."
#> [5] "http://www.imemc.org,"
#> [6] "http://gawker.com/active-shooter."
#> [7] "http://www.prweb.com/releases/2015/11/prweb13104594.htm"
#> [8] "https://t.co/njlirCxPkt."
#> [9] "http://bit.ly/1jAfZCz"
#> [10] "http://www.prweb.com/releases/2015/12/prweb13113805.htm"
#> [11] "http://www.prweb.com/releases/2015/12/prweb13115886.htm"
#> [12] "https://t.co/42vPUfgCgM."
#> [13] "http://www.prweb.com/releases/Economic/Arts/prweb13123894.htm"
#> [14] "http://bit.ly/1mqsbaU"
#> [15] "http://www.prweb.com/releases/2015/12/prweb13134571.htm"
#> [16] "https://t.co/eMSrr1bhlC."
#> [17] "https://t.co/ZZ6hHRfgIw"
#> [18] "http://www.youtube.com/embed/A3rKavB0krs"
#> [19] "https://t.co/RUPbcev5jY"
#> [20] "http://www.prweb.com/releases/2016/01/prweb13148253.htm"
#> [21] "http://abc13"
#> [22] "http://www.prweb.com/releases/2016/01/prweb13150208.htm"
#> [23] "http://indy.st/1RdpQwX"
#> [24] "http://goo.gl/8Yu3g4V"
#> [25] "http://www.prweb.com/releases/2016/01/prweb13167807.htm"
#> [26] "https://t.co/JJ3kATYXJ7."
#> [27] "https://t.co/HZcWvsWlZ3."
#> [28] "http://yusc.ca/mural/palestinian-roots/)"
#> [29] "https://t.co/grG0RwlRNl."
#> [30] "http://www.prweb.com/releases/2016/02/prweb13196567.htm"
#> [31] "http://bit.ly/20tllni"
#> [32] "https://en.wikipedia.org/wiki/Chairman_of_the_"
#> [33] "https://t.co/"
#> [34] "http://www.prweb.com/releases/2016/02/prweb13227264.htm"
#> [35] "http://www.prweb.com/releases/2016/02/prweb13225850.htm"
#> [36] "http://www.bbc.com/news/world-middle-east-33521655"
#> [37] "http://www.prweb.com/releases/2016/02/prweb13231017.htm"
#> [38] "http://www.prweb.com/releases/2016/02/prweb13237356.htm"
#> [39] "https://www.fitchratings.com/creditdesk/reports/report_frame.cfm?rpt_id=878254"
Jumlah observasi yang mengandung url berjumlah :
sum(!is.na(check_url$contentURL_title))#> [1] 0
sum(!is.na(check_url$contentURL_headline))#> [1] 53
Data Preparation
Berikut adalah 6 observasi teratas pada data news :
news$Headline %>% head()#> [1] "Obama Lays Wreath at Arlington National Cemetery. President Barack Obama has laid a wreath at the Tomb of the Unknowns to honor"
#> [2] "Tim Haywood, investment director business-unit head for fixed income at Gam, discusses the China beige book and the state of the economy."
#> [3] "Nouriel Roubini, NYU professor and chairman at Roubini Global Economics, explains why the global economy isn't facing the same conditions"
#> [4] "Finland's economy expanded marginally in the three months ended December, after contracting in the previous quarter, preliminary figures from Statistics Finland showed Monday. "
#> [5] "Tourism and public spending continued to boost the economy in January, in light of contraction in private consumption and exports, according to the Bank of Thailand data. "
#> [6] "Over 100 attendees expected to see latest version of Microsoft Dynamics SL and Dynamics GP (PRWeb February 29, 2016) Read the full story at http://www.prweb.com/releases/2016/03/prweb13238571.htm "
Dapat dilihat bahwa data kita perlu dilakukan beberapa tahap preparation sebelum digunakan untuk pembuatan model machine learning.
Text Cleansing
Pada tahap ini kita akan mecoba mempersiapkan data news
kita, dikarenkan data ini merupakan data yang tidak terstruktur berupa
teks maka kita harus melaukan beberapa step cleansing. Sebagai contoh
untuk text cleansing kita akan menggunakan variabel
example.
example <- 'WASHINGTON (AP) — President Barack Obama said Thursday investigators are continuing to search for the motives of the people who killed 14 people in a spray of + bullets in California and called on Americans to "search ourselves as a society" to find a way to curb gun violence. Over 100 attendees expected to see latest version of Microsoft Dynamics SL and Dynamics GP (PRWeb February 29, 2016) Read the full story at http://www.prweb.com/releases/2016/03/prweb13238571.htm '
example#> [1] "WASHINGTON (AP) — President Barack Obama said Thursday investigators are continuing to search for the motives of the people who killed 14 people in a spray of + bullets in California and called on Americans to "search ourselves as a society" to find a way to curb gun violence. Over 100 attendees expected to see latest version of Microsoft Dynamics SL and Dynamics GP (PRWeb February 29, 2016) Read the full story at http://www.prweb.com/releases/2016/03/prweb13238571.htm "
- Lower Case
Step pertama yang akan kita lakukan ada membuat data teks kita
menjadi lower case, kali ini kita akan menggunakan fungsi
str_to_lower() dari library stringr
result <- example %>% str_to_lower()
result#> [1] "washington (ap) — president barack obama said thursday investigators are continuing to search for the motives of the people who killed 14 people in a spray of + bullets in california and called on americans to "search ourselves as a society" to find a way to curb gun violence. over 100 attendees expected to see latest version of microsoft dynamics sl and dynamics gp (prweb february 29, 2016) read the full story at http://www.prweb.com/releases/2016/03/prweb13238571.htm "
- Remove HTML Entities
Seperti yang kita temukan pada tahap EDA, data kita memiliki HTML
entity yang perlu kita hilangkan. Untuk menghilangkan nya kita akan
menggunan fungsi str_replace_all() dengan pattern yang
sudah tersimpan pada variabel html_pattern.
result <- result %>% str_replace_all(html_pattern, " ")
result#> [1] "washington (ap) — president barack obama said thursday investigators are continuing to search for the motives of the people who killed 14 people in a spray of + bullets in california and called on americans to search ourselves as a society to find a way to curb gun violence. over 100 attendees expected to see latest version of microsoft dynamics sl and dynamics gp (prweb february 29, 2016) read the full story at http://www.prweb.com/releases/2016/03/prweb13238571.htm "
- Remove URL
Pada URL akan kita hilangkan juga menggunakan fungsi
str_replace_all() dengan pattern
url_pattern.
result <- result %>% str_replace_all(url_pattern, " ")
result#> [1] "washington (ap) — president barack obama said thursday investigators are continuing to search for the motives of the people who killed 14 people in a spray of + bullets in california and called on americans to search ourselves as a society to find a way to curb gun violence. over 100 attendees expected to see latest version of microsoft dynamics sl and dynamics gp (prweb february 29, 2016) read the full story at "
- Replace Word Elongation
Pada step ini kita ingin merubah kata yang terjadi elongation atau
pemanjangan seperti ‘waiiit’ akan di ganti menjadi ‘wait’. Walaupun pada
data news berisi informasi berita yang biasanya sudah
berbentuk bahasa formal tetapi tetap ada kemungkinan ada human error
pada teks tersebut. Untuk melakukan hal tersebut kita dapat menggunakan
fungsi replace_word_elongation() dari library
textclean.
result <- result %>% replace_word_elongation()
result#> [1] "washington (ap) — president barack obama said thursday investigators are continuing to search for the motives of the people who killed 14 people in a spray of + bullets in california and called on americans to search ourselves as a society to find a way to curb gun violence. over 100 attendees expected to see latest version of microsoft dynamics sl and dynamics gp (prweb february 29, 2016) read the full story at "
- Replace Contraction
Sedangkan pada step ini, kita ingin merubah sebuah kata singkatan
seperti ‘w8’ menjadi ‘wait’. Langkah ini merupakan langkah preventif
untuk menghindari human error pada data teks. Kita dapat menggunakan
fungsi replace_contraction().
result <- result %>% replace_contraction()
result#> [1] "washington (ap) — president barack obama said thursday investigators are continuing to search for the motives of the people who killed 14 people in a spray of + bullets in california and called on americans to search ourselves as a society to find a way to curb gun violence. over 100 attendees expected to see latest version of microsoft dynamics sl and dynamics gp (prweb february 29, 2016) read the full story at "
- Remove Numerical
Selanjutnya kita akan menghilangkan angka, dikarenakan pada
classfication machine learning akan melakukan klasifikasi berdasarkan
kata. Untuk menghilangkan angka kita dapat menggunakan fungsi
str_replace_all().
result <- result %>% str_replace_all("[[:digit:]]", " ")
result#> [1] "washington (ap) — president barack obama said thursday investigators are continuing to search for the motives of the people who killed people in a spray of + bullets in california and called on americans to search ourselves as a society to find a way to curb gun violence. over attendees expected to see latest version of microsoft dynamics sl and dynamics gp (prweb february , ) read the full story at "
- Remove Punctuation
Kita juga perlu untuk menghilangkan tanda baca, dikarenakan tidak
akan digunakan dalam pembuatan model. Untuk menghilangkannya kita akan
menggunakan kembali fungsi str_replace_all().
result <- result %>% str_replace_all("[[:punct:]]", " ")
result#> [1] "washington ap president barack obama said thursday investigators are continuing to search for the motives of the people who killed people in a spray of + bullets in california and called on americans to search ourselves as a society to find a way to curb gun violence over attendees expected to see latest version of microsoft dynamics sl and dynamics gp prweb february read the full story at "
- Remove Symbol
Jika kita lihat pada hasil diatas, data tersebut masih memiliki
sebuah symbol + yang harus kita hilangkan. Untuk
menghilangkan nya kita akan menggunakan fungsi
replace_symbol() dari library textclean.
result <- result %>% replace_symbol()
result#> [1] "washington ap president barack obama said thursday investigators are continuing to search for the motives of the people who killed people in a spray of bullets in california and called on americans to search ourselves as a society to find a way to curb gun violence over attendees expected to see latest version of microsoft dynamics sl and dynamics gp prweb february read the full story at "
- Remove Stop Words
Selanjutnya kita akan menghapus stopword atau kata kata sambung yang
sering muncul dan biasanya tidak meaningful. List stopword yang kita
akan hilangkan didapatkan dari fungsi stopwords() dari
library tm, lalu akan dijadikan sebuah pattern regex. Untuk
menghilangkannya kita akan menggunakan fungsi
str_replace_all().
stopwords_regex <- paste(stopwords('en'), collapse = '\\b|\\b')
stopwords_regex <- paste0('\\b', stopwords_regex, '\\b')
result <- result %>% str_replace_all(stopwords_regex, ' ')
result#> [1] "washington ap president barack obama said thursday investigators continuing search motives people killed people spray bullets california called americans search society find way curb gun violence attendees expected see latest version microsoft dynamics sl dynamics gp prweb february read full story "
- Stem Word
Setelah membersihkan stopword kita kan melakukan pemotong kata
menjadi kata dasarnya atau stemming. Misalnya walking,
walked, walks menjadi walk. Kita akan
menggunakan fungsi stemDocument() dari library
tm.
result <- stemDocument(result, language = 'english')
result#> [1] "washington ap presid barack obama said thursday investig continu search motiv peopl kill peopl spray bullet california call american search societi find way curb gun violenc attende expect see latest version microsoft dynam sl dynam gp prweb februari read full stori"
- Remove Whitespace
Langkah terakhir adalah menghapus whitespace berlebih. hal ini diperlukan karena pada proses tokenizing (selanjutnya), kata akan dipotong berdasarkan karakter spasi. Untuk melakukan hal tersebut kita akan menggunakan fungsi `replace_white()``
result <- result %>% replace_white()
result #> [1] "washington ap presid barack obama said thursday investig continu search motiv peopl kill peopl spray bullet california call american search societi find way curb gun violenc attende expect see latest version microsoft dynam sl dynam gp prweb februari read full stori"
Dari langkah-langkah text cleansing diatas, akan kita jadikan sebuah
fungsi bernama text_cleansing agar memudahkan
kedepannya.
text_cleansing <- function(text){
# create pattern
html_pattern <- '&([a-z0-9]+|#[0-9]{1,6}|#x[0-9a-fA-F]{1,6});'
url_pattern <- 'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\(\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+'
stopwords_regex <- paste(stopwords('en'), collapse = '\\b|\\b')
stopwords_regex <- paste0('\\b', stopwords_regex, '\\b')
# cleansing
new_data <- text %>%
str_to_lower() %>%
str_replace_all(html_pattern, ' ') %>%
str_replace_all(url_pattern, " ") %>%
replace_word_elongation() %>%
replace_contraction() %>%
str_replace_all("[[:digit:]]", " ") %>%
str_replace_all("[[:punct:]]", " ") %>%
replace_symbol() %>%
str_replace_all(stopwords_regex, ' ') %>%
stemDocument(language = 'english') %>%
replace_white()
return(new_data)
}Selanjutnya kita akan menggunakan fungsi text_cleansing
yang sudah dibuat untuk diaplikasikan pada data news.
news_clean <- news %>%
mutate(
Title = Title %>% text_cleansing(),
Headline = Headline %>% text_cleansing()
) Berikut adalah 50 baris teratas hasil dari text cleansing pada data
news.
head(news_clean,50)Jika kita lihat pada kolom Title baris 14 dan 15
terdapat simbol £, dan pada kolom Headline baris 50
terdapat simbol ® dan ™. Maka dari kita harus menambahkan fungsi
str_replace_all() pada fungsi text_cleansing
untuk menghapus simbol-simbol tersebut.
text_cleansing <- function(text){
# create pattern
html_pattern <- '&([a-z0-9]+|#[0-9]{1,6}|#x[0-9a-fA-F]{1,6});'
url_pattern <- 'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\(\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+'
stopwords_regex <- paste(stopwords('en'), collapse = '\\b|\\b')
stopwords_regex <- paste0('\\b', stopwords_regex, '\\b')
other_symbol_pattern <- "[^A-Za-z_0-9]"
# cleansing
new_data <- text %>%
str_to_lower() %>%
str_replace_all(html_pattern, ' ') %>%
str_replace_all(url_pattern, " ") %>%
replace_word_elongation() %>%
replace_contraction() %>%
str_replace_all("[[:digit:]]", " ") %>%
str_replace_all("[[:punct:]]", " ") %>%
replace_symbol() %>%
str_replace_all(other_symbol_pattern, " ") %>%
str_replace_all(stopwords_regex, ' ') %>%
stemDocument(language = 'english') %>%
replace_white()
return(new_data)
}Lalu kita aplikasikan kembali pada data news
news_clean <- news %>%
mutate(
Title = Title %>% text_cleansing(),
Headline = Headline %>% text_cleansing()
)
head(news_clean,50)Cross-Validation
Setelah dilakukan text cleansing, kita akan melakukan
cross-validation pada data news_clean dengan pembagian 80%
untuk data train dan 20% data test.
set.seed(121)
row_data <- nrow(news_clean)
index <- sample(row_data, row_data*0.8)
news_train <- news[index,]
news_test <- news[-index,]Kita juga akan memisahkan antara data Title dan
Headline yang kedepannya akan dibuatkan model terpisah.
title_train <- news_train %>% select(Title, SentimentTitleLable)
title_test <- news_test %>% select(Title, SentimentTitleLable)
headline_train <- news_train %>% select(Headline, SentimentHeadlineLable)
headline_test <- news_test %>% select(Headline, SentimentHeadlineLable)Class Imbalance
Seperti yang kita ketahui pada tahap EDA, data news
memiliki proporsi kelas yang tidak seimbang. Maka dari itu kita perlu
melakukan downsampling agar proporsi kelas nya seimbang yang akan
berpengaruh terhadap model kita.
Title Data
Berikut adalah proporsi kelas awal pada data
title_train.
title_train$SentimentTitleLable %>%
table() %>%
prop.table()#> .
#> negative neutral positive
#> 0.4084926 0.2000670 0.3914404
Untuk mengetahui jumlah observasi awal kita dapat menggunakan fungsi
nrow().
nrow(title_train)#> [1] 44745
Fungsi yang digunakan untuk melakukan downsampling adalah
downSample dari library caret.
set.seed(121)
title_train <- downSample(x = title_train$Title,
y = title_train$SentimentTitleLable,
yname = 'SentimentTitleLable')
title_train$SentimentTitleLable %>%
table() %>%
prop.table()#> .
#> negative neutral positive
#> 0.3333333 0.3333333 0.3333333
Jika dilihat dari proporsi kelas setelah dilakukan downsampling sudah seimbang, tetapi hal tersebut akan berpengaruh pada jumlah data nya.
nrow(title_train)#> [1] 26856
Headline Data
Berikut adalah proporsi kelas awal pada data
headline_train.
headline_train$SentimentHeadlineLable %>%
table() %>%
prop.table()#> .
#> negative neutral positive
#> 0.57192982 0.03034976 0.39772042
Jumlah observasi awal dapat dilihat menggunakan fungsi
nrow().
nrow(headline_train)#> [1] 44745
Kita akan menggunakan fungsi downSample() kembali untuk
melakukan downsampling pada data headline_train.
set.seed(121)
headline_train <- downSample(x = headline_train$Headline,
y = headline_train$SentimentHeadlineLable,
yname = 'SentimentHeadlineLable')
headline_train$SentimentHeadlineLable %>%
table() %>%
prop.table()#> .
#> negative neutral positive
#> 0.3333333 0.3333333 0.3333333
Berikut adalah jumlah observasi setelah dilakukan downsampling :
nrow(headline_train)#> [1] 4074
Text to Corpus
Corpus adalah kumpulan dari dokumen. Pada kasus ini, satu dokumen
ekuivalen dengan satu observasi Title/Headline. Di dalam satu
Title/Headline bisa terdapat satu atau lebih kalimat. Salah satu library
yang bisa kita gunakan untuk text mining adalah tm.
Pengubahan dari vector text menjadi corpus bisa dilakukan menggunakan
fungsi VCorpus().
title_train_corpus <- VCorpus(VectorSource(title_train$x))
headline_train_corpus <- VCorpus(VectorSource(headline_train$x))Document Term Matrix
Kita perlu melakukan transformasi data text menjadi Document-Term
Matrix (DTM) melalu proses tokenization. Tokenization adalah proses
memecah satu kalimat menjadi beberapa term (bisa berupa 1 kata, pasangan
kata, dll). Dalam DTM, 1 kata akan menjadi 1 prediktor dengan nilai
berupa frekuensi kemunculan kata tersebut dalam sebuah dokumen. Untuk
melakukan transformasi tersebut kita dapat menggunakan fungsi
DocumentTermMatrix() dari library tm.
title_train_dtm <- DocumentTermMatrix(title_train_corpus)
headline_train_dtm <- DocumentTermMatrix(headline_train_corpus)Selanjutnya kita akan melakukan filter kata yang setidaknya muncul 10 kali pada Document-Term Matrix untuk memperingkas waktu komputasi.
freq_title <- findFreqTerms(title_train_dtm, 10)
freq_headline <- findFreqTerms(headline_train_dtm, 10)
length(freq_title)#> [1] 2810
length(freq_headline)#> [1] 1259
title_train_dtm <- title_train_dtm[, freq_title]
headline_train_dtm <- headline_train_dtm[, freq_headline]Bernoulli Converter
Pada matrix title_train_dtm dan
headline_train_dtm masih berupa frekuensi. Untuk
perhitungan peluang, frekuensi akan diubah menjadi hanya kondisi muncul
(1) atau tidak (0). Salah satu caranya dengan menggunakan bernoulli
converter.
bernoulli_conv <- function(x){
x <- factor(
ifelse(x > 0, 1, 0), levels = c(0,1), labels = c("Absent", "Present")
)
return(x)}
# convert the document-term matrix
title_train_x <- apply(title_train_dtm, 2, bernoulli_conv)
headline_train_x <- apply(headline_train_dtm, 2, bernoulli_conv)
# create the target variable
title_train_label <- title_train$SentimentTitleLable
headline_train_label <- headline_train$SentimentHeadlineLable A work by Muhammad Yusuf Ibrahim
myusufibrahim@outlook.com