#HITS
print(nx.hits(G))
结果
[(1, 3), (2, 2), (4, 2), (5, 3), (3, 2)]
[{1, 2, 3, 4, 5}]
2
{1: 0.75, 2: 0.5, 4: 0.5, 5: 0.75, 3: 0.5}
{1: 0.5298988890761731, 2: 0.35775191431708964, 4: 0.4271316779596084, 5: 0.5298988890761731, 3: 0.35775191431708964}
{1: 0.25, 2: 0.08333333333333333, 4: 0.0, 5: 0.25, 3: 0.08333333333333333}
{1: 0.8, 2: 0.6666666666666666, 4: 0.6666666666666666, 5: 0.8, 3: 0.6666666666666666}
{1: 0.24369622576677996, 2: 0.17225629712058638, 4: 0.16809495422526693, 5: 0.2436962257667799, 3: 0.17225629712058638}
({1: 0.24059715195481507, 2: 0.1624345647450478, 4: 0.19393656660027417, 5: 0.2405971519548151, 3: 0.1624345647450478}, {1: 0.2405971522393837, 2: 0.1624345646565165, 4: 0.19393656620819955, 5: 0.2405971522393837, 3: 0.1624345646565165})
## 三 邻接矩阵
图像可以作为邻居矩阵 ,A表示邻居之间的关系
GNN(A,X)
文本数据也可以表示图的形式,零阶矩阵表示连接关系
Graphs ->are ->all ->around ->us
| | Graphs | are | all | around | us |
| --- | --- | --- | --- | --- | --- |
| Graphs | | 1 | | | |
| are | | | 1 | | |
| all | | | | 1 | |
| around | | | | | 1 |
| us | | | | | |
GNN要求所有图的格式是一样的,考虑GCN
## 四 Graph embedding图嵌入
结合第2章的代码可以知道表示图,节点数和边数决定了维度。
### 4.1 DeepWalk(无向图)
简化了节点的长度
DeepWalk给出的方法是使用随机游走(RandomWalk)的方式在图中进行节点采样。
RandomWalk是一种**可重复访问已访问节点的深度优先遍历**算法。给定当前访问起始节点,从其邻居中随机采样节点作为下一个访问节点,重复此过程,直到访问序列长度满足预设条件。
获取足够数量的节点访问序列后,使用skip-gram model 进行向量学习。
[【Graph Embedding】DeepWalk:算法原理,实现和应用 - 知乎 (zhihu.com)]( )")
### 4.2 Line(有向图)
大规模的图上,表示节点之间的结构信息。
一阶:局部的结构信息 (连接的节点很相似)
二阶:节点的邻居。共享邻居的节点可能是相似的 (不连接的节点A和B,但是A和B分别的连接点很相似,那么A和B也相似)邻居节点多的比较适用此办法
联合概率分布
经验概率分布
### 4.3 node2Vec
homophily:同质性
structural equivalence:结构等价性
BFS广度优先搜索
DFS深度优先搜索
### 4.4 Struct2Vec
对图的结构信息进行捕获,在其结构重要性大于邻居重要性时,有较好的效果。
### 4.5 SDNE
采用了多个非线性层的方式捕获一阶二阶的相似性。
## 四 消息传递
Source,Target
## 五 多层GCN的作用
GNN也可以有多层
GNN的本质就是更新各部分特征
其中输入是特征,输出也是特征,邻接矩阵也不会变的
(感受野)
## 六 图卷积GCN
图卷积和卷积有什么不同?
看起来都是利用周围的特征,但是在图中每个点的邻居是不确定的
节点分类,对每个结点进行预测,不同点是否有连接预测
整个图分类,部分图分类等,不同子图是否相似,异常检测等
**GCN归根到底还是要完成特征提取操作,只不过输入对象不是固定格式**
如何获取特征呢?
通常交给GCN两个东西就行:1.各节点输入特征 2.网络结构图(邻接矩阵)
很多文章,半监督任务也能解决
GCN的基本思想:
争对橙色节点,计算他的特征:**平均其邻居特征(包括自身)后传入神经网络**
网络层数
这个跟卷积类似,GCN也可以做多层,每一层输入的还是节点特征,然后将当前特征与网络结构图继续传入下层就可以不断算下去
A,D,F
## 七 Graph Neural Network图神经网络
### 7.1 GCN
图卷积网络(Graph Convolution Networks,GCN)
[图卷积网络(Graph Convolutional Networks, GCN)详细介绍-CSDN博客]( )详细介绍-CSDN博客")
### 7.2 GraphSAGE
### 7.3 GAT
图注意力网络**Graph Attention Network (GAT)**
## 八 知识图谱结合图神经网络的模型模型
### 8.1 KGCN
KGCN提出于2019年。中心思想就是利用图神经网络的消息传递机制与基本推荐思想结合训练。在做KGCN模型时候,我们就把知识图谱是作为有权图,也就是关系会通过某种方式变为权重,而这个权重可被理解为是该关系影响用户行为的偏好程度。
计算过程
消息传递机制“**Embedding**”,Embedding 应该是一种映射,就像 Unicode 对应了某一个字符。在某种程度上,就是用来降维的,降维的原理就是矩阵乘法[通俗讲解pytorch中nn.Embedding原理及使用 - 简书 (jianshu.com)]( )")
[KGCN\_基于知识图谱的推荐系统(KG+GCN)\_kgcn代码-CSDN博客]( )
l[KGCN:推荐系统的知识图谱卷积神经网络(Hongwei et al.,2019) - 知乎]( )
**前置知识:**
显式回馈(用户给物品打分)和隐式回馈(点击1,不点击0)
协同过滤:稀疏性,冷启动问题
**需要明确:**
1.user不属于entity
2.item是entity,但entity不一定是item(演员白鹿是一个实体,但是白鹿不能被推荐给用户,item理解为可以被推荐的东西)
3.user和item之间的关系是interaction(交互),entity和entity之间的关系叫relation.
所以在三元组其实是和interaction没有关系的。
**摘要:**
**KGCN的特点:**
1.端到端模型
2.通过感受野捕捉一个entity的邻域信息,且感受野可以扩展到高阶,以获取用户潜在的远距离兴趣
3.使用小批量方式进行训练
充分利用用用户-项目的属性信息。
**将知识图谱引入推荐系统的三个优势**
1.丰富了语义信息可以提升任务的精度
2.relation的多样性可以提升推荐项目的多样性
3.可解释性更强
RippleNet基本不关注relation的重要性
**KGCN的关键思想:**计算entity的representation时候聚集和 该entity的领域信息
**这种设计的优势**
1.能不或局部邻域结构并将其保存在当前entity中
2.relation和user都会影响邻域结构的权重,从而将知识图谱的语义和用户对于relation的个性化邢确这两个信息都引入进来
感受野:探查到附近的个数。(所以感受野的大小,合理化计算开销)
* user集合,item集合,interaction矩阵
* implicit feedback
* 知识图谱由entity和relation构成
* 学习预测函数,参数为interaction矩阵和知识图谱,用以预测某user和该user本身没有interaction的entity之间的交互概率
以单层KGCN Layer为例
![N(v)](https://latex.csdn.net/eq?N%28v%29)直接与item v相连的entity集合
定义函数g,用以刻画user对于某relation的重要性score
**公式算法**
![](https://img-blog.csdnimg.cn/3ebdb6e0aaa449f5ab5f5b30ea2195d7.png)
第三行的i表示:v目标节点的第几跳跃的节点
第二跳的时候将第一层和里面的v看成一个新的v。
步骤:
* 使用Microsoft Satori将上述数据集转化为KG
* 第二和第三类数据集相比于第一类更稀疏
* 三类数据集都是显式回馈,均将其转化为隐式
**修改此算法的方向**
1. 构建邻域结构时基于超参数K,统一采样(即等概率采样),之后可以考虑non-uniform采样
2. 模型是基于KG的item端进行建模,之后可以利用user端的信息
3. 考虑设计算法,结合user端和item端
#### **实践:**
##### **1.导入代码**
[GitHub - hwwang55/KGCN:知识图谱卷积网络的 tensorflow 实现]( )
1.下载项目并且导入pycharm中
2.在terminal中下载movielens的数据集
wget http://files.grouplens.org/datasets/movielens/ml-20m.zip
![](https://img-blog.csdnimg.cn/4b31ea8b51004c6da75d0f0646e86159.png)
$ wget http://files.grouplens.org/datasets/movielens/ml-20m.zip
$ unzip ml-20m.zip
$ mv ml-20m/ratings.csv data/movie/
其中出现的下载包,解压 压缩包命令没有成功,所以我手动操作的。(1.下载ml-20m的压缩包 2.解压此压缩包 3.将压缩包中的ratings.csv文件放在data/movie/下)
![](https://img-blog.csdnimg.cn/ccad16ecb88d41389f4d3484a5ad92ec.png)
##### **2.运行结果**
![](https://img-blog.csdnimg.cn/752623e4308744b5992b8a4a9f2a62e4.png)
![](https://img-blog.csdnimg.cn/1043321039064ee2988cde3517bec0fb.png)
点击率(CTR)
音乐集
![](https://img-blog.csdnimg.cn/6bf851f366464f96afe4195c50fa91ca.png)
##### 3.解读整个项目
###### 3.1 从preprocess.py开始
python preprocess.py -d movie
python代码输入参数参考:[Python 讲堂 parse\_args()详解\_parser.parse\_args-CSDN博客]( )详解_parser.parse_args-CSDN博客")
import argparse
import numpy as np
RATING_FILE_NAME = dict({‘movie’: ‘ratings.csv’, ‘book’: ‘BX-Book-Ratings.csv’, ‘music’: ‘user_artists.dat’})
SEP = dict({‘movie’: ‘,’, ‘book’: ‘;’, ‘music’: ‘\t’})
THRESHOLD = dict({‘movie’: 4, ‘book’: 0, ‘music’: 0})
‘’’
ratings_final.txt:user的序号,movie的序号,是否有关联
kg_final.txt:
‘’’
#将项目索引读取到实体 ID 文件:…/数据/音乐/item_index2entity_id.txt
#item是entity,但是entity不一定是item
#读取的文件的部分数据如下
2 0
3 1
4 2
6 3
#输出为:item_index_old2new[2]=0,item_index_old2new[3]=1,item_index_old2new[4]=2,item_index_old2new[6]=3,
#entity_id2index[0]=0,entity_id2index[1]=1,entity_id2index[2]=2,entity_id2index[3]=3
def read_item_index_to_entity_id_file():
file = ‘…/data/’ + DATASET + ‘/item_index2entity_id.txt’
print(‘reading item index to entity id file: ’ + file + ’ …’)
i = 0
for line in open(file, encoding=‘utf-8’).readlines():
item_index = line.strip().split(‘\t’)[0]#电影id
satori_id = line.strip().split(‘\t’)[1]#对应的序号 实体的序号,此项目自己排序的
item_index_old2new[item_index] = i #将item的序列号更新为实体的序号,等于将行号-1赋值了。
entity_id2index[satori_id] = i
i += 1
#转换评级
def convert_rating():
file = ‘…/data/’ + DATASET + ‘/’ + RATING_FILE_NAME[DATASET]
#D:\PyCharmProjects\KGCN-master\KGCN-master\data\music\user_artists.dat
# userID artistID weight
# 2 51 13883
# 2 52 11690
# 2 53 11351
# 2 54 10300
print(‘reading rating file …’)
#set() 函数创建一个无序不重复元素集,可进行关系测试,删除重复数据,还可以计算交集、差集、并集等。
item_set = set(item_index_old2new.values())#所有新的item的id的set 这里set里面存的是item实体对应的序号了0,1,2,3
user_pos_ratings = dict()#用户-项目 大于阈值的正样本
user_neg_ratings = dict()#用户-项目 小于阈值的负样本
for line in open(file, encoding='utf-8').readlines()[1:]:#跳过表头
array = line.strip().split(SEP[DATASET])#strip( ) 是行首尾处理函数,'\t'为分隔符
# remove prefix and suffix quotation marks for BX dataset
if DATASET == 'book':
array = list(map(lambda x: x[1:-1], array))
item_index_old = array[1]#movie数据集里面的item就是movie 作者挑选一部分数据使用
#上一步在music里面item_index_old=artistID(51,52,53,54)艺术家的id
if item_index_old not in item_index_old2new: # 判断item_index_old2new里面有没有item_index_old这个键
continue#作者挑选一部分数据使用 忽视这个artistID
item_index = item_index_old2new[item_index_old]#给item重新赋值id 在itemId entityId 52 20 item_index= item_index_old2new[52]=20
#item_index=20代表这是entity的Id
user_index_old = int(array[0])#在ratings.csv中的原本userid
#user_index_old在原本的userId
rating = float(array[2])
if rating >= THRESHOLD[DATASET]:#THRESHOLD[music]=0
if user_index_old not in user_pos_ratings:
user_pos_ratings[user_index_old] = set()
user_pos_ratings[user_index_old].add(item_index)#user_pos_ratings[2] 20,这里一个userId对应user喜欢的所有的物品的entityId
else:
if user_index_old not in user_neg_ratings:
user_neg_ratings[user_index_old] = set()
user_neg_ratings[user_index_old].add(item_index)#userId不喜欢的所有entityId
print('converting rating file ...')
writer = open('../data/' + DATASET + '/ratings_final.txt', 'w', encoding='utf-8')
# ../data/music/ratings_final.txt
user_cnt = 0
user_index_old2new = dict()
for user_index_old, pos_item_set in user_pos_ratings.items():
if user_index_old not in user_index_old2new:#把旧的userid变为新的userid
user_index_old2new[user_index_old] = user_cnt
user_cnt += 1
user_index = user_index_old2new[user_index_old]
for item in pos_item_set:#user和item的关系初始化为1
writer.write('%d\t%d\t1\n' % (user_index, item)) #userId entityId 1 对喜欢的物品给的是1
unwatched_set = item_set - pos_item_set #此userId的用户不喜欢的item的集合
if user_index_old in user_neg_ratings:
unwatched_set -= user_neg_ratings[user_index_old]#把正样本和负样本的rating都去掉,留下一些和user没关系的rating
for item in np.random.choice(list(unwatched_set), size=len(pos_item_set), replace=False):
writer.write('%d\t%d\t0\n' % (user_index, item)) #userId entityId 0 对没有关系的物品给的是0
writer.close()
print('number of users: %d' % user_cnt)
print('number of items: %d' % len(item_set))
#注意这里没有处理user不喜欢的物品
#转换 KG 文件
def convert_kg():
print(‘converting kg file …’)
entity_cnt = len(entity_id2index)
relation_cnt = 0
writer = open(‘…/data/’ + DATASET + ‘/kg_final.txt’, ‘w’, encoding=‘utf-8’)
#…/data/music/kg_final.txt
for line in open(‘…/data/’ + DATASET + ‘/kg.txt’, encoding=‘utf-8’):
# 2086 music.artist.origin 3846
# 1601 film.person_or_entity_appearing_in_film.film 3847
# 3355 film.actor.film 3848
array = line.strip().split(‘\t’)
head_old = array[0]
relation_old = array[1]
tail_old = array[2]
if head_old not in entity_id2index:#如果实体不在,就另外赋值id
entity_id2index[head_old] = entity_cnt
entity_cnt += 1
head = entity_id2index[head_old]
if tail_old not in entity_id2index:
entity_id2index[tail_old] = entity_cnt
entity_cnt += 1
tail = entity_id2index[tail_old]
if relation_old not in relation_id2index:
relation_id2index[relation_old] = relation_cnt
relation_cnt += 1
relation = relation_id2index[relation_old]
# print("entity_cnt=" + str(entity_cnt))
# print("relation_cnt=" + str(relation_cnt))
writer.write('%d\t%d\t%d\n' % (head, relation, tail))
writer.close()
print('number of entities (containing items): %d' % entity_cnt)
print('number of relations: %d' % relation_cnt)
#这个函数就是将原本的/kg.txt写入/kg_final.txt,如果实体没在原本的实体集合里面增加
if name == ‘main’:
#每次调用都seed()一下,表示种子相同,从而生成的随机数相同。随机数组相同
np.random.seed(555)
#ArgumentParser 对象包含将命令行解析成 Python 数据类型所需的全部信息
js基础
1)对js的理解?
2)请说出以下代码输出的值?
3)把以下代码,改写成依次输出0-9
4)如何区分数组对象,普通对象,函数对象
5)面向对象、面向过程
6)面向对象的三大基本特性
7)XML和JSON的区别?
8)Web Worker 和webSocket?
9)Javascript垃圾回收方法?
10)new操作符具体干了什么呢?
11)js延迟加载的方式有哪些?
12)WEB应用从服务器主动推送Data到客户端有那些方式?
t)
print(‘number of relations: %d’ % relation_cnt)
#这个函数就是将原本的/kg.txt写入/kg_final.txt,如果实体没在原本的实体集合里面增加
if name == ‘main’:
#每次调用都seed()一下,表示种子相同,从而生成的随机数相同。随机数组相同
np.random.seed(555)
#ArgumentParser 对象包含将命令行解析成 Python 数据类型所需的全部信息
js基础
1)对js的理解?
2)请说出以下代码输出的值?
3)把以下代码,改写成依次输出0-9
4)如何区分数组对象,普通对象,函数对象
5)面向对象、面向过程
6)面向对象的三大基本特性
7)XML和JSON的区别?
8)Web Worker 和webSocket?
9)Javascript垃圾回收方法?
10)new操作符具体干了什么呢?
11)js延迟加载的方式有哪些?
12)WEB应用从服务器主动推送Data到客户端有那些方式?
[外链图片转存中…(img-UThtKOQU-1714641247504)]
[外链图片转存中…(img-UEGTY6aB-1714641247506)]