R ile Metin Madenciliği | Bölüm 6/6

Bölüm 5/6’da düzenli yapıda olmayan metin verilerini, çeşitli araçlarla nasıl düzenli hale getirebileceğimizi öğrendik. Bu bölümde bahsi geçen dönüştürme araçlarının konu modellemesi üzerinde metin analizine katkısı anlatılacaktır.

6. Bölüm – Konu Modellemesi – Topic Modelling

Metin madenciliğinde , döküman topluluklarını yani blog gönderileri veya haber makaleleri gibi metinleri anlayabilmek için doğal gruplara ayırmamız gerekir. Konu modellemesi, sayısal verileri kümelemeye benzer bir şekilde metin içerisinde aradığımız şeylerden emin olmadığımız durumlarda bile doğal metin gruplarını bulmaya çalışır.

Latent Dirichlet Allocation (LDA), konu modellemesi için popüler bir yöntemdir. Her belge konuların bir karışımıdır ve her konu ise kelimelerin karışımı olarak ele alınır. Bu da belgelerin doğal dilin tipik kullanımını yansıtarak, ayrık gruplara ayrılması yerine içerik bakımından birbiri ile örtüşmesini sağlar.

Yukarıdaki şema konu modellemeyi de içeren bir metin analizinin bir akış şemasıdır. topicmodels paketi ile elimizdeki Document-Term Matrix (Döküman-Terim Matrisi) ’i girdi olarak alır ve tidytext ile işlenebilecek bir model oluşturur. Böylelikle dplyr ve ggplot2 kütüphaneleri ile manipülasyon ve görselleştirme işlemleri yapılır.

Şemada gördüğümüz gibi şuana kadar öğrendiğimiz tüm araçlar ile konu modellemesi için tidy text – düzenli metin ilkelerini kullanabiliriz. Bu bölümde topicmodels paketi ile LDA nesnelerini nasıl işleyeceğimizi öğreneceğiz. Ayrıca kitaplardan bölümler ile kümeleme işlemleri yapıp, metinler içerisindeki farklılığı anlayıp anlamadığımızı göreceğiz.

6.1. Latent Dirichlet Allocation

Latent Dirichlet Allocation, konu modellemesi için en yaygın algoritmalardan biridir. İşin matematiğine girmeden, konu modellemesinin iki ilke tarafından ilerlediğini anlayabiliriz.

  • Her bir belge konuların bir karışımıdır. Her bir belge, çeşitli konulardan belirli oranlarda kelimeler içerir. Örneğin, elimizdeki metinin iki başlık altında modellendiğini düşünelim. “1. Belge” %90 A konusunu ve %10 B konusunu, “2. Belge” %30 A konusunu ve %70 B konusunu içersin.
  • Her bir belge konuların karışımı ise her bir konu da kelimelerin karışımıdır. Örneğin, Amerikan haberlerinin “siyaset” ve “eğlence” konuları ile iki konu modeli olduğunu düşünelim. Siyaset konusundaki en yaygın kelimeler “Başkan”, “Hükümet”, “Meclis” gibi kelimelerden oluşabilirken, eğlence konusundaki en yaygın kelimeler “filmler”, “aktör” ve “televizyon” kelimelerinden oluşabilir. Ayrıca bazı kelimeler de konular arasında paylaşılıyor olabilir. “bütçe” gibi bir kelime hem siyaset hem de eğlence konularında eşit olarak görülebilir.

LDA yukarıdaki iki maddeyi aynı anda tahmin etmek için yapılmış bir yöntemdir: Her bir konuyla ilişkili kelimelerin karışımını bulmak ve ayrıca her bir dökümanı tanımlayan konuların karışımını belirlemek temel amaçtır.

Associated Press veri seti bir Document-Term Matrix olarak topicmodels paketi içerisinde yer alır. Bu veri seti 1988’de yayınlanan bir Amerikan haber ajansından 2246 haber makalesinin bir derlemesidir.

library(topicmodels)

data("AssociatedPress")
AssociatedPress
## <<DocumentTermMatrix (documents: 2246, terms: 10473)>>
## Non-/sparse entries: 302031/23220327
## Sparsity           : 99%
## Maximal term length: 18
## Weighting          : term frequency (tf)

topicmodels paketi LDA() fonksiyonu ile LDA modeli oluşturmamızı sağlar. k = 2 argümanını kullanırsak iki konulu bir model oluşturmuş oluruz.

k artarsa modeldeki konu sayısı da artar.

LDA() fonksiyonu kelimelerin konularla nasıl ilişkilendirildiği ve konuların belgerle nasıl ilişkilendirildiği gibi modelin tüm ayrıntılarını içeren bir nesne verir.

# modelin çıktısını ön görebilmek için seed kullanma
ap_lda <- LDA(AssociatedPress, k = 2, control = list(seed = 1234))
ap_lda
## A LDA_VEM topic model with 2 topics.

Modelin oluşturulması kolay kısımdı. Analizin geri kalanı için tidytext paketi ile modelin incelenmesini ve yorumlanması gerekir.

6.1.1. Kelime-Konu Olasılıkları – Word-Topic Probabilities

broom paketinden tidy() fonksiyonunu anlatmıştık. tidy(), model nesnelerini düzenleme için kullanılır. tidytext paketi modelden konu başına kelime olasılıklarını incelemek için β’yı (“Beta”) kullanır.

library(tidytext)

ap_topics <- tidy(ap_lda, matrix = "beta")
ap_topics
## # A tibble: 20,946 x 3
##    topic term           beta
##    <int> <chr>         <dbl>
##  1     1 aaron      1.69e-12
##  2     2 aaron      3.90e- 5
##  3     1 abandon    2.65e- 5
##  4     2 abandon    3.99e- 5
##  5     1 abandoned  1.39e- 4
##  6     2 abandoned  5.88e- 5
##  7     1 abandoning 2.45e-33
##  8     2 abandoning 2.34e- 5
##  9     1 abbott     2.13e- 6
## 10     2 abbott     2.97e- 5
## # ... with 20,936 more rows

Yukarıdaki işlevin modeli satır başına bir konu ve bir terim olarak dönüştürdüğüne dikkat edelim. Her bir kombinasyon için model, kelimelerin bir konuya ait olma olasılıklarını hesaplar.

Örneğin, “aaron” kelimesinin 1. ve 2. konuya ait olma olasılıklarına yani beta’ya bakalım.

ap_topics[1:2,]
## # A tibble: 2 x 3
##   topic term      beta
##   <int> <chr>    <dbl>
## 1     1 aaron 1.69e-12
## 2     2 aaron 3.90e- 5

top_n() ile her konu içerisindeki en yaygın 10 terimi bulmak için dplyr kütüphanesini kullanabiliriz. Sonrasında ggplot2 kütüphanesi ile bunu görselleştirelim. Aşağıda her bir konu içindeki en yaygın terimleri göreceksiniz.

library(ggplot2)
library(dplyr)

ap_top_terms <- ap_topics %>%
  group_by(topic) %>%
  top_n(10, beta) %>%
  ungroup() %>%
  arrange(topic, -beta)

ap_top_terms %>%
  mutate(term = reorder(term, beta)) %>%
  ggplot(aes(term, beta, fill = factor(topic))) +
  geom_col(show.legend = FALSE) +
  facet_wrap(~ topic, scales = "free") +
  coord_flip() 

Yukarıdaki görselleştirme ile makalelerden çıkarılan iki konuyu anlamamızı sağlar. 1. konudaki kelimelerden bazıları, “percent”, “million”, “billion” ve “company” kelimeleri iş veya finansal haberler olabilir, 2. konudaki kelimelerden bazıları ise, “president”, “goverment” ve “soviet” kelimeleri de siyasi haberler olabilir. Yani bu kelimelerden yola çıkarak 1. konu iş veya finansal haberler, 2. konu ise siyasi haberler olabilir.

Ayrıca iki konuda da aynı kelimelerin ortaya çıkması konu modellemesinin, kümelemeye göre daha avantajlı olduğunu gösterir.

Alternatif olarak, konu 1 ve konu 2 arasındaki β’nın büyük bir fark olduğunu düşünelim. β1β1 ve β2β2 ’lerin 2 tabanında logaritmik oranlarını almak işe yarar bir yöntemtir. Çünkü logaritmik oranlar aradaki farkı simetrik bir hale getirir. Konulardaki yaygın kelimeleri bulmak için de betaların 1/1000’den büyük olmasını isteriz. logaritmik oran pozitif ve negatif değerler alır. B1B1B2B2’den büyük ise logaritmik oran negatif bir değer olur. Eğer B2B2B1B1’den büyük olursa logaritmik oran pozitif bir değer olur.

library(tidyr)

beta_spread <- ap_topics %>%
  mutate(topic = paste("topic", topic)) %>%
  spread(topic, beta) %>%
  filter(topic1 > .001 | topic2 > .001) %>%
  mutate(log_ratio = log2(topic2 / topic1))

beta_spread
## # A tibble: 198 x 4
##    term              topic1      topic2 log_ratio
##    <chr>              <dbl>       <dbl>     <dbl>
##  1 administration 0.000431  0.00138         1.68 
##  2 ago            0.00107   0.000842       -0.339
##  3 agreement      0.000671  0.00104         0.630
##  4 aid            0.0000476 0.00105         4.46 
##  5 air            0.00214   0.000297       -2.85 
##  6 american       0.00203   0.00168        -0.270
##  7 analysts       0.00109   0.000000578   -10.9  
##  8 area           0.00137   0.000231       -2.57 
##  9 army           0.000262  0.00105         2.00 
## 10 asked          0.000189  0.00156         3.05 
## # ... with 188 more rows

İki konu arasındaki büyük farka sahip olan kelimelerin görselleştirmesini yapalım. Konu 1 ve Konu 2 arasındaki beta farkının büyük olduğu kelimeler,

ggplot(
  rbind(
    beta_spread %>% select(term, log_ratio) %>% top_n(10),
    beta_spread %>% select(term, log_ratio) %>% top_n(-10)),
  aes(
    reorder(term, log_ratio),log_ratio)
  )+
  geom_col()+
  coord_flip()+
  labs(x = "term",
       y = "Log2 ratio of beta in topic 2 / topic 1")
## Selecting by log_ratio
## Selecting by log_ratio 

Konu 2’de yer alan kelimelerin “democratic” ve “republican” gibi siyasi partilerin yanı sıra “dukakis” ve “gorbachev” gibi politikacıların isimlerinin de geçtiğini görüyoruz. Konu 1’de ise “yen”, “dollar” gibi para birimlerinin yanı sıra “index”, “prices” gibi finansal kelimeleri de görüyoruz. Bu kelimeler iki konunun siyasi ve finansal haberler olduğunu doğrulamaya yeterli olur.

6.1.2. Döküman-Konu Olasılıkları – Document-Topic Probabilities

Her bir konuyu kelimelerin bir karışımı olarak tahmin etmenin yanında, LDA ayrıca her bir dökümanı konuların bir karışımı olarak modellemektedir.tidy() fonksiyonu içerisinde matrix argümanına “beta” yerine “gamma” yazarsak döküman-konu modelini ederiz.

ap_documents <- tidy(ap_lda, matrix = "gamma")
ap_documents
## # A tibble: 4,492 x 3
##    document topic    gamma
##       <int> <int>    <dbl>
##  1        1     1 0.248   
##  2        2     1 0.362   
##  3        3     1 0.527   
##  4        4     1 0.357   
##  5        5     1 0.181   
##  6        6     1 0.000588
##  7        7     1 0.773   
##  8        8     1 0.00445 
##  9        9     1 0.967   
## 10       10     1 0.147   
## # ... with 4,482 more rows

gamma değerlerinin her biri, mensubu olduğu konudan oluşturulan belgenin tahmin edilen bir oranını ifade eder. Örneğin, kurulan model, Belge 1’deki kelimelerin yalnızca %24.8’inin Konu 1’den oluşturulduğunu tahmin edebiliriz.

Bu dökümanların çoğu iki konunun karışımından elde edildi, ama Döküman 6’ya bakarsak Konu 1 için gamma değerinin sıfıra yakın olduğunu görebiliriz. Bunu da kontrol etmek için tidy() ile Document-Term Matrix – Döküman-Terim Matrisini ve bu dökümanda en sık kullanılan kelimelerin neler olduğuna bakalım.

tidy(AssociatedPress) %>%
  filter(document == 6) %>%
  arrange(desc(count))
## # A tibble: 287 x 3
##    document term           count
##       <int> <chr>          <dbl>
##  1        6 noriega           16
##  2        6 panama            12
##  3        6 jackson            6
##  4        6 powell             6
##  5        6 administration     5
##  6        6 economic           5
##  7        6 general            5
##  8        6 i                  5
##  9        6 panamanian         5
## 10        6 american           4
## # ... with 277 more rows

En yaygın kelimelere dayanarak, Amerikan hükümeti ile Panama diktatörü Manuel Noriega arasındaki ilişki hakkında bir makale olduğunu düşünebiliriz. Bu da algoritmanın doğru çalıştığını ve Döküman 6’nın Konu 2’ye (Siyasi haberler olarak) eğilimli olduğunu gösterir.

6.2. Örnek: Büyük Kütüphane Soygunu

İstatistiksel bir yöntemi incelememiz gerektiğinde, doğru cevabı bildiğimiz çok basit bir durum için bu yöntemi denememiz yararlı olacaktır.

Örneğin, metin madenciliği için dört ayrı konuyla ilgili bir dizi belge toplayalım. Daha sonra algoritmanın dört grubu da doğru şekilde ayırt edip edemeyeceğini görmek için konu modellemesini gerçekleştirebiliriz.

Elimizde dört adet kitap var ve bu dört kitabın bir vandal tarafından karıştırıldığını ve parçalara ayırıldığını düşünelim:

  • Charles Dickens – Great Expectations
  • HG Wells – The War of the Worlds
  • Jules Verne – Twenty Thousand Leagues Under the Sea
  • Jane Austen – Pride and Prejudice

Bu vandal, kitapları bireysel bölümlere ayırdı ve büyük bir yığın halinde bıraktı. Bu dağınık bölümleri orijinal kitaplarına nasıl geri yükleyebiliriz? Bireysel bölümlerin etiketlenmemiş olduğundan zor bir sorun ile karşı karşıyayız. Kelimeleri hangi gruplara ayıracağımızı bilmiyoruz. Bu yüzden konu modellemesi ile bölümlerden her birinin kitaplardan birini temsil eden farklı konulara nasıl ayrıldığını keşfedeceğiz.

Bu dört kitabı gutenberg paketi ile elde edebiliriz.

titles <- c("Twenty Thousand Leagues under the Sea", "The War of the Worlds",
            "Pride and Prejudice", "Great Expectations")
library(gutenbergr)

books <- gutenberg_works(title %in% titles) %>%
  gutenberg_download(meta_fields = "title")

Ön işlem olarak, bunları bölümlere ayıralım, daha sonra tidytext paketinden unnest_tokens() ile kelimelere parçalayalım. Daha sonra da duraklama kelimelerini (stop words) kaldırmamız gerekir.

Biz böyle bir adla ayrı bir “belgenin”, her biri her bölüm tedavi ediyoruz Great Expectations_1 veya Pride and Prejudice_11. (Diğer uygulamalarda, her belge bir gazete makalesi veya bir blog yazısı olabilir).

Her bir bölümü bir belge olarak ayırabilmemiz için her birini isimlendirmemiz gerekir, Great Expectations_1, Pride and Prejudice_11 gibi.

library(stringr)

# Dökümanları ayırma işlemi, her biri bir bölümü temsil edecek
by_chapter <- books %>%
  group_by(title) %>%
  mutate(chapter = cumsum(str_detect(text, regex("^chapter ", ignore_case = TRUE)))) %>%
  ungroup() %>%
  filter(chapter > 0) %>%
  unite(document, title, chapter)

# kelimelere parçalama
by_chapter_word <- by_chapter %>%
  unnest_tokens(word, text)

# belge-terim frekansı bulma
word_counts <- by_chapter_word %>%
  anti_join(stop_words) %>%
  count(document, word, sort = TRUE) %>%
  ungroup()
## Joining, by = "word"
word_counts
## # A tibble: 104,722 x 3
##    document                 word        n
##    <chr>                    <chr>   <int>
##  1 Great Expectations_57    joe        88
##  2 Great Expectations_7     joe        70
##  3 Great Expectations_17    biddy      63
##  4 Great Expectations_27    joe        58
##  5 Great Expectations_38    estella    58
##  6 Great Expectations_2     joe        56
##  7 Great Expectations_23    pocket     53
##  8 Great Expectations_15    joe        50
##  9 Great Expectations_18    joe        50
## 10 The War of the Worlds_16 brother    50
## # ... with 104,712 more rows

6.2.1. Kitapların Bölümlerinde LDA

Şu anda veri setimiz düzenli veri formatında, ancak topicmodels paketi ile Document-Term Matrix yani Döküman-Terim Matrisine dönüştürmemiz gerekiyor. Bunu da cast_dtm() fonksiyonu ile yapalım.

chapters_dtm <- word_counts %>% 
  cast_dtm(document, word, n)
## Warning: Trying to compute distinct() for variables not found in the data:
## - `row_col`, `column_col`
## This is an error, but only a warning is raised for compatibility reasons.
## The operation will return the input unchanged.
chapters_dtm
## <<DocumentTermMatrix (documents: 193, terms: 18215)>>
## Non-/sparse entries: 104722/3410773
## Sparsity           : 97%
## Maximal term length: 19
## Weighting          : term frequency (tf)

Şimdi LDA() fonksyionu ile konu modellememizi dört olarak ayarlabiliriz. Çünkü elimizde dört adet kitap var ve dört adet konu aradığımızı biliyoruz. Başka problemler için k değerinin ayarlanması gerekebilir.

chapters_lda <- LDA(chapters_dtm, k = 4, control = list(seed = 1234))
chapters_lda
## A LDA_VEM topic model with 4 topics.

Associated Press verilerinde yaptığımız gibi, her bir konu başına düşen kelime olasılıklarını inceleyebiliriz.

chapter_topics <- tidy(chapters_lda, matrix = "beta")
chapter_topics
## # A tibble: 72,860 x 3
##    topic term        beta
##    <int> <chr>      <dbl>
##  1     1 joe     1.44e-17
##  2     2 joe     5.96e-61
##  3     3 joe     9.88e-25
##  4     4 joe     1.45e- 2
##  5     1 biddy   5.14e-28
##  6     2 biddy   5.02e-73
##  7     3 biddy   4.31e-48
##  8     4 biddy   4.78e- 3
##  9     1 estella 2.43e- 6
## 10     2 estella 4.32e-68
## # ... with 72,850 more rows

Yukarıdaki işlevin modeli satır başına bir konu ve bir terim olarak dönüştürdüğüne dikkat edelim. Her bir kombinasyon için model, kelimelerin bir konuya ait olma olasılıklarını hesaplar. Örneğin, “joe” kelimesinin, Konu 1, Konu 2 ve Konu 3 içerisinde olma olasılığı neredeyse sıfırdır, ancak Konu 4’te “joe” kelimesi konunun %1.45’ini oluşturur.

Her bir konudaki en iyi 5 terimi bulmak için dplyr kütüphanesinden top_n() fonksiyonunu kullanabiliriz .

top_terms <- chapter_topics %>%
  group_by(topic) %>%
  top_n(5, beta) %>%
  ungroup() %>%
  arrange(topic, -beta)

top_terms
## # A tibble: 20 x 3
##    topic term         beta
##    <int> <chr>       <dbl>
##  1     1 elizabeth 0.0141 
##  2     1 darcy     0.00881
##  3     1 miss      0.00871
##  4     1 bennet    0.00694
##  5     1 jane      0.00649
##  6     2 captain   0.0155 
##  7     2 nautilus  0.0131 
##  8     2 sea       0.00884
##  9     2 nemo      0.00871
## 10     2 ned       0.00803
## 11     3 people    0.00679
## 12     3 martians  0.00646
## 13     3 time      0.00534
## 14     3 black     0.00528
## 15     3 night     0.00449
## 16     4 joe       0.0145 
## 17     4 time      0.00685
## 18     4 pip       0.00683
## 19     4 looked    0.00637
## 20     4 miss      0.00623

Yukarıdaki çıktı ggplot2 görselleştirilmesi ile daha anlamlı hale gelecektir. Her bir konu için en yaygın olan kelimeleri görelim.

library(ggplot2)

top_terms %>%
  mutate(term = reorder(term, beta)) %>%
  ggplot(aes(term, beta, fill = factor(topic))) +
  geom_col(show.legend = FALSE) +
  facet_wrap(~ topic, scales = "free") +
  coord_flip()

Konuların oldukça dört kitap ile ilişkili olduğunu görmekteyiz. “captain”, “nautilus”, “sea”, ve “nemo” kelimeleri “Twenty Thousand Leagues Under the Sea” kitabına, “jane”, “darcy”, ve “elizabeth” kelimeleri “Pride and Prejudice” kitabına aittir. “Great Expectations” kitabından “pip”, “joe” kelimelerini ve “The War of the Worlds” kitabından da “martians”, “black” ve “night” kelimelerini görmekteyiz.

Ayrıca LDA “bulanık kümeleme” yöntemi ile uyumlu olarak Konu 1 ve Konu 4’te “miss” kelimesinin geçtiğini, Konu 3 ve Konu 4’te de “time” kelimesinin geçtiğini görüyoruz. Birden çok konular arasında ortak kelimelerin de olduğunu görüyoruz.

6.2.2 Döküman Başına Sınıflandırma – Per-Document Classification

Bu analizdeki her belge tek bir bölümü temsil ediyordu. Bundan kaynaklı her bir belge ile hangi konuların ilişkilendirilebileceğini anlamamız gerebilir. Bölümleri doğru kitaplarda bir araya getirme şansımız var mıdır ? Bunu her bir belge için konu olasılıklarına yani γ gamma’ya bakarak bulabiliriz.

chapters_gamma <- tidy(chapters_lda, matrix = "gamma")
chapters_gamma
## # A tibble: 772 x 3
##    document                 topic     gamma
##    <chr>                    <int>     <dbl>
##  1 Great Expectations_57        1 0.0000134
##  2 Great Expectations_7         1 0.0000146
##  3 Great Expectations_17        1 0.0000210
##  4 Great Expectations_27        1 0.0000190
##  5 Great Expectations_38        1 0.355    
##  6 Great Expectations_2         1 0.0000171
##  7 Great Expectations_23        1 0.547    
##  8 Great Expectations_15        1 0.0124   
##  9 Great Expectations_18        1 0.0000126
## 10 The War of the Worlds_16     1 0.0000107
## # ... with 762 more rows

Elde ettiğimiz gamma değerleri belgelerin hangi konudan olabileceğinin olasılığıdır. Great_Expectations_5 belgesindeki her kelimenin Konu !’den yani Pride and Prejudice kitabından olma olasılığının yalnızca 0.00135 olduğunu tahmin etmektedir.

Şimdi konu olasılıklarına sahip olduğumuza göre unsupervised learning (denetimsiz öğrenme) ile elimizdeki dört kitabı ayırt etmede ne kadar başarılı olacağımızı görelim.

Öncelikle, belge ismini başlık (“title”) ve bölüm (“chapter”) olmak üzere yeniden ayırdık ve ardından her bir belge başına konu olasılıklarını görselleştirebileceğiz.

chapters_gamma <- chapters_gamma %>%
  separate(document, c("title", "chapter"), sep = "_", convert = TRUE)

chapters_gamma
## # A tibble: 772 x 4
##    title                 chapter topic     gamma
##    <chr>                   <int> <int>     <dbl>
##  1 Great Expectations         57     1 0.0000134
##  2 Great Expectations          7     1 0.0000146
##  3 Great Expectations         17     1 0.0000210
##  4 Great Expectations         27     1 0.0000190
##  5 Great Expectations         38     1 0.355    
##  6 Great Expectations          2     1 0.0000171
##  7 Great Expectations         23     1 0.547    
##  8 Great Expectations         15     1 0.0124   
##  9 Great Expectations         18     1 0.0000126
## 10 The War of the Worlds      16     1 0.0000107
## # ... with 762 more rows

Kitaplardaki her bir bölüm için gamma olasılıkları,

chapters_gamma %>%
  mutate(title = reorder(title, gamma * topic)) %>%
  ggplot(aes(factor(topic), gamma)) +
  geom_boxplot() +
  facet_wrap(~ title)

Neredeyse kitapladaki tüm bölümler benzersiz te bir konu ile tanımlandı. Bunlar “Pride and Prejudice”, “War of the Worlds” ve “Twenty Thousand Leagues Under the Sea” kitaplarıdır.

Great Expectations (Konu 4) kitabından bazı bölümler diğer konularla bir şekilde ilişkiliydi.Bir bölümle en çok ilişkilendirilen konunun başka bir kitaba ait olduğu durumlar var mı?

İlk olarak, her bir bölümü top_n() fonksiyonunu kullanarak en çok ilişkili olan konular ile etkili bir biçimde sınıflandırabiliriz.

chapter_classifications <- chapters_gamma %>%
  group_by(title, chapter) %>%
  top_n(1, gamma) %>%
  ungroup()

chapter_classifications
## # A tibble: 193 x 4
##    title               chapter topic gamma
##    <chr>                 <int> <int> <dbl>
##  1 Great Expectations       23     1 0.547
##  2 Pride and Prejudice      43     1 1.000
##  3 Pride and Prejudice      18     1 1.000
##  4 Pride and Prejudice      45     1 1.000
##  5 Pride and Prejudice      16     1 1.000
##  6 Pride and Prejudice      29     1 1.000
##  7 Pride and Prejudice      10     1 1.000
##  8 Pride and Prejudice       8     1 1.000
##  9 Pride and Prejudice      56     1 1.000
## 10 Pride and Prejudice      47     1 1.000
## # ... with 183 more rows

Daha sonra her bir kitap için bölümler arasındaki en yaygın konuları karşılaştırabiliriz ve en fazla yanlış tanımlanmş olanları görebiliz. Bunu da “consensus” ile bakabiliriz.

book_topics <- chapter_classifications %>%
  count(title, topic) %>%
  group_by(title) %>%
  top_n(1, n) %>%
  ungroup() %>%
  transmute(consensus = title, topic)

chapter_classifications %>%
  inner_join(book_topics, by = "topic") %>%
  filter(title != consensus)
## # A tibble: 2 x 5
##   title              chapter topic gamma consensus            
##   <chr>                <int> <int> <dbl> <chr>                
## 1 Great Expectations      23     1 0.547 Pride and Prejudice  
## 2 Great Expectations      54     3 0.481 The War of the Worlds

LDA’a göre “Pride and Prejudice” Konu 1 ve “The War of the Worlds” Konu 3 olarak tanımladığı gibi “Great Expectations” kitabında ise sadece iki bölümün yanlış sınıflandırıldığı görüyoruz. Denetimsiz öğrenmede kümeleme yöntemi için bu sonuç kötü değildir.

6.2.3. Kelime Atamaları: augment

LDA algoritmasının bir adımı da her bir belgedeki kelimeleri bir konuya atamaktır. Belgedeki daha fazla kelimeler bu konuya atanır. Genellikle gamma ağırlığı fazla olan document-topic classification yani döküman-konu sınıflandırmasına geçecektir.

Orijinal belge-kelime çiftlerini bilmek ve her bir belgedeki kelimelerin hangi konuya atandığını bulmak isteyebiliriz. Broom paketindeki augment() fonksiyonu düzenli model çıktısını almak için bir yolu sağlar. tidy() fonksyionu modelin istatistiksel bileşenlerini alırken, augment() fonksiyonu ise orjinal verilerin her bir gözlemine bilgi eklemek için bir model kullanır.

assignments <- augment(chapters_lda, data = chapters_dtm)
assignments
## # A tibble: 104,722 x 4
##    document              term  count .topic
##    <chr>                 <chr> <dbl>  <dbl>
##  1 Great Expectations_57 joe      88      4
##  2 Great Expectations_7  joe      70      4
##  3 Great Expectations_17 joe       5      4
##  4 Great Expectations_27 joe      58      4
##  5 Great Expectations_2  joe      56      4
##  6 Great Expectations_23 joe       1      4
##  7 Great Expectations_15 joe      50      4
##  8 Great Expectations_18 joe      50      4
##  9 Great Expectations_9  joe      44      4
## 10 Great Expectations_13 joe      40      4
## # ... with 104,712 more rows

Yukarıdaki kod, Kitap-Terim frekanslarının (book-term counts) düzeni bir veri setini verir. Ancak veri setine fazladan bir sütun ekler, bu sütun topic. topic değikeni ile her bir terim belgelerin içine atanmıştır. (Mevcut değişkenlerin üzerine yazılmasındansa augment() fonksiyonu ek değişken oluşturur). Hangi kelimelerin yanlış sınıflandırıldığını bulmak için assignments tablosunu uygun kitap başlıklarıyla birleştirebiliriz .

assignments <- assignments %>%
  separate(document, c("title", "chapter"), sep = "_", convert = TRUE) %>%
  inner_join(book_topics, by = c(".topic" = "topic"))

assignments
## # A tibble: 104,722 x 6
##    title              chapter term  count .topic consensus         
##    <chr>                <int> <chr> <dbl>  <dbl> <chr>             
##  1 Great Expectations      57 joe      88      4 Great Expectations
##  2 Great Expectations       7 joe      70      4 Great Expectations
##  3 Great Expectations      17 joe       5      4 Great Expectations
##  4 Great Expectations      27 joe      58      4 Great Expectations
##  5 Great Expectations       2 joe      56      4 Great Expectations
##  6 Great Expectations      23 joe       1      4 Great Expectations
##  7 Great Expectations      15 joe      50      4 Great Expectations
##  8 Great Expectations      18 joe      50      4 Great Expectations
##  9 Great Expectations       9 joe      44      4 Great Expectations
## 10 Great Expectations      13 joe      40      4 Great Expectations
## # ... with 104,712 more rows

Gerçek kitabın (title) ve ona atanan kitabın (consensus) bu birleşimi daha fazla keşif yapmak için yararlıdır. Örnek olarak bir kitaptaki kelimelerin diğer kitaplara ne kadar sıklıkla atanmış olabileceğini gösteren bir “confusion matrix” yani karışıklık matrisini görselleştirebiliriz. Burada dplyr ve ggplot2 küüphanelerini etkin bir biçimde kullanalım.

Aşağıdaki görselleştirme Confusion Matrix ile LDA’nın her bir kitaptaki kelimelerin atandığı kitapları görebiliriz. Her bir satır yani y-ekseni kelimelerin geldikleri kitapları ve her bir sütun yani x-ekseni de kelimelerin atandıkları kitapları gösterir.

assignments %>%
  count(title, consensus, wt = count) %>%
  group_by(title) %>%
  mutate(percent = n / sum(n)) %>%
  ggplot(aes(consensus, title, fill = percent)) +
  geom_tile() +
  scale_fill_gradient2(high = "red", label = percent_format()) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 90, hjust = 1),
        panel.grid = element_blank()) +
  labs(x = "Book words were assigned to",
       y = "Book words came from",
       fill = "% of assignments") 

 

“Pride and Prejudice”, “Twenty Thousand Leagues Under the Sea” ve “The War of the Worlds” kitaplarındaki kelimeler hemen hemen doğru bir şekilde atanmış olmasına rağmen, “Great Expectations” kitabındaki kelimelerin çok fazla sayıda yanlış atanmış olduğunu görüyoruz. Bunun da nedeni yukarıda da görmüştük, iki bölüm yanlış sınıflandırılmıştı.

Peki en çok rastlanan yanlış kelimeler nelerdi?

wrong_words <- assignments %>%
  filter(title != consensus)

wrong_words
## # A tibble: 4,617 x 6
##    title                chapter term    count .topic consensus            
##    <chr>                  <int> <chr>   <dbl>  <dbl> <chr>                
##  1 Great Expectations        38 brother     2      1 Pride and Prejudice  
##  2 Great Expectations        22 brother     4      1 Pride and Prejudice  
##  3 Great Expectations        23 miss        2      1 Pride and Prejudice  
##  4 Great Expectations        22 miss       23      1 Pride and Prejudice  
##  5 Twenty Thousand Lea…       8 miss        1      1 Pride and Prejudice  
##  6 Great Expectations        31 miss        1      1 Pride and Prejudice  
##  7 Great Expectations         5 sergea…    37      1 Pride and Prejudice  
##  8 Great Expectations        46 captain     1      2 Twenty Thousand Leag…
##  9 Great Expectations        32 captain     1      2 Twenty Thousand Leag…
## 10 The War of the Worl…      17 captain     5      2 Twenty Thousand Leag…
## # ... with 4,607 more rows
wrong_words %>%
  count(title, consensus, term, wt = count) %>%
  ungroup() %>%
  arrange(desc(n))
## # A tibble: 3,551 x 4
##    title              consensus             term         n
##    <chr>              <chr>                 <chr>    <dbl>
##  1 Great Expectations Pride and Prejudice   love        44
##  2 Great Expectations Pride and Prejudice   sergeant    37
##  3 Great Expectations Pride and Prejudice   lady        32
##  4 Great Expectations Pride and Prejudice   miss        26
##  5 Great Expectations The War of the Worlds boat        25
##  6 Great Expectations The War of the Worlds tide        20
##  7 Great Expectations The War of the Worlds water       20
##  8 Great Expectations Pride and Prejudice   father      19
##  9 Great Expectations Pride and Prejudice   baby        18
## 10 Great Expectations Pride and Prejudice   flopson     18
## # ... with 3,541 more rows

“Great Expectations” kiabındaki bazı kelimelerin sıklıkla “Pride and Prejudice” veya “The War of the Worlds” kitabına atandığını görebiliriz. “love” ve “lady” gibi kelimeler “Pride and Prejudice” kitabında daha yaygın olduğu için atanmıştır.

Öte yandan yanlış bir şekilde sınıflandırılmış kelimeler de olabilir. Örneğin, “flopson” kelimesi “Pride and Prejudice” kümesine atanmış olmasına rağmen “Great Expectations” kitabında yer aldığını teyit edebiliriz.

word_counts %>%
  filter(word == "flopson")
## # A tibble: 3 x 3
##   document              word        n
##   <chr>                 <chr>   <int>
## 1 Great Expectations_22 flopson    10
## 2 Great Expectations_23 flopson     7
## 3 Great Expectations_33 flopson     1

6.3. Özet

Bu bölümde, bir dizi belgeyi karakterize eden kelime kümelerini bulmak için konu modellemesi – topic modelling konusunu anlattık. tidy() eylemi ile dplyr ve ggplot2 kütüphanelerini kullanarak modelleri nasıl keşfedeceğimizi ve anlayacağımızı öğrendik. Model keşfi için LDA düzenli veri formatı yaklaşımının avantajlarından biridir. Farklı çıktı biçimlerinin zorlukları düzenleme fonksionları ile giderilir ve bir takım araçları kullanarak model sonuçlarını keşfedebiliriz. Özellikle konu modellemesinin, kitapların her bir bölümünü diğer kitaplardan ayırabildiğini ve modelin yanlış bir şekilde atadığı kelimeleri ve bölümleri tespit ettiği başarılı bir yöntem olduğunu görüyoruz.

Mutlu Son

Çok uzun bir yazı ile R’da metin madenciliği uygulamalarının nasıl yapıldığını öğrenmiş olduk. Ayrıca, tidytext kütüphanesinin diğer kütüphaneler ile birlikte kullanımının işlevselliğini gördük.

Veri Bilimi maceramızda yeni bir şeyler öğrendiğimize göre, mutlu bir şekilde metinleri analiz etmeye başlayabilirsiniz.

Yazar Hakkında
Toplam 18 yazı
Ekrem Bayar
Ekrem Bayar
Yorumlar (Yorum yapılmamış)

Bir cevap yazın

E-posta hesabınız yayımlanmayacak.

×

Bir Şeyler Ara