0. 개요
사회 연결망 분석(* Social Network Analysis)는 분석 대상 및 분석 대상들간의 관계를 연결망 구조로 표현하고 이를 계량적으로 제시하는 분석 기법입니다.
사회 연결망 분석은 사람, 장소, 물품 등의 객체 간의 관계를 분석하는데 효과적이며 주로 친구 관계, 전력 공급 등을 분석하는데 사용합니다.
사회 연결망 분석 기법은 텍스트 내 단어의 관계에 적용한 것이 바로 의미 연결망 분석입니다.
의미 연결망 분석에서는 일정한 범위 내에서 어휘가 동시에 등장하면 서로 연결된 것으로 간주, 이 연결 관계를 분석합니다.
1. n-gram
nltk 라이브러리는 편하게 n-gram을 생성할 수 있는 함수를 제공합니다.
먼저 nltk 의 'punkt' 를 다운받습니다.
import nltk
nltk.download('punkt')
그리고 주어진 문장을 토큰화 한 후, bigram 을 이용합니다.
from nltk import word_tokenize, bigrams
sentence = 'I love data science and deep learning'
# 토큰화
tokens = word_tokenize(sentence)
bgram = bigrams(tokens)
bgram_list = [x for x in bgram]
print(bgram_list)
# output:
# [('I', 'love'), ('love', 'data'),
# ('data', 'science'), ('science', 'and'), ('and', 'deep'), ('deep', 'learning')]
더 많은 데이터를 얻고 싶다면 trigram, quadgram 을 사용합니다.
from nltk.util import ngrams
tgram = ngrams(tokens, 3)
qgram = ngrams(tokens, 4)
tgram_list = [x for x in tgram]
qgram_list = [x for x in qgram]
print(tgram_list)
print(qgram_list)
# output:
# [('I', 'love', 'data'), ('love', 'data', 'science'), ('data', 'science', 'and'), ('science', 'and', 'deep'), ('and', 'deep', 'learning')]
# [('I', 'love', 'data', 'science'), ('love', 'data', 'science', 'and'), ('data', 'science', 'and', 'deep'), ('science', 'and', 'deep', 'learning')]
2. 어휘 동시 출현 빈도의 계수화
동시 출현(* Co-occurrence)란 두 개 이상의 어휘가 일정한 범위나 거리 내에서 함께 출현하는 것을 의미합니다.
단어간의 동시 출현 관계를 분석하면 문서나 문장으로부터 두 단어가 유사한 의미를 가졌는지 등의 추상화된 정보를 얻을 수 있습니다.
동시 출현 빈도는 Window라는 지정 범위 내에서 동시 등장한 어휘를 확률 등으로 계수화 가능합니다.
예를 들어, 단어 뒤 잘못된 단어가 온다면, 이를 동시 출현 빈도가 높은 단어로 교정할 수 있습니다.
어휘 동시 출현 빈도 행렬은 하나하나 측정할 수도 있지만, 바이그램 개수를 정리하면 편리하게 만들어 볼 수 있습니다.
nltk 에서 제공하는 ConditionalFreqDist 함수를 이용하면 문맥별 단어 빈도를 쉽게 측정할 수 있습니다.
from nltk import ConditionalFreqDist
sentences = ['I love data science and deep learning', 'I love science', 'I know this code']
tokens = [word_tokenize(x) for x in sentences]
bgrams = [bigrams(x) for x in tokens]
token = []
for i in bgrams:
token += ([x for x in i])
cfd = ConditionalFreqDist(token)
# 조건이 되는(* 쿼리가 되는) 단어들 출력
cfd.conditions()
# output:
# ['I', 'love', 'data', 'science', 'and', 'deep', 'know', 'this']
ConditionalFreqDist 를 통해 동시 출현 빈도 행렬을 만들 수 있습니다.
import numpy as np
freq_matrix = []
for i in cfd.keys():
temp = []
for j in cfd.keys():
temp.append(cfd[i][j])
freq_matrix.append(temp)
freq_matrix = np.array(freq_matrix)
print(cfd.keys())
print(freq_matrix)
# output:
'''
dict_keys(['I', 'love', 'data', 'science', 'and', 'deep', 'know', 'this'])
[[0 2 0 0 0 0 1 0]
[0 0 1 1 0 0 0 0]
[0 0 0 1 0 0 0 0]
[0 0 0 0 1 0 0 0]
[0 0 0 0 0 1 0 0]
[0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 1]
[0 0 0 0 0 0 0 0]]
'''
좀 더 깔끔하게 보기 위해 DataFrame 으로 시각화 합니다.
df = pd.DataFrame(freq_matrix, index = cfd.keys(), columns = cfd.keys())
df.style.background_gradient(cmap='coolwarm')
결과
이때 동시 출현 빈도 행렬은 인접 행렬로도 간주할 수 있는데,
이를 통해 networkx 를 사용해 그래프로 시각화 할 수 있습니다.
import networkx as nx
G = nx.from_pandas_adjacency(df)
# 그래프의 노드와 엣지를 출력
print(G.nodes())
print(G.edges())
# output:
# ['I', 'love', 'data', 'science', 'and', 'deep', 'know', 'this']
# [('I', 'love'), ('I', 'know'), ('love', 'data'), ('love', 'science'), ('data', 'science'), ('science', 'and'), ('and', 'deep'), ('know', 'this')]
nx.draw 를 통해 간편하게 그래프를 시각화할 수 있습니다.
nx.draw(G, with_labels=True)
결과
3. 중심성 분석
연결망 분석에서 가장 많이 주목하는 속성은 바로 중심성 지수입니다.
중심성을 전체 연결망에서 중심에 위치하는 정도를 표현하는 지표로, 이를 분석하면 연결 정도, 중요도 등을 알 수 있습니다.
중심성 지수는 나타내는 특징에 따라 다음과 같이 구분할 수 있습니다:
- 연결 중심성
- 매개 중심성
- 근접 중심성
- 위세 중심성
3.1 연결 중심성
연결 중심성은 가장 기본적이고 직관적으로 중심성을 측정하는 지표입니다.
텍스트에서 다른 단어와의 동시 출현 빈도가 많은 특정 단어는 연결 중심성이 높다고 볼 수 있습니다.
연결 정도로만 측정한다면 연결망의 크기에 따라 달라져 비교가 어렵기 때문에 여러 방법으로 표준화해야 합니다.
(* 연결되어있는 노드의 개수가 많으면 중심성이 그냥 높아짐)
그래서 주로 (특정 노드 i와 직접적으로 연결된 노드 수 / 노드 i와 직간접적으로 연결된 노드 수)로 계산해서 정규화를 해줍니다.
여기서 직접적으로 연결된 노드는 서로 엣지 관계인 노드를 뜻하며, 간접적으로 연결된 노드는 서로 엣지 관계는 아니나 다른 노드와 엔지에 의해 도달할 수 있는 노드를 말합니다.
이는 networkx의 degree_centrality() 를 통해 구할 수 있습니다.
nx.degree_centrality(G)
# output:
'''
{'I': 0.2857142857142857,
'love': 0.42857142857142855,
'data': 0.2857142857142857,
'science': 0.42857142857142855,
'and': 0.2857142857142857,
'deep': 0.14285714285714285,
'know': 0.2857142857142857,
'this': 0.14285714285714285}
'''
3.2 위세 중심성
위세 중심성은 연결된 상대 단어의 중요성에 가중치를 둡니다.
중요한 단어와 많이 연결됐다면 위세 중심성은 높아지게 됩니다.
위세 중심성은 고유 벡터로써 인접해 있는 노드의 위세 점수와 관련되어 있어서 직접 계산하기는 쉽지 않습니다.
위세 중심성 계산에는 eigenvector_centrality() 를 이용합니다.
(* weight 로는 어휘 동시 출현 빈도를 이용합니다.)
nx.eigenvector_centrality(G)
# output:
'''
{'I': 0.29326042267418495,
'love': 0.5444588678327624,
'data': 0.45743606861852176,
'science': 0.5396394974482632,
'and': 0.27702186019379066,
'deep': 0.11688896952645939,
'know': 0.15054806537664825,
'this': 0.06352526616240758}
'''
3.3 근접 중심성
근접 중심성은 한 단어가 다른 단어에 얼마나 가깝게 있는지를 측정하는 지표입니다.
직접적으로 연결된 노드만 측정하는 연결 중심성과는 다르게, 근접 중심성은 직간접적으로 연결된 모든 노드들 사이의 거리를 측정합니다.
근접 중심성을 측정하기 위해서 다음과 같은 계산식을 사용합니다:
(모든 노드 수 - 1) / (특정 노드 i 에서 모든 노드에 이르는 최단 경로 수를 모두 더한 수)
근접 중심성을 계산하기 위해서 closeness_centrality() 함수를 사용합니다.
nx.closeness_centrality(G)
# output:
'''
{'I': 0.4666666666666667,
'love': 0.5384615384615384,
'data': 0.4375,
'science': 0.5,
'and': 0.3888888888888889,
'deep': 0.2916666666666667,
'know': 0.3684210526315789,
'this': 0.28}
'''
3.4 매개 중심성
매개 중심성은 한 단어가 단어들과의 연결망을 구축하는데 얼마나 도움을 주는지를 측정하는 지표입니다.
매개 중심성이 높은 단어는 빈도 수가 작더라도 단어 간 의미부여의 역할이 크기 때문에, 해당 단어를 제거하면 의사소통이 어려워집니다.
매개 중심성은 모든 노드 간 최단 경로에서 특정 노드가 등장하는 횟수로 측정하며, 표준화를 위해 최대값인 (N-1)(N-2) / 2 로 나눕니다.
매개 중심성을 계산하기 위해서 betweenness_centrality() 메소드를 사용합니다.
nx.betweenness_centrality(G)
# output:
'''
{'I': 0.47619047619047616,
'love': 0.5714285714285714,
'data': 0.0,
'science': 0.47619047619047616,
'and': 0.2857142857142857,
'deep': 0.0,
'know': 0.2857142857142857,
'this': 0.0}
'''
3.5 페이지 랭크
월드 와이드 웹과 같은 하이퍼링크 구조를 가지는 문서에 상대적 중요도에 따라 가중치를 부여하는 방법입니다.
이 알고리즘은 서로간의 인용과 참조로 연결된 임의의 묶음에 적용할 수 있습니다.
페이지 랭크는 더 중요한 페이지는 더 많은 다른 사이트로부터 링크를 받는다는 관찰에 기초한 알고리즘입니다.
페이지 랭크를 계산하기 위해서 pagerank() 메소드를 사용합니다.
nx.pagerank(G)
# output:
'''
{'I': 0.1536831077679558,
'love': 0.19501225218917406,
'data': 0.10481873412175656,
'science': 0.15751225722745082,
'and': 0.12417333539164832,
'deep': 0.07152392879557615,
'know': 0.1224741813421488,
'this': 0.07080220316428934}
'''
3.6 시각화
def get_node_size(node_val):
nsize = np.array([v for v in node_val])
nsize = 1000 * (nsize - min(nsize)) / (max(nsize) - min(nsize))
return nsize
import matplotlib.pyplot as plt
plt.style.use('seaborn-white')
dc = nx.degree_centrality(G).values()
ec = nx.eigenvector_centrality(G, weight='weight').values()
cc = nx.closeness_centrality(G, distance='weight').values()
bc = nx.betweenness_centrality(G).values()
pr = nx.pagerank(G).values()
plt.figure(figsize=(14,20))
# plt.axis(off)
plt.subplot(321)
plt.title('Normal', fontsize=16)
nx.draw_networkx(G, font_size=16, alpha=0.7, cmap=plt.cm.Blues)
plt.subplot(322)
plt.title('Degree Centrality', fontsize=16)
nx.draw_networkx(G, font_size=16, node_color=list(dc), node_size=get_node_size(dc), alpha=0.7, cmap=plt.cm.Blues)
plt.subplot(323)
plt.title('Eigenvector Centrality', fontsize=16)
nx.draw_networkx(G, font_size=16, node_color=list(ec), node_size=get_node_size(ec), alpha=0.7, cmap=plt.cm.Blues)
plt.subplot(324)
plt.title('Closeness Centrality', fontsize=16)
nx.draw_networkx(G, font_size=16, node_color=list(cc), node_size=get_node_size(cc), alpha=0.7, cmap=plt.cm.Blues)
plt.subplot(325)
plt.title('Betweenness Centrality', fontsize=16)
nx.draw_networkx(G, font_size=16, node_color=list(bc), node_size=get_node_size(bc), alpha=0.7, cmap=plt.cm.Blues)
plt.subplot(326)
plt.title('Page Rank', fontsize=16)
nx.draw_networkx(G, font_size=16, node_color=list(pr), node_size=get_node_size(pr), alpha=0.7, cmap=plt.cm.Blues)
plt.show()
결과
배움
중심성 분석
의미 연결망 분석은 n-gram을 통해서만 할 수 있는것이 아니라,
tf-idf 를 통해 단어들의 벡터화를 한 후
코사인 유사도나 피어슨 상관계수를 통해 단어들간의 가중치를 부여한다면,
이 또한 시각화 가능하다 !!
https://www.j-kosham.or.kr/journal/view.php?viewtype=pubreader&number=10151
(* 의미 연결망 분석을 tf-idf 와 상관계수로 분석한 예시)
'[Deep daiv.] > [Deep daiv.] NLP' 카테고리의 다른 글
[Deep daiv.] WIL, NLP - 7. Seq2seq with Attention (0) | 2024.08.29 |
---|---|
[Deep daiv.] WIL, NLP - 5. 토픽 모델링 (0) | 2024.08.22 |
[Deep daiv.] WIL, NLP - 3. 군집 분석 (0) | 2024.08.20 |
[Deep daiv.] TIL & WIL - 5. 자연어 처리 & 텍스트 처리 (Contd.) (0) | 2024.08.14 |
[Deep daiv.] WIL, NLP - 1. 텍스트 처리 (0) | 2024.08.09 |