使用DeepWalk 和Word2Vec实现单词Embedding

0、准备“边”数据集Wiki_edgelist

import pandas as pd

df = pd.read_csv('./data/wiki/Wiki_edgelist.txt', sep=' ', header=None, names=["source", "target"])
df.head()

1、读入 起点-终点 边数据,构建图

# 1、读入 起点-终点 边数据,构建图
import networkx as nx
# G = nx.from_pandas_edgelist(df, "source", "target", edge_attr=True, create_using=nx.Graph())
G = nx.read_edgelist('./data/wiki/Wiki_edgelist.txt',
                         create_using=nx.DiGraph(), nodetype=None, data=[('weight', int)])
print(G)
print(len(G))
DiGraph with 2405 nodes and 16523 edges
2405

2. 定义并实现一个输入起始点和随机游走步数的函数

# 2. 定义并实现一个输入起始点和随机游走步数的函数
import random
def get_randomwalk(node, path_length):
    '''
    输入起始节点和路径长度,生成随机游走节点序列
    '''
    
    random_walk = [node]
    
    for i in range(path_length-1):
        # 汇总邻接节点
        temp = list(G.neighbors(node))
        temp = list(set(temp) - set(random_walk))    
        if len(temp) == 0:
            break
        # 从邻接节点中随机选择下一个节点
        random_node = random.choice(temp)
        random_walk.append(random_node)
        node = random_node
        
    return random_walk


# 试着从随机森林出发,采样五个节点
# get_randomwalk('random forest', 5)
get_randomwalk('66', 5)
['66', '68', '1449', '1465', '1461']

3. 把所有节点放进一个列表list中。

4. 对每个节点生成随机游走序列

 5. 对每个结点跑DeepWalk

# 3. 把所有节点放进一个列表list中。
all_nodes = list(G.nodes())
print(all_nodes[:10])

# 4. 接下来对每个节点生成随机游走序列
gamma = 10 # 每个节点作为起始点生成随机游走序列个数
walk_length = 5 
# walk_length 为随机游走序列最大长度
# 可是是无向图喔,length为什么可以小于5呢,不回原路返回吗?答案是不会,看上面get_randomwalk函数的定义,是会排除掉出发点的


from tqdm import tqdm
# 5. 对每个结点跑DeepWalk
random_walks = []

for n in tqdm(all_nodes):
    # 遍历每个节点
    for i in range(gamma):
        #每个节点作为起始点生成gamma个随机游走序列
        random_walks.append(get_randomwalk(n, walk_length))
        
# 跑出来的随机游走序列个数
print(len(random_walks))
# 查看一个节点的 10个随机游走序列
print(random_walks[:gamma])
['1397', '1470', '362', '226', '750', '489', '1462', '1713', '393', '445']
100%|██████████| 2405/2405 [00:00<00:00, 7602.81it/s]
24050
[['1397', '226', '1467', '1466', '1450'], ['1397', '750', '489', '464', '397'], ['1397', '226', '246', '225', '224'], ['1397', '750', '489', '339', '1717'], ['1397', '226', '216', '222', '124'], ['1397', '226', '1464', '1444', '1445'], ['1397', '750', '1525', '1470', '1540'], ['1397', '226', '232', '235', '247'], ['1397', '489', '1825', '1860', '1722'], ['1397', '489', '708', '1530', '1498']]

6. 直接用Word2Vec来处理DeepWalk

# 6. 直接用Word2Vec来处理DeepWalk
from gensim.models import Word2Vec # 自然语言处理
model = Word2Vec(vector_size=256, # Embedding维数
                 window=4, # 窗口宽度,NLP中就是左边看四个词,右边看四个词,graph就是左看四节点,右看四节点
                 sg=1, # Skip-Gram,中心节点预测周围4*2节点;为0就是周围节点预测中心节点
                 hs=0, # 不加分层softmax
                 negative=10, # 负采样
                 alpha=0.03,  # 初始学习率
                 min_alpha=0.0007, # 最小学习率
                 seed=14 # 随机数种子
                )

# 用随机游走序列构建词汇表
model.build_vocab(random_walks, progress_per=2)

# 训练,启动
model.train(random_walks, total_examples=model.corpus_count, epochs=50, report_delay=1)

7.  分析Wod2Vec(DeepWalk)结果

# 7.  分析Wod2Vec(DeepWalk)结果
# 查看单词/节点 的embedding
print(model.wv.get_vector("66").shape)
model.wv.get_vector("66")

8、查看和单词相似度高的单词(节点)

# 8、查看和单词相似度高的单词(节点)

model.wv.similar_by_word("66")
[('966', 0.7036892175674438),
 ('897', 0.6912005543708801),
 ('60', 0.6891793608665466),
 ('183', 0.684368908405304),
 ('67', 0.6747772693634033),
 ('11', 0.6455847024917603),
 ('118', 0.638038694858551),
 ('2006', 0.6363611817359924),
 ('181', 0.6297730803489685),
 ('65', 0.623363196849823)]

9、绘制图 可视化

# 将Embedding用TSNE降维到2维
from sklearn.manifold import TSNE
tsne = TSNE(n_components=2, n_iter=1000)
embed_2d = tsne.fit_transform(X)
 
plt.figure(figsize=(14,14))
plt.scatter(embed_2d[:, 0], embed_2d[:, 1])
plt.show()

将我们关心的节点展示在二维空间直角坐标系中
# 结合PageRank,计算出PageRank节点重要度前三十的节点,再加上一些手动补充我们关心的节点,把这一些节点进行可视化在二维图里。

# 计算PageRank重要度
pagerank = nx.pagerank(G)
# 从高到低排序
node_importance = sorted(pagerank.items(), key=lambda x:x[1], reverse=True) # 排序
 
# 取最高的前n个节点
n = 30
terms_chosen = []
for each in node_importance[:n]:
    terms_chosen.append(each[0])

# 手动补充我们关心的节点
terms_chosen.extend(['666','66'])

# 得到一个转换器term2index :输入词条,输出词典中的索引号
term2index = model.wv.key_to_index

# 10-2 将刚刚的PageRank节点重要度前三十的节点,再加上一些手动补充我们关心的节点再次展示在二维空间直角坐标系中。 
plt.figure(figsize=(14,14))
plt.scatter(embed_2d[:, 0], embed_2d[:, 1])
for item in terms_chosen:
    idx = term2index[item]
    plt.scatter(embed_2d[idx,0], embed_2d[idx,1],c='r',s=50)
    plt.annotate(item, xy=(embed_2d[idx,0], embed_2d[idx,1]),c='k',fontsize=12)
plt.show()

相关推荐

  1. Word2Vec原理+gensim实现

    2024-07-15 05:42:01       61 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-15 05:42:01       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-15 05:42:01       72 阅读
  3. 在Django里面运行非项目文件

    2024-07-15 05:42:01       58 阅读
  4. Python语言-面向对象

    2024-07-15 05:42:01       69 阅读

热门阅读

  1. leetcode239.滑动窗口最大值

    2024-07-15 05:42:01       13 阅读
  2. SQL基础 | NOT NULL 约束介绍

    2024-07-15 05:42:01       23 阅读
  3. 算法金 | 深度学习图像增强方法总结

    2024-07-15 05:42:01       17 阅读
  4. rabbitmq解除消息者消息推送限制

    2024-07-15 05:42:01       23 阅读
  5. 迪米特法则

    2024-07-15 05:42:01       25 阅读
  6. SpringBoot+Vue实现简单的文件上传(策略模式)

    2024-07-15 05:42:01       25 阅读