R 및 Gephi를 통한 Twitter 역학 이해: 텍스트 분석 및 중심성

게시 됨: 2022-07-22

이 기사는 소셜 네트워크 분석 시리즈의 첫 번째 기사에서 제시된 분석을 확장하고 심화합니다. 첫 번째 기사에서 구성한 것과 동일한 Twitter 데이터 세트와 상호 작용 네트워크를 사용합니다. 그러나 이번에는 주역을 더 잘 추론하고 토론 주제를 식별하고 이러한 주제가 어떻게 확산되는지 이해하는 것이 아이디어입니다.

소셜 네트워크 중심성

목표를 달성하려면 먼저 중심성 개념을 도입해야 합니다. 네트워크 과학에서 중심성은 네트워크에 강한 영향을 미치는 노드를 나타냅니다. 영향력은 모호한 개념입니다. 그것은 여러 가지로 이해할 수 있다. 많은 가장자리를 가진 노드가 더 적지만 더 "중요한" 가장자리를 가진 노드보다 더 영향력이 있습니까? 소셜 네트워크에서 중요한 에지를 구성하는 것은 무엇입니까?

이러한 모호성을 해결하기 위해 네트워크 과학자들은 중심성을 측정하는 여러 가지 방법을 개발했습니다. 여기에서는 더 많은 것을 사용할 수 있지만 일반적으로 사용되는 네 가지 방법에 대해 설명합니다.

가장 일반적이고 직관적인 측정은 정도 중심성입니다. 차수 중심성의 이면에 있는 아이디어는 간단합니다. 노드의 차수로 영향을 측정합니다. 그래프가 지시된 경우 변형이 있을 수 있습니다. 이 경우 내도와 외도를 측정할 수 있습니다. 첫 번째는 허브 점수, 두 번째는 권위 점수입니다.

이 시리즈의 첫 번째 기사에서는 무방향 접근 방식을 사용했습니다. 이번에는 indegree 접근에 초점을 맞춥니다. 이렇게 하면 단순히 자주 리트윗하는 사용자보다 다른 사람이 리트윗하는 사용자를 강조하여 보다 정확한 분석이 가능합니다.

고유 벡터

고유 벡터 측정은 차수 중심성을 기반으로 합니다. 영향력 있는 노드가 주어진 노드를 더 많이 가리킬수록 점수가 높아집니다. 행과 열이 노드를 나타내는 인접 행렬 로 시작하고 1 또는 0을 사용하여 주어진 행과 열의 해당 노드가 연결되어 있는지 여부를 나타냅니다. 주요 계산은 행렬의 고유 벡터를 추정합니다. 주요 고유 벡터는 우리가 원하는 중심성 측정을 포함할 것이며, 여기서 i 위치는 노드 i 의 중심성 점수를 보유할 것입니다.

페이지 랭크

PageRank는 Google의 핵심에 있는 고유 벡터 측정의 변형입니다. Google이 사용하는 정확한 방법은 알려져 있지 않지만 일반적인 아이디어는 각 노드가 1의 점수로 시작한 다음 점수를 각 가장자리에 동일한 부분으로 분배한다는 것입니다. 예를 들어 노드에 세 개의 가장자리가 있는 경우 각 가장자리를 통해 점수의 1/3을 "전송"합니다. 동시에 노드는 노드를 가리키는 가장자리에 의해 더 중요해집니다. 그 결과 N 개의 미지수가 있는 N 방정식의 풀 수 있는 시스템이 생성됩니다.

사이

네 번째 측정값인 사이 는 매우 다른 접근 방식을 사용합니다. 여기서 노드는 다른 노드들 사이의 짧은 경로에 많이 포함되어 있으면 영향력이 있다고 한다. 즉, "다른 세계"를 연결하여 다른 많은 노드와 통신하는 역할을 합니다.

예를 들어, 소셜 네트워크 분석에서 이러한 종류의 노드는 다른 사람들이 새로운 직업을 찾거나 새로운 연결을 만드는 데 도움이 되는 유형의 사람들로 이해될 수 있습니다. 그들은 이전에 알려지지 않은 소셜 서클의 문입니다.

어떤 것을 사용해야 합니까?

적절한 중심성 측정은 분석 목표에 따라 다릅니다. 양적으로 다른 사람들이 자주 뽑는 사용자를 알고 싶습니까? 학위 중심성이 최선의 선택일 것입니다. 아니면 품질을 고려한 중심성 측정을 선호합니까? 이 경우 고유 벡터 또는 PageRank가 더 나은 결과를 산출합니다. 어떤 사용자가 서로 다른 커뮤니티 간의 다리 역할을 가장 효과적으로 수행하는지 알고 싶다면 매개가 최선의 선택입니다.

eigenvector 및 PageRank와 같은 여러 유사한 측정값을 사용할 때 모든 측정값을 추정하고 동일한 순위를 산출하는지 확인할 수 있습니다. 그렇지 않은 경우 차이점에 대한 분석을 심화하거나 점수를 결합하여 새로운 측정값을 생성할 수 있습니다.

또 다른 접근 방식은 주성분 분석을 사용하여 네트워크에 대한 노드의 실제 영향에 대한 추가 정보를 제공하는 측정값을 추정합니다.

실습 중심성 계산

R 및 RStudio를 사용하여 이러한 측정값을 계산하는 방법을 살펴보겠습니다. (Gephi로도 가능합니다.)

먼저 이 기사 전체에서 사용할 모든 라이브러리를 로드해야 합니다.

 library("plyr") library(igraph) library(tidyverse) library(NLP) library("tm") library(RColorBrewer) library(wordcloud) library(topicmodels) library(SnowballC) library("textmineR")

다음으로 이 분석에 유용하지 않기 때문에 이전에 사용한 데이터에서 격리된 노드를 제거합니다. 그런 다음 igraph 함수 betweenness , centr_eigen , page_rankdegree 를 사용하여 중심성 측정값을 추정합니다. 마지막으로 igraph 객체와 데이터 프레임에 점수를 저장하여 가장 중심적인 사용자를 확인합니다.

 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)

이제 각 측정 단위로 가장 중앙에 있는 10명의 사용자를 확인할 수 있습니다.

 top_n(cent, 10 ,degr)%>% arrange(desc(degr))%>% select(degr)
고유 벡터
 top_n(cent, 10 ,eig)%>% arrange(desc(eig))%>% select(eig)
페이지 랭크
 top_n(cent, 10 ,prank)%>% arrange(desc(prank))%>% select(prank)
사이
 top_n(cent, 10 ,bet)%>% arrange(desc(bet))%>% select(bet)

결과:

고유 벡터 페이지 랭크 사이
ESPNFC 5892 PSG_inside 1 문도다볼라 0.037 뷰디 77704
트롤축구 5755 크루매트19 0.51 알레리파로티 0.026 에드먼드 오리스 76425
PSG_inside 5194 eh01195991 0.4 PSG_inside 0.017 빌어먹을 63799
크루매트19 4344 모하마드135680 0.37 로이네머 0.016 프란시스코 가이우스 63081
축구 4054 액츄풋_ 0.34 트롤축구 0.013 예미하잔 62534
PSG_에스파놀 3616 마트발 0.34 ESPNFC 0.01 해시태그2weet 61123
이바이아웃 3258 ESPNFC 0.3 PSG_에스파놀 0.007 안젤라_FCB 60991
액츄풋_ 3175 축구 0.25 인스턴트풋 0.007 자이욘_ 57269
푸티유머 2976 세일러문아미 0.22 이바이아웃 0.006 크루매트19 53758
문도다볼라 2778 존스빌팻 0.2 2010미스터칩 0.006 MdeenOlawale 49572

처음 세 가지 측정값이 PSG_inside, ESPNFC, CrewsMat19 및 TrollFootball과 같은 여러 사용자를 공유한다는 것을 알 수 있습니다. 그들이 토론에 강한 영향을 미쳤다고 가정할 수 있습니다. 사이는 중심성을 측정하는 다른 접근 방식을 사용하므로 다른 기술과 많이 겹치지 않습니다.

참고: 이 기사에 언급된 Twitter 계정의 견해는 Toptal 또는 작성자의 견해를 반영하지 않습니다.

다음 이미지에서 두 개의 사용자 레이블 오버레이가 있는 원래의 컬러 네트워크 그래프를 볼 수 있습니다. 첫 번째 노드에서 노드는 PageRank 점수로 강조 표시되고 두 번째 노드에서는 중간 점수로 강조 표시됩니다.

상위 10명의 사용자와 해당 네트워크가 강조 표시된 컬러 PageRank 플롯을 보여주는 이미지. 가장 큰 세 사용자는 PSG_inside, TrollFootball 및 ESPNFC입니다. ESPNFC는 플롯 왼쪽에 보라색으로 표시되고 PSG_inside는 오른쪽에 빨간색으로 표시됩니다. TrollFootball은 녹색, 파란색 및 주황색 사용자 사이의 더 높은 오른쪽에 있습니다.
주요 PageRank 사용자 10명과의 메시 토론

상위 10명의 사용자와 해당 네트워크에 레이블이 지정되고 강조 표시된 채색된 중간 플롯을 보여주는 이미지입니다. 이전 이미지보다 크기가 더 유사한 상위 10명의 사용자는 모두 보라색으로 표시된 이미지의 왼쪽 하단 모서리에 있습니다. 그들은 단단히 함께 그룹화됩니다.
상위 10명의 중간 사용자와의 메시 토론 강조

Gephi를 사용하여 이러한 이미지를 재현할 수 있습니다. 통계 패널의 네트워크 직경 버튼을 사용하여 중간 또는 PageRank 점수를 추정할 수 있습니다. 그런 다음 이 시리즈의 첫 번째 기사에서 설명한 대로 속성을 사용하여 노드 이름을 표시할 수 있습니다.

텍스트 분석: R 및 LDA

또한 소셜 네트워크 토론을 분석하여 사용자가 이야기한 내용을 식별할 수 있습니다. 이에 접근하는 방법은 여러 가지가 있습니다. 함께 나타나는 경향이 있는 단어 집합을 추정할 수 있는 비지도 머신 러닝 기술인 LDA(Latent Dirichlet Allocation)를 통해 주제 모델링을 수행합니다. 그런 다음 해당 단어 집합을 통해 논의 중인 주제를 유추할 수 있습니다.

첫 번째 단계는 텍스트를 소독하는 것입니다. 이를 위해 다음 함수를 정의합니다.

 # 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) }

또한 중지 단어, 중복 및 빈 항목을 제거해야 합니다. 다음으로 텍스트를 LDA에서 처리할 문서 용어 행렬로 변환해야 합니다.

이 데이터 세트에는 다양한 언어(영어, 스페인어, 프랑스어 등)를 사용하는 사용자가 있습니다. LDA는 단일 언어에 집중할 때 가장 잘 작동합니다. 주로 영어 사용자 계정으로 구성된 이 시리즈의 첫 번째 기사에서 발견된 가장 큰 커뮤니티의 사용자에게 적용할 것입니다.

 # 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))

주제 수 및 일관성 점수

LDA에서 정의해야 하는 주요 하이퍼파라미터는 추정하려는 주제의 수 (k) 입니다. 그러나 어떻게 미리 알 수 있습니까? 한 가지 일반적인 접근 방식은 다른 k 값에 대해 LDA 모델을 훈련하고 각각의 일관성을 측정하는 것입니다. 내 경험상 이 범위를 벗어난 값은 확인할 가치가 없기 때문에 3에서 20까지의 k 값에 대해 이 작업을 수행합니다.

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

다음으로 각각의 일관성 값을 그래프로 표시합니다.

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

높은 일관성 값은 텍스트가 주제로 더 잘 분할되었음을 보여줍니다.

다양한 주제에 대한 일관성 점수를 보여주는 그래프. 일관성 점수는 6~7개 주제에 대해 0.05를 약간 상회하며 3~12개 주제는 모두 0.065 미만의 점수를 나타냅니다. 점수는 갑자기 13개 주제에 대해 약 0.105로 최고점에 도달합니다. 그런 다음 17개 주제에 대해 0.06 아래로 내려가고 19개 주제에 대해 최대 0.09까지, 20개 주제에 대해 0.07 바로 위에서 끝납니다.

k = 13으로 최대 일관성 점수에 도달하므로 13개 주제로 훈련된 LDA 모델을 사용합니다. GetTopTerms 함수를 통해 각 주제에 대한 10개의 주요 단어를 보고 이를 통해 주제 의미를 추정할 수 있습니다.

 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

다음 표에는 감지된 가장 중요한 5가지 주제와 이를 예시하는 10가지 주요 단어가 자세히 설명되어 있습니다.

t_1 t_2 t_3 t_4 t_5
1 메시 메시 메시 메시 메시
2 라이오넬 인스 타 그램 리그 동부 표준시 PSG
리오넬 메시 게시하다 이기다 사자 별자리
4 PSG 백만 목표 레오_메시
5 마드리드 좋아하는 채널 붓다 아오라
6 진짜 스포 이온 우선권 컴파
7 바르셀로나 염소 채널 에벡
8 파리 PSG UCL 세르
9 레알_마드리드 술집 풍선 쥬가도르
10 mbapp 더 큰 세계 메이저

이 커뮤니티의 대부분의 사용자는 영어 사용자이지만 여전히 많은 프랑스어 및 스페인어 사용자가 있습니다(표의 t_4 및 t_5). 첫 번째 주제는 메시의 전 팀(FC 바르셀로나), 두 번째 주제는 인스타그램에 올린 메시의 글, 세 번째 주제는 메시의 업적에 초점을 맞춘 것으로 추측할 수 있다.

이제 주제가 있으므로 가장 많이 논의된 주제를 예측할 수 있습니다. 이를 위해 먼저 사용자의 트윗을 연결합니다(다시 말하지만 가장 큰 커뮤니티에서).

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

그런 다음 이전과 같이 텍스트를 삭제하고 DTM을 만듭니다. 그런 다음 LDA 모델과 DTM을 인수로 사용하여 predict 함수를 호출합니다. 또한 분석할 텍스트가 많기 때문에 계산 시간을 개선하기 위해 메서드를 Gibbs로 설정했습니다.

 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)

이제 com1.users.topics 데이터 프레임에서 각 사용자가 각 주제에 대해 얼마나 이야기했는지 확인합니다.

계정 t_1 t_2 t_3 t_4 t_5 […]
___99번째 0.02716049 0.86666666 0.00246913 0.00246913 0.00246913
사장님__ 0.05185185 0.84197530 0.00246913 0.00246913 0.00246913
멤피스 0.00327868 0.00327868 0.03606557 0.00327868 0.00327868
___알렉스1 0.00952380 0.00952380 0.00952380 0.00952380 0.00952380
[…]

마지막으로 이 정보를 사용하여 노드 그래프에 새 속성을 만들어 어떤 사용자가 가장 많이 이야기한 주제를 정의할 수 있습니다. 그런 다음 새 GML 파일을 만들어 Gephi에서 시각화할 수 있습니다.

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

Gephi를 사용하여 생성된 컬러 노드 그래프로 ESPNFC를 PageRank 중심성 기준으로 가장 높은 순위의 사용자로 표시합니다. ESPNFC는 이미지 하단 근처에 있으며 많은 보라색 노드가 그 아래에 그룹화되어 있습니다.
주제별로 색칠된 최대 메시 토론 커뮤니티 및 PageRank 중심으로 강조 표시된 사용자

그래프에 사용된 각 색상으로 강조 표시된 사용자의 비율을 보여주는 이미지. 보라색 "t 6"이 가장 많이 사용된 색상(그래프에서 모든 사용자의 40.53%)이고 11.02에서 녹색 "t 13"이 그 뒤를 잇습니다. % 및 9.68%에서 파란색/청록색 "t 10". 이 11개 목록의 마지막에서 두 번째 위치에 있는 회색 "NA"는 2.25%를 구성합니다.
그래프에 사용된 각 색상에 대한 주제 레이블 및 사용자 비율

중요한 주제 추론 및 소셜 네트워크 중심성 적용

이 시리즈의 첫 번째 기사에서는 Twitter에서 데이터를 얻고, 상호 작용 그래프를 만들고, Gephi를 통해 플롯하고, 커뮤니티와 중요한 사용자를 감지하는 방법을 배웠습니다. 이 기사에서는 영향력 있는 사용자를 감지하기 위해 추가 기준을 사용하는 방법을 보여줌으로써 이 분석을 확장했습니다. 또한 사용자가 말하는 내용을 감지하고 추론하고 네트워크에서 플롯하는 방법도 시연했습니다.

다음 기사에서는 사용자가 스팸봇과 트롤과 같은 소셜 미디어의 재앙을 감지하는 방법을 보여줌으로써 이 분석을 계속 심화할 것입니다.

Toptal 엔지니어링 블로그에 대한 추가 정보:

  • Power BI 및 R을 사용한 소셜 네트워크 분석: 사용자 지정 시각적 개체 가이드