概述
K最近邻(kNN, k-NearestNeighbor)算法,也称最近邻算法,是一种根据目标节点的k个最近(最相似)节点的分类对目标节点进行分类的技术。kNN由T.M. Cover和P.E. Hart于1967年提出,此后成为最广泛使用的分类算法之一:
- T.M. Cover, P.E. Hart, Nearest Neighbor Pattern Classification (1967)
尽管名称中包含单词“邻居”,但 kNN 在计算相似性时并不明确考虑节点之间的边,它只关注节点的属性。
基本概念
相似度指标
嬴图的kNN算法计算目标节点与图中所有其他节点之间的余弦相似度,然后选择与目标节点相似度最高的k个节点。
选举分类
用节点的某个属性作为分类标签。找到与目标节点最近的k个节点后,将k个节点中出现次数最多的标签分配给目标节点。
如果出现次数最多的标签有多个,则选取其中相似度相最高的节点的标签。
语法
- 命令:
algo(knn)
- 参数:
名称 |
类型 |
规范 |
默认 |
可选 |
描述 |
---|---|---|---|---|---|
node_id | _uuid |
/ | / | 否 | 目标节点的UUID |
node_schema_property | []@<schema>?.<property> |
数值类型,需LTE,需与目标节点的Schema一致 | / | 否 | 用于计算余弦相似度的两个或两个以上点属性 |
top_k | int | >0 | / | 否 | 选取最相似节点的个数 |
target_schema_property | @<schema>?.<property> |
数值/字符串类型,需LTE,需与目标节点的Schema一致 | / | 否 | 作为分类标签的点属性 |
示例
示例图包含6个图片节点(忽略边),每个节点有d1、d2、d3、d4和type属性:
文件回写
配置项 |
回写内容 |
描述 |
---|---|---|
filename | 第一行:attribute_value 第二行开始: _id ,similarity |
第一行:选拔出的分类标签 第二行开始:选出的每个相似节点的ID及其与目标节点间的余弦相似度 |
algo(knn).params({
node_id: 1,
node_schema_property: ['d1', 'd2', 'd3', 'd4'],
top_k: 4,
target_schema_property: @image.type
}).write({
file:{
filename: "knn"
}
})
结果:文件knn
Gold
top k : image4,0.538975
image3,0.705072
image6,0.841922
image2,0.85516
直接返回
别名序号 |
类型 |
描述 | 列名 |
---|---|---|---|
0 | KV | 选拔出的分类标签及其在K个最近邻中出现的次数 | attribute_value , count |
1 | []perNode | 选出的最近邻及与目标节点的余弦相似度 | node , similarity |
algo(knn).params({
node_id: 1,
node_schema_property: ['d1', 'd2', 'd3', 'd4'],
top_k: 4,
target_schema_property: @image.type
}) as a1, a2
return a1, a2
结果:a1和a2
attribute_value | count |
---|---|
Gold | 2 |
node | similarity |
---|---|
4 | 0.538974677919475 |
3 | 0.705071517140301 |
6 | 0.841922130134788 |
2 | 0.855159652306166 |
流式返回
别名序号 |
类型 |
描述 | 列名 |
---|---|---|---|
0 | KV | 选拔出的分类标签及其在K个最近邻中出现的次数 | attribute_value , count |
algo(knn).params({
node_id: 2,
node_schema_property: ['@image.d1', '@image.d2', '@image.d3', '@image.d4'],
top_k: 5,
target_schema_property: @image.type
}).stream() as label
find().nodes({_uuid == 2}) as target
return case
when target.type == label.attribute_value then 'True'
else 'false'
end
结果:false
find().nodes({@image}) as images
call {
with images._uuid as target
algo(knn).params({
node_id: target,
node_schema_property: ['d1', 'd2', 'd3', 'd4'],
top_k: 3,
target_schema_property: 'type'
}).stream() as label
return label
}
return table(images._id, label.attribute_value)
结果:table(images._id, label.attribute_value)
images._id | label.attribute_value |
---|---|
image1 | Silver |
image2 | Silver |
image3 | Gold |
image4 | Silver |
image5 | Gold |
image6 | Gold |