一、node2vec原理
node2vec是由Perozzi 等学者提出的将 word2vec 的思想用于图节点表示学习的一种Deepwalk 算法, 该算法在Deepwalk的基础上改变了随机游走的序列生成方式, 通过半监督的方式学习
p
p
p,
q
q
q 两个超参数的值, 控制游走对深度和广度的趋向, 其中
p
p
p控制跳向前节点邻居的概率,
q
q
q控制跳向前节点非邻居的概率, 如图所示:
当
q
>
1
q>1
q>1时, 趋向于遍历临近
t
t
t节点的
x
1
x_1
x1节点,即趋向于BFS;当
p
>
1
p>1
p>1时, 趋向于遍历临近
t
t
t节点的
x
2
x_2
x2或
x
3
x_3
x3节点, 即趋向于DFS。在确定要遍历的邻居节点之后, 采用 skip-gram 模型进行训练进而获得节点的向量表示。
node2vec算法的详细推导请移步:https://zhuanlan.zhihu.com/p/46344860
二、Python代码实现
1. node2vec依赖word2vec,以及需要用到网络图,所以需要安装三个包
pip install gensim
pip install node2vec
pip install networkx
2. 导入所需包
import jieba
import networkx as nx
from node2vec import Node2Vec
from gensim.models import Word2Vec
3. 准备中文分词语料
本文省略数据读取部分,直接从分词开始。
content_cut = content.apply(lambda text:jieba.lcut(text))
其中content为pandas读取的中文文档。
4. 构建网络图
graph = nx.Graph() # 网络初始化
# 构建网络图(笔者选择词的相差长度为1作为共词标准)
for cont in content_cut.values:
for ind, word, in enumerate(cont[:-1]):
graph.add_edge(word, cont[ind+1])
5. node2vec图的构建,向量维度设置为200维
node2vec = Node2Vec(graph, dimensions=200, walk_length=30, num_walks=200, workers=1)
6. node2vec模型训练与保存
model = node2vec.fit(window=10, min_count=1, batch_words=4)
model.save('node2vec.model')
如果数据量大,第五、六步耗时较长,需要耐心等待。
7. 加载模型并构建文档向量
# 加载模型
node2vec = Word2Vec.load(node2vec.model')
def get_text_node2vec():
text_vec = np.zeros((content.shape[0], 200))
for ind, text in enumerate(content):
wlen = len(text)
vec = np.zeros((1, 200))
for w in text:
try:
vec += node2vec.wv[w]
except:
pass
text_vec[ind] = vec/wlen
word2vec = pd.DataFrame(data=text_vec)
word2vec.to_csv('node2vec.csv', index=False)
get_text_node2vec()
以上便完成了node2vec词向量训练,并构建了每个文档的向量,方便后续深入挖掘分析。与word2vec相比,node2vec算法由于涉及到太多的循环迭代,所以训练词向量的时间较长。