R ve Gephi ile Twitter Dinamiklerini Anlamak: Metin Analizi ve Merkezilik

Yayınlanan: 2022-07-22

Bu 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
 top_n(cent, 10 ,degr)%>% arrange(desc(degr))%>% select(degr)
özvektör
 top_n(cent, 10 ,eig)%>% arrange(desc(eig))%>% select(eig)
Sayfa Sıralaması
 top_n(cent, 10 ,prank)%>% arrange(desc(prank))%>% select(prank)
arasındalık
 top_n(cent, 10 ,bet)%>% arrange(desc(bet))%>% select(bet)

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:

En iyi 10 kullanıcı ve ağlarının vurgulandığı renkli bir PageRank grafiğini gösteren bir resim. En büyük üç kullanıcı PSG_inside, TrollFootball ve ESPNFC'dir. ESPNFC, arsanın solunda bulunur ve mor renklidir, PSG_inside ise sağına kırmızı renkli olarak yerleştirilir. TrollFootball, yeşil, mavi ve turuncu renkli kullanıcılar arasında daha yüksekte ve sağda bulunur.
En iyi 10 PageRank kullanıcısıyla Messi tartışması vurgulandı

En iyi 10 kullanıcı ve ağlarının etiketlenip vurgulandığı renkli bir aradalık grafiğini gösteren bir resim. Boyut olarak bir önceki görsele göre daha çok benzeyen ilk 10 kullanıcının tamamı, görselin sol alt köşesinde mor renkle yer alıyor. Sıkı bir şekilde gruplandırılmışlardır.
En iyi 10 aradalık kullanıcısıyla Messi tartışması vurgulandı

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:

Farklı konular için tutarlılık puanını gösteren bir grafik. Tutarlılık puanı, altı ila yedi konuda 0.05'in biraz üzerinde değişir ve üç ila 12 konunun tümü 0.065'in altında bir puana sahiptir. Skor aniden 13 konu için yaklaşık 0.105'te zirveye çıkıyor. Ardından 17 konu için 0,06'nın altına, 19 konu için yaklaşık 0,09'a kadar çıkıyor ve 20 konu için 0,07'nin hemen üzerinde bitiyor.

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 instagram 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") 

ESPNFC'yi PageRank merkeziliği tarafından en yüksek rütbeli kullanıcı olarak gösteren, Gephi kullanılarak oluşturulan renkli bir düğüm grafiği. ESPNFC, altında gruplandırılmış birçok mor düğüm ile görüntünün altına yakın bir yerde bulunur.
Konuya göre renklendirilmiş ve kullanıcıların PageRank merkeziliği ile vurgulandığı en büyük Messi tartışması topluluğu

Mor "t 6" en çok kullanılan renk (grafikteki tüm kullanıcıların %40,53'ü) ve ardından 11.02'de yeşil "t 13" ile grafikte kullanılan her renkle vurgulanan kullanıcıların yüzdesini gösteren bir resim % ve mavi/camgöbeği "t 10" %9.68'de. Bu 11 listenin sondan ikinci sırasındaki gri bir "NA", %2,25'i oluşturur.
Grafikte kullanılan her renk için konu etiketleri ve kullanıcı yüzdesi

Ö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