R ve Gephi ile Twitter Dinamiklerini Anlamak: Metin Analizi ve Merkezilik
Yayınlanan: 2022-07-22Bu makale, sosyal ağ analizi serimizin ilk bölümünde sunulan analizi genişletiyor ve derinleştiriyor. İlk makalede oluşturulan aynı Twitter veri kümesini ve etkileşim ağını kullanıyoruz. Ancak bu seferki fikir, ana aktörleri daha iyi anlamak, tartışma konularını belirlemek ve bu konuların nasıl yayıldığını anlamaktır.
Sosyal Ağ Merkeziliği
Hedeflerimize ulaşmak için önce merkezilik kavramını tanıtmamız gerekiyor. Ağ biliminde, merkezilik, ağ üzerinde güçlü bir etkisi olan düğümleri ifade eder. Etki belirsiz bir kavramdır; birçok şekilde anlaşılabilir. Birçok kenarı olan bir düğüm, daha az ama daha fazla “önemli” kenara sahip bir düğümden daha mı etkili? Bir sosyal ağda önemli bir avantajı ne oluşturur?
Bu belirsizlikleri gidermek için ağ bilimciler birçok merkezilik ölçütü geliştirdiler. Burada, yaygın olarak kullanılan dört önlemi tartışıyoruz, ancak daha birçoğu mevcut.
Derece
En yaygın ve sezgisel ölçü, derece merkeziliğidir. Derece merkeziliğinin arkasındaki fikir basittir: Etkiyi düğümün derecesine göre ölçün. Grafik yönlendirilirse varyantları olabilir; bu durumda, dereceyi ve dereceyi ölçebilirsiniz; birincisi merkez puanı, ikincisi ise otorite puanı olarak bilinir.
Bu dizinin ilk bölümünde, yönlendirilmemiş yaklaşımı kullandık. Bu sefer derece yaklaşımına odaklanıyoruz. Bu, başkaları tarafından retweetlenen kullanıcıları yalnızca sık retweetleyen kullanıcılardan daha fazla vurgulayarak daha doğru bir analiz yapılmasına olanak tanır.
özvektör
Özvektör ölçüsü, derece merkeziliği üzerine kuruludur. Etkili düğümler belirli bir düğüme ne kadar çok işaret ederse, puanı o kadar yüksek olur. Satırların ve sütunların düğümleri temsil ettiği bir bitişiklik matrisi ile başlıyoruz ve belirli bir satır ve sütunun karşılık gelen düğümlerinin bağlı olup olmadığını belirtmek için 1 veya 0 kullanıyoruz. Ana hesaplama, matrisin özvektörlerini tahmin eder. Asıl özvektör, istediğimiz merkezilik ölçülerini içerecektir, burada i konumu, i düğümünün merkezilik puanını tutacaktır.
Sayfa Sıralaması
PageRank, Google'ın merkezindeki özvektör ölçüsünün varyasyonudur. Google'ın kullandığı kesin yöntem bilinmiyor, ancak genel fikir, her düğümün 1 puanla başlaması ve ardından puanını her bir kenarına eşit parçalara dağıtmasıdır. Örneğin, bir düğümün kendisinden uzanan üç kenarı varsa, puanının üçte birini her kenardan “gönderir”. Aynı zamanda düğüm, ona işaret eden kenarlar tarafından daha önemli hale getirilir. Bu, N bilinmeyenli çözülebilir bir N denklem sistemi ile sonuçlanır.
arasındalık
Dördüncü ölçü, aradalık , çok farklı bir yaklaşım kullanır. Burada, bir düğümün diğer düğümler arasındaki birçok kısa yola dahil olması durumunda etkili olduğu söylenir. Yani, “farklı dünyaları” birbirine bağlayan diğer birçok düğümle iletişim kurmaktan sorumludur.
Örneğin, sosyal ağ analizinde, bu tür düğümler, başkalarının yeni iş bulmasına veya yeni bağlantılar kurmasına yardımcı olan insan türleri olarak anlaşılabilir - bunlar daha önce bilinmeyen sosyal çevrelere açılan kapılardır.
Hangisini Kullanmalıyım?
Uygun merkezilik ölçüsü, analizinizin amacına bağlıdır. Hangi kullanıcıların nicelik açısından başkaları tarafından sıklıkla seçildiğini bilmek ister misiniz? Derece merkeziliği muhtemelen en iyi seçeneğiniz olacaktır. Yoksa kaliteyi dikkate alan bir merkezilik ölçüsü mü tercih edersiniz? Bu durumda özvektör veya PageRank daha iyi sonuçlar verecektir. Hangi kullanıcıların farklı topluluklar arasında en etkili şekilde köprü işlevi gördüğünü bilmek istiyorsanız, aradalık en iyi seçeneğinizdir.
Özvektör ve PageRank gibi birden fazla benzer ölçü kullanırken, hepsini tahmin edebilir ve eşdeğer sıralamalar verip vermediklerini görebilirsiniz. Değilse, farklılıklar analizinizi derinleştirebilir veya puanlarını birleştirerek yeni bir ölçü oluşturabilirsiniz.
Başka bir yaklaşım, ağınız üzerindeki düğümlerin gerçek etkisi hakkında size daha fazla bilgi veren önlemi tahmin etmek için temel bileşen analizini kullanır.
Uygulamalı Merkezilik Hesaplaması
Şimdi bu ölçüleri R ve RStudio kullanarak nasıl hesaplayabileceğimize bakalım. (Gephi ile de yapılabilir.)
Öncelikle, bu makale boyunca kullanacağımız tüm kütüphaneleri yüklememiz gerekiyor:
library("plyr") library(igraph) library(tidyverse) library(NLP) library("tm") library(RColorBrewer) library(wordcloud) library(topicmodels) library(SnowballC) library("textmineR")
Daha sonra, bu analiz için kullanışlı olmadıklarından, daha önce kullandığımız verilerden izole edilmiş düğümleri çıkaracağız. Ardından, merkezilik ölçülerini tahmin etmek için arasındalık, betweenness
, centr_eigen
ve degree
igraph
fonksiyonlarını page_rank
. Son olarak, hangi kullanıcıların en merkezi olduğunu görmek için puanları igraph
nesnesinde ve bir veri çerçevesinde saklayacağız.
load("art1_tweets.RData") Isolated = which(degree(net)==0) net_clean = delete.vertices(net, Isolated) cent<-data.frame(bet=betweenness(net_clean),eig=centr_eigen(net_clean)$vector,prank=(page_rank(net_clean)$vector),degr=degree(net_clean, mode="in")) cent <- cbind(account = rownames(cent), cent)
Artık her bir ölçüme göre en merkezi 10 kullanıcıyı kontrol edebiliriz:
Derece | |
özvektör | |
Sayfa Sıralaması | |
arasındalık | |
Sonuçlar:
Derece | özvektör | Sayfa Sıralaması | arasındalık | ||||
---|---|---|---|---|---|---|---|
ESPNFC | 5892 | PSG_inside | 1 | mundodabola | 0.037 | görüş alanı | 77704 |
Troll Futbol | 5755 | EkiplerMat19 | 0,51 | AleLiparoti | 0.026 | EdmundOris | 76425 |
PSG_inside | 5194 | eh01195991 | 0,4 | PSG_inside | 0.017 | ba*****lla | 63799 |
EkiplerMat19 | 4344 | Muhammed135680 | 0.37 | RoyNemer | 0.016 | FranciscoGaius | 63081 |
brfutbol | 4054 | ActuFoot_ | 0.34 | Troll Futbol | 0.013 | Yemihazan | 62534 |
PSG_espanol | 3616 | marttvall | 0.34 | ESPNFC | 0.01 | hashtag2weet | 61123 |
IbaiOut | 3258 | ESPNFC | 0,3 | PSG_espanol | 0.007 | Angela_FCB | 60991 |
ActuFoot_ | 3175 | brfutbol | 0.25 | Anında Ayak | 0.007 | Zyyon_ | 57269 |
Ayak Mizahı | 2976 | SaylorMoonOrdusu | 0.22 | IbaiOut | 0.006 | EkiplerMat19 | 53758 |
mundodabola | 2778 | JohnsvillPat | 0,2 | 2010Bay Çip | 0.006 | MdeenOlawale | 49572 |
İlk üç önlemin PSG_inside, ESPNFC, CrewsMat19 ve TrollFootball gibi bir dizi kullanıcıyı paylaştığını görebiliriz. Tartışma üzerinde güçlü bir etkiye sahip olduklarını varsayabiliriz. Arasındalık, merkeziliği ölçmek için farklı bir yaklaşıma sahiptir ve bu nedenle diğer tekniklerle çok fazla örtüşme göstermez.
Not: Bu yazıda bahsedilen Twitter hesapları tarafından ifade edilen görüşler, Toptal'ın veya yazarın görüşlerini yansıtmamaktadır.
Aşağıdaki resimlerde, orijinal renkli ağ grafiğimizi iki kullanıcı etiketi katmanıyla görebilirsiniz. İlkinde, düğümler PageRank puanlarıyla, ikincisinde ise aradalık puanlarıyla vurgulanır:
Gephi bu görüntüleri çoğaltmak için kullanılabilir. İstatistik panelindeki Ağ Çapı düğmesini kullanarak aradalık veya PageRank puanlarını tahmin edebilirsiniz. Ardından, bu serinin ilk bölümünde gösterildiği gibi öznitelikleri kullanarak düğüm adlarını gösterebilirsiniz.
Metin Analizi: R ve LDA
Kullanıcıların ne hakkında konuştuğunu belirlemek için sosyal ağ tartışmalarını da analiz edebiliriz. Buna yaklaşmanın birden fazla yolu var. Hangi sözcük kümesinin birlikte görünme eğiliminde olduğunu tahmin etmemize olanak tanıyan denetimsiz bir makine öğrenme tekniği olan Latent Dirichlet Allocation (LDA) aracılığıyla konu modellemesi yapacağız. Ardından, bu kelime grubu aracılığıyla tartışılan konuyu çıkarabiliriz.
İlk adım, metni sterilize etmektir. Bunu yapmak için aşağıdaki işlevi tanımlıyoruz:
# This function normalizes text by removing Twitter-related terms and noisy characters sanitize_text <- function(text) { # Convert to ASCII to remove accented characters: text <- iconv(text, to = "ASCII", sub = " ") # Move to lower case and delete RT word (this is added by Twitter) text <- gsub("rt", " ", tolower(text)) # Delete links and user names: text <- gsub("@\\w+", " ", gsub("http.+ |http.+$", " ", text)) # Delete tabs and punctuation: text <- gsub("[ |\t]{2,}", " ", gsub("[[:punct:]]", " ", text)) text <- gsub("amp", " ", text) # Remove HTML special character # Delete leading and lagging blanks: text <- gsub("^ ", "", gsub(" $", "", text)) text <- gsub(" +", " ", text) # Delete extra spaces return(text) }
Ayrıca, durma kelimelerini, yinelenenleri ve boş girişleri de kaldırmamız gerekiyor. Ardından, metnimizi LDA tarafından işlenecek bir belge terim matrisine dönüştürmemiz gerekiyor.
Bu veri setinde birçok dilde (İngilizce, İspanyolca, Fransızca vb.) konuşan kullanıcılarımız bulunmaktadır. LDA, tek bir dile odaklanırsak en iyi sonucu verir. Bunu, esas olarak İngilizce konuşan kullanıcıların hesaplarından oluşan bu serinin ilk bölümünde tespit edilen en büyük topluluğun kullanıcıları üzerinde uygulayacağız.
# Detect communities: my.com.fast <-cluster_louvain(as.undirected(simplify(net))) largestCommunities <- order(sizes(my.com.fast), decreasing=TRUE)[1:3] # Save the usernames of the biggest community: community1 <- names(which(membership(my.com.fast) == largestCommunities[1])) # Sanitize the text of the users of the biggest community: text <- unique(sanitize_text(tweets.df[which(tweets.df$screen_name %in% community1),]$text)) text = text[text!=''] # Delete empty entries stopwords_regex = paste(stopwords('es'), collapse = '\\b|\\b') stopwords_regex = paste0('\\b', stopwords_regex, '\\b') # Remove English stopwords: text = stringr::str_replace_all(text, stopwords_regex, '') # Create the document term matrix: dtm <- CreateDtm(text, doc_names = seq(1:length(text)), ngram_window = c(1, 2))
Konu Sayıları ve Tutarlılık Puanları
LDA'da tanımlamamız gereken ana hiperparametre, tahmin etmek istediğimiz konuların sayısıdır (k) . Ancak, bunu önceden nasıl bilebiliriz? Yaygın bir yaklaşım, LDA modellerini farklı k değerleri üzerinde eğitmek ve her birinin tutarlılığını ölçmektir. Bunu 3'ten 20'ye kadar olan k değerleri için yapacağız, çünkü bu aralığın dışındaki değerler kontrol etmeye değmez, benim deneyimime göre:
tf <- TermDocFreq(dtm = dtm) # Remove infrequent words: tf_trimmed = tf$term[ tf$term_freq > 1 & tf$doc_freq < nrow(dtm) / 2 ] # Create a folder to store trained models: model_dir <- paste0("models_", digest::digest(tf_trimmed, algo = "sha1")) if (!dir.exists(model_dir)) dir.create(model_dir) # Define a function to infer LDA topics: train_lda_model <- function(number_of_topics){ filename = file.path(model_dir, paste0(number_of_topics, "_topics.rda")) # Check if the model already exists: if (!file.exists(filename)) { # To get exactly the same output on each run, use a constant seed: set.seed(12345) lda_model = FitLdaModel(dtm = dtm, k = number_of_topics, iterations = 500) lda_model$k = number_of_topics lda_model$coherence = CalcProbCoherence(phi = lda_model$phi, dtm = dtm, M = 5) save(lda_model, file = filename) } else { load(filename) } lda_model } # The number of topics that we are going to infer in each LDA training run: topic_count = seq(3, 20, by = 1) # Train through the TmParallelApply function models = TmParallelApply(X = topic_count, FUN = train_lda_model, export = c("dtm", "model_dir"))
Ardından, her birinin tutarlılık değerini grafik haline getiriyoruz:
coherence_by_topics_quantity = data.frame( topic_number = sapply(models, function(model_instance) nrow(model_instance$phi)), score_coherence = sapply(models, function(model_instance) mean(model_instance$coherence)), stringsAsFactors = FALSE) ggplot(coherence_by_topics_quantity, aes(x = topic_number, y = score_coherence)) + geom_point() + geom_line(group = 1) + ggtitle("Coherence by Topic") + theme_minimal() + scale_x_continuous(breaks = seq(1,20,1)) + ylab("Coherence Score") + xlab("Number of topics")
Yüksek bir tutarlılık değeri, metnin konulara daha iyi bölündüğünü gösterir:
En yüksek tutarlılık puanımıza k = 13 ile ulaşıyoruz, bu nedenle 13 konu ile eğitilmiş LDA modelini kullanacağız. GetTopTerms işlevi aracılığıyla, her konu için 10 ana kelimeyi görebilir ve bunlar aracılığıyla konu semantiğini tahmin edebiliriz:
best_model <- models[which.max(coherence_by_topics_quantity$score_coherence)][[ 1 ]] # Most important terms by topic: best_model$top_terms <- GetTopTerms(phi = best_model$phi, M = 20) top10 <- as.data.frame(best_model$top_terms) top10
Aşağıdaki tablo, tespit edilen en önemli beş konuyu ve bunlara örnek teşkil eden 10 ana kelimeyi detaylandırmaktadır:
t_1 | t_2 | t_3 | t_4 | t_5 | |
---|---|---|---|---|---|
1 | messi | messi | messi | messi | messi |
2 | aslan | lig | Avustralya, Brezilya ve Kuzey Amerika ülkelerinin kullandığı saat uygulaması | psg | |
3 | Lionel Messi | İleti | kazanç | il | aslan |
4 | psg | milyon | hedefler | ben | Leo Messi |
5 | Madrid | seviyor | ch | dökün | ahora |
6 | gerçek | ben | iyonlar | pas | yoldaş |
7 | barselona | keçi | ch_ions | ortalama | va |
8 | Paris | psg | ucl | du | ser |
9 | Real Madrid | çubuk | balon | ki | jugador |
10 | mbapp | daha büyük | dünya | ben | büyük |
Bu topluluktaki çoğu kullanıcı İngilizce konuşsa da, hala Fransızca ve İspanyolca konuşanlar vardır (tabloda t_4 ve t_5). İlk konunun Messi'nin önceki takımı (FC Barcelona) ile ilgili olduğunu, ikinci konunun Messi'nin Instagram'daki gönderisiyle ilgili olduğunu ve üçüncü konunun Messi'nin başarılarına odaklandığını söyleyebiliriz.
Artık konuları öğrendiğimize göre, hangisinin en çok tartışıldığını tahmin edebiliriz. Bunu yapmak için, önce kullanıcıların tweetlerini birleştireceğiz (yine en büyük topluluktan):
tweets.df.com1 = tweets.df[which(tweets.df$screen_name %in% community1),] users_text <- ddply(tweets.df.com1, ~screen_name, summarise, text = paste(text, collapse = " "))
Daha sonra metni eskisi gibi temizliyoruz ve DTM'yi oluşturuyoruz. Bundan sonra, LDA modelimizi ve DTM'yi argüman olarak kullanarak predict
fonksiyonunu çağırırız. Ayrıca, analiz edilecek çok fazla metnimiz olduğu için hesaplama süresini iyileştirmek için yöntemi Gibbs olarak belirledik:
users_text$text <- sanitize_text(users_text$text) # Get rid of duplicates stopwords_regex = paste(stopwords('en'), collapse = '\\b|\\b') stopwords_regex = paste0('\\b', stopwords_regex, '\\b') users_text$text = stringr::str_replace_all(users_text$text, stopwords_regex, '') dtm.users.com1 <- CreateDtm(users_text$text, doc_names = users_text$screen_name, ngram_window = c(1, 2)) com1.users.topics = predict(best_model, dtm.users.com1, method="gibbs", iterations=100)
Şimdi, com1.users.topics
veri çerçevesinde, her kullanıcının her bir konu hakkında ne kadar konuştuğunu görüyoruz:
Hesap | t_1 | t_2 | t_3 | t_4 | t_5 | […] |
---|---|---|---|---|---|---|
___99. | 0.02716049 | 0.86666666 | 0.00246913 | 0.00246913 | 0.00246913 | |
Müdür__ | 0.05185185 | 0.84197530 | 0.00246913 | 0.00246913 | 0.00246913 | |
Memphis | 0,00327868 | 0,00327868 | 0.03606557 | 0,00327868 | 0,00327868 | |
___Alex1 | 0,00952380 | 0,00952380 | 0,00952380 | 0,00952380 | 0,00952380 | |
[…] |
Son olarak, bu bilgilerle, hangi konunun hangi kullanıcı tarafından en çok konuşulduğunu tanımlamak için düğüm grafiğinde yeni bir öznitelik oluşturabiliriz. Sonra onu Gephi'de görselleştirmek için yeni bir GML dosyası oluşturabiliriz:
# Get the subgraph of the first community: net.com1 = induced_subgraph(net,community1) # Estimate the topic with the max score for each user: com1.users.maxtopic = cbind(users_text$screen_name, colnames(com1.users.topics)[apply(com1.users.topics, 1, which.max)]) # Order the users topic data frame by the users' order in the graph: com1.users.maxtopic = com1.users.maxtopic[match(V(net.com1)$name, com1.users.maxtopic[,1]),] # Create a new attr of the graph by the topic most discussed by each user: V(net.com1)$topic = com1.users.maxtopic[,2] # Create a new graph: write_graph(simplify(net.com1), "messi_graph_topics.gml", format = "gml")
Önemli Konuları Çıkarma ve Sosyal Ağ Merkeziliğini Uygulama
Bu serinin ilk bölümünde, Twitter'dan nasıl veri elde edileceğini, etkileşim grafiğinin nasıl oluşturulacağını, Gephi üzerinden nasıl çizileceğini ve toplulukları ve önemli kullanıcıları nasıl tespit edeceğimizi öğrendik. Bu bölümde, etkili kullanıcıları tespit etmek için ek kriterlerin kullanımını göstererek bu analizi genişlettik. Ayrıca, kullanıcıların ne hakkında konuştuğunu nasıl tespit edip çıkaracağımızı ve bunu ağda nasıl çizeceğimizi gösterdik.
Bir sonraki yazımızda, kullanıcıların sosyal medyanın belasını nasıl tespit edebileceklerini göstererek bu analizi derinleştirmeye devam edeceğiz: spam robotları ve troller.
Toptal Mühendislik Blogunda Daha Fazla Okuma:
- Power BI ve R Kullanarak Sosyal Ağ Analizi: Özel Görseller Kılavuzu