标签传递算法:java版

2023-11-08

标签传递算法:java版


原文:smly/java-labelpropagation: java implementation of labelpropagation

java-labelpropagation

Java implementation of GFHF ([Zhu and Ghahramani, 2002]).

Iterate
1. \hat{Y}^{(t+1)} \leftArrow D^{-1} W \hat{Y}^{(t)}
2. \hat{Y}^{(t+1)}_l \leftArrow Y_l
until convergence to \hat{Y}^{(\infty)}
Usage

  $ mvn compile
  $ mvn package
  $ cat data/sample.json
  [2, 1, [[1, 1.0], [3, 1.0]]]
  [3, 0, [[1, 1.0], [2, 1.0], [4, 1.0]]]
  [4, 0, [[3, 1.0], [5, 1.0], [8, 1.0]]]
  [5, 0, [[4, 1.0], [6, 1.0], [7, 1.0]]]
  [6, 2, [[5, 1.0], [7, 1.0]]]
  [7, 0, [[5, 1.0], [6, 1.0]]]
  [8, 0, [[4, 1.0], [9, 1.0]]]
  [9, 2, [[8, 1.0]]]
  $ java -classpath target/labelprop-1.0-SNAPSHOT-jar-with-dependencies.jar \
     org.ooxo.LProp \
     -a GFHF \
     -m 100 \
     -e 10e-5 \
     data/sample.json
  Number of vertices:            9
  Number of class labels:        2
  Number of unlabeled vertices:  6
  Numebr of labeled vertices:    3
  eps:                          1e-5
  max iteration:                100
  .............................
  iter = 29, eps = 9.918212890613898E-5
  [1,1,[1,0.8706],[2,0.1294]]
  [2,1,[1,1.0000],[2,0.0000]]
  [3,1,[1,0.7412],[2,0.2588]]
  [4,2,[1,0.3529],[2,0.6470]]
  [5,2,[1,0.1412],[2,0.8588]]
  [6,2,[1,0.0000],[2,1.0000]]
  [7,2,[1,0.0706],[2,0.9294]]
  [8,2,[1,0.1765],[2,0.8235]]
  [9,2,[1,0.0000],[2,1.0000]]

References

Chapelle O, Schölkopf B and Zien A: Semi-Supervised Learning, 508, MIT Press, Cambridge, MA, USA, (2006).
http://mitpress.mit.edu/catalog/item/default.asp?ttype=2&tid=11015

本地测试

E:\workspace\java\java-labelpropagation

git clone https://github.com/smly/java-labelpropagation.git
mvn clean package
java -classpath target/labelprop-1.0-SNAPSHOT-jar-with-dependencies.jar org.ooxo.LProp -a GFHF -m 100 -e 10e-5 data/sample.json

数据集

[vertexId, vertexLabel, edges[destVertexId, edgeWeight]]
如果vertexLabel == 0,则表示未打标签。destVertexId连接的另一个节点,edgeWeight边的权重。

[1, 0, [[2, 1.0], [3, 1.0]]]
[2, 1, [[1, 1.0], [3, 1.0]]]
[3, 0, [[1, 1.0], [2, 1.0], [4, 1.0]]]
[4, 0, [[3, 1.0], [5, 1.0], [8, 1.0]]]
[5, 0, [[4, 1.0], [6, 1.0], [7, 1.0]]]
[6, 2, [[5, 1.0], [7, 1.0]]]
[7, 0, [[5, 1.0], [6, 1.0]]]
[8, 0, [[4, 1.0], [9, 1.0]]]
[9, 2, [[8, 1.0]]]

LPAlgorithm

void processLine(String line) {
    try {
        // [vertexId, vertexLabel, edges]
        // unlabeled vertex if vertexLabel == 0
        // i.e. [2, 1, [[1, 1.0], [3, 1.0]]]
        JSONArray json = new JSONArray(line);
        Long vertexId = json.getLong(0);
        Long vertexLabel = json.getLong(1);
        JSONArray edges = json.getJSONArray(2);
        ArrayList<Edge> edgeArray = new ArrayList<Edge>();
        vertexLabelMap.put(vertexId, vertexLabel);
        for (int i = 0; i < edges.length(); ++i) {
            JSONArray edge = edges.getJSONArray(i);
            Long destVertexId = edge.getLong(0);
            Double edgeWeight = edge.getDouble(1);
            edgeArray.add(new Edge(vertexId, destVertexId, edgeWeight));
        }
        vertexAdjMap.put(vertexId, edgeArray);
    } catch (JSONException e) {
        throw new IllegalArgumentException(
                "Coundn't parse vertex from line: " + line, e);
    }
}

处理一行数据,将标签存到vertexLabelMap,将节点和边的情况存到vertexAdjMap

vertexLabelMap

[vertexId, vertexLabel]

vertexAdjMap

[vertexId, [vertexId, destVertexId, edgeWeight]]

loadJSON

vertexAdjMapvertexInAdjMap的区别在哪里?

掉头

//vertexAdjMap
1:[{"dest":2,"src":1,"weight":1},{"dest":3,"src":1,"weight":1}]
//vertexInAdjMap
1:[{"dest":1,"src":2,"weight":1},{"dest":1,"src":3,"weight":1}]
// initialize vertexInAdjMap
for (Long vertexId : vertexAdjMap.keySet()) {
    if (! vertexInAdjMap.containsKey(vertexId)) {
        vertexInAdjMap.put(vertexId, new ArrayList<Edge>());
    }
}
// setup vertexInAdjMap
for (Long vertexId : vertexAdjMap.keySet()) {
    for (Edge e : vertexAdjMap.get(vertexId)) {
        vertexInAdjMap.get(e.getDest()).add(e);
    }
}

根据每个节点的权重计算度vertexDegMap

// setup vertexDegMap
for (Long vertexId : vertexAdjMap.keySet()) {
    double degree = 0;
    if (vertexDegMap.containsKey(vertexId)) {
        degree = vertexDegMap.get(vertexId);
    }
    for (Edge e : vertexAdjMap.get(vertexId)) {
        degree += e.getWeight();
    }
    vertexDegMap.put(vertexId, degree);
}

vertexDegMap
{1=2.0, 2=2.0, 3=3.0, 4=3.0, 5=3.0, 6=2.0, 7=2.0, 8=2.0, 9=1.0}

标签

// setup vertexFMap
Set<Long> vSet = vertexLabelMap.keySet();
Iterator<Long> it = vSet.iterator();
Set<Long> lSet = new TreeSet<Long>();
while (it.hasNext()) {

    Long l = vertexLabelMap.get(it.next());
    lSet.add(l);
    vertexSize++;
}
Iterator<Long> lSetIter = lSet.iterator();
int labelEnum = 0;
while (lSetIter.hasNext()) {
    Long l = lSetIter.next();
    if (l.intValue() == 0) continue;
    labelIndexMap.put(l, new Long(labelEnum));
    labelEnum++;
}
labelSize = labelEnum;
it = vSet.iterator();
labeledSize = 0;
while (it.hasNext()) {
    Long v = it.next();
    ArrayList<Double> arr = new ArrayList<Double>(labelEnum);
    Long l = vertexLabelMap.get(v);
    if (l.intValue() == 0) {
        // unlabeled
        for (int i = 0; i < labelSize; ++i) {
            arr.add(0.0);
        }
    } else {
        // labeled
        labeledSize++;
        int ix = labelIndexMap.get(vertexLabelMap.get(v)).intValue();
        for (int i = 0; i < labelSize; ++i) {
            arr.add((i == ix) ? 1.0 : 0.0);
        }
    }
    vertexFMap.put(v, arr);
}

TreeSet

Java 集合系列17之 TreeSet详细介绍(源码解析)和使用示例 - 如果天空不死 - 博客园
java TreeSet的使用 - you_off3的专栏 - CSDN博客

Set<Long> lSet = new TreeSet<Long>();
TreeSet:它可以给Set集合中的元素进行指定方式的排序。保证元素唯一性的方式:通过比较的结果是否为0。底层数据结构是:二叉树。TreeSet是基于TreeMap实现的。TreeSet中的元素支持2种排序方式:自然排序 或者 根据创建TreeSet 时提供的 Comparator 进行排序。这取决于使用的构造方法。

构建vSetlSetlabelIndexMap

Set<Long> vSet = vertexLabelMap.keySet();
Iterator<Long> it = vSet.iterator();
Set<Long> lSet = new TreeSet<Long>();
while (it.hasNext()) {

    Long l = vertexLabelMap.get(it.next());
    lSet.add(l);
    vertexSize++;
}
Iterator<Long> lSetIter = lSet.iterator();
int labelEnum = 0;
while (lSetIter.hasNext()) {
    Long l = lSetIter.next();
    if (l.intValue() == 0) continue;
    labelIndexMap.put(l, new Long(labelEnum));
    labelEnum++;
}
labelSize = labelEnum;

vSet
[1, 2, 3, 4, 5, 6, 7, 8, 9]
lSet
[0, 1, 2]
labelIndexMap是对label进行编号,1=0表示标签1放在第0个位置上。
{1=0, 2=1}

构建vertexFMap

it = vSet.iterator();
labeledSize = 0;
while (it.hasNext()) {
    Long v = it.next();
    ArrayList<Double> arr = new ArrayList<Double>(labelEnum);
    Long l = vertexLabelMap.get(v);
    if (l.intValue() == 0) {
        // unlabeled
        for (int i = 0; i < labelSize; ++i) {
            arr.add(0.0);
        }
    } else {
        // labeled
        labeledSize++;
        int ix = labelIndexMap.get(vertexLabelMap.get(v)).intValue();
        for (int i = 0; i < labelSize; ++i) {
            arr.add((i == ix) ? 1.0 : 0.0);
        }
    }
    vertexFMap.put(v, arr);
}

vertexFMap
{1=[0.0, 0.0], 2=[1.0, 0.0], 3=[0.0, 0.0], 4=[0.0, 0.0], 5=[0.0, 0.0], 6=[0.0, 1.0], 7=[0.0, 0.0], 8=[0.0, 0.0], 9=[0.0, 1.0]}

showDetail

void showDetail() {
    System.out.println("Number of vertices:            " + vertexSize);
    System.out.println("Number of class labels:        " + labelSize);
    System.out.println("Number of unlabeled vertices:  " + (vertexSize - labeledSize));
    System.out.println("Numebr of labeled vertices:    " + labeledSize);
}

GFHF

iter

处理未标签的节点nextVertexFMap

// for all vertex
double diff = 0.0;
for (Long vertexId : vertexFMap.keySet()) {
    if (vertexLabelMap.get(vertexId) != 0) continue; // skip labeled
    // update F(vertexID) ... vetexFMap
    ArrayList<Double> nextFValue = new ArrayList<Double>();
    ArrayList<Double> fValues = vertexFMap.get(vertexId);
    for (int l = 0; l < labelSize; ++l) {
        // update f_l(vertexId)
        double fValue = 0.0;
        for (Edge e : vertexInAdjMap.get(vertexId)) {
            double w = e.getWeight();
            long src = e.getSrc();
            double deg = vertexDegMap.get(vertexId);
            fValue += vertexFMap.get(src).get(l) * (w / deg);
            System.out.println("(src,dst): " + src + "->" + vertexId + ", value = (" + fValue +"), deg = " + deg + ", label = " + l);
        }
        nextFValue.add(fValue);
        if (vertexLabelMap.get(vertexId) == 0) {
            diff += ((fValue > fValues.get(l)) ? fValue - fValues.get(l) : fValues.get(l) - fValue);
        }
    }
    //System.out.println(nextFValue);
    nextVertexFMap.put(vertexId, nextFValue);
    //System.out.println("----");
}

value的值

fValue += vertexFMap.get(src).get(l) * (w / deg);

(src,dst): 2->1, value = (0.5), deg = 2.0, label = 0
(src,dst): 3->1, value = (0.5), deg = 2.0, label = 0
(src,dst): 2->1, value = (0.0), deg = 2.0, label = 1
(src,dst): 3->1, value = (0.0), deg = 2.0, label = 1

结果nextVertexFMap

{1=[0.5, 0.0], 3=[0.3333333333333333, 0.0], 4=[0.0, 0.0], 5=[0.0, 0.3333333333333333], 7=[0.0, 0.5], 8=[0.0, 0.5]}

将已标签的节点回写到nextVertexFMap

// fix labeled vertex
for (Long vertexId : vertexLabelMap.keySet()) {
    if (vertexLabelMap.get(vertexId) == 0) continue; // 0 means unlabeled vertex
    nextVertexFMap.put(vertexId, vertexFMap.get(vertexId));
}

最后将nextVertexFMap赋值给vertexFMap

vertexFMap = nextVertexFMap;

nextVertexFMap
vertexFMap
{1=[0.5, 0.0], 2=[1.0, 0.0], 3=[0.3333333333333333, 0.0], 4=[0.0, 0.0], 5=[0.0, 0.3333333333333333], 6=[0.0, 1.0], 7=[0.0, 0.5], 8=[0.0, 0.5], 9=[0.0, 1.0]}

循环多次结果

vertexFMap
{1=[0.8705767912004067, 0.12939269122146832], 2=[1.0, 0.0], 3=[0.7411612117974713, 0.25880064122987234], 4=[0.3529182882869945, 0.6470206765567554], 5=[0.14116121180087424, 0.8588006412264694], 6=[0.0, 1.0], 7=[0.0705767912042349, 0.92939269121764], 8=[0.1764553294462316, 0.8235065235811121], 9=[0.0, 1.0]}

debug

void debug() {
    ArrayList<Long> labels = new ArrayList<Long>(labelSize);
    for (Long label : labelIndexMap.keySet()) {
        labels.add(labelIndexMap.get(label).intValue(), label);
    }
    for (Long vertexId : vertexFMap.keySet()){
        ArrayList<Double> arr = vertexFMap.get(vertexId);
        System.out.printf("[%d,", vertexId);
        ByteArrayOutputStream buff = new ByteArrayOutputStream();
        PrintStream ps = new PrintStream(buff);
        double maxFVal = 0.0;
        int maxFValIx = 0;
        for (int i = 0; i < labelSize; ++i) {
            double fval = arr.get(i);
            if (fval > maxFVal) {
                maxFVal = fval;
                maxFValIx = i;
            }
            ps.printf("[%d,%.04f]", labels.get(i), arr.get(i));
            ps.printf(i != labelSize - 1 ? "," : "]\n");
        }
        System.out.print(labels.get(maxFValIx) + "," + buff.toString());
    }
}

比较vertexFMap中的值。哪个大,则标标记为对应标签。

例如

1=[0.8705767912004067, 0.12939269122146832]

输出

[1,1,[1,0.8706],[2,0.1294]]

最终结果输出
[1,1,[1,0.8706],[2,0.1294]]
[2,1,[1,1.0000],[2,0.0000]]
[3,1,[1,0.7412],[2,0.2588]]
[4,2,[1,0.3529],[2,0.6470]]
[5,2,[1,0.1412],[2,0.8588]]
[6,2,[1,0.0000],[2,1.0000]]
[7,2,[1,0.0706],[2,0.9294]]
[8,2,[1,0.1765],[2,0.8235]]
[9,2,[1,0.0000],[2,1.0000]]

1,2,3标记为1
4,5,6,7,8,9标记为2

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

标签传递算法:java版 的相关文章

随机推荐

  • Mathematica 随机打乱列表顺序/列表随机重排列

    更新 找到相关函数了 没仔细看说明以为RandomSample只能随机取样来着 汗 RandomSample list 原内容 没必要看了 没有找到直接的相关函数 想到的方法是随机交换列表元素 例如以下程序为1 10的数字乱序 Permut
  • IP数据包长度问题总结

    首先要看TCP IP协议 涉及到四层 链路层 网络层 传输层 应用层 其中以太网 Ethernet 的数据帧在链路层 IP包在网络层 TCP或UDP包在传输层 TCP或UDP中的数据 Data 在应用层 它们的关系是 数据帧 IP包 TCP
  • TypeError: write() argument must be str, not bytes报错原因及Python3写入二进制文件方法

    Python2随机写入二进制文件 with open python2 random bin w as f f write os urandom 10 但使用Python3会报错 TypeError must be str not bytes
  • Java设计模式:深入解析与应用示例

    文章目录 引言 一 单例模式 二 工厂模式 三 抽象工厂模式 四 建造者模式 五 原型模式 六 适配器模式 七 装饰器模式 八 观察者模式 九 策略模式 十 命令模式 结语 引言 设计模式是一种在特定上下文中反复出现的可重用解决方案 用于处
  • Linux / ldd 命令的介绍与使用

    0 介绍 ldd 用来打印或者查看程序运行所需的共享库 访问共享对象依赖关系 常用来解决程序因缺少某个库文件而不能运行的一些问题 1 首先 ldd 不是一个可执行程序 而只是一个 shell 脚本 2 ldd 能够显示可执行模块的 depe
  • 学习笔记Flink(八)—— 基于Flink 在线交易反欺诈检测

    一 背景介绍 信用卡欺诈 信用卡欺诈是指故意使用伪造 作废的信用卡 冒用他人的信用卡骗取财物 或用本人信用卡进行恶意透支的行为 在当今数字时代 信用卡欺诈行为越来越被重视 罪犯可以通过诈骗或者入侵安全级别较低系统来盗窃信用卡卡号 用盗得的信
  • mipi和isp处理_ISP-摄像头的最强大脑- 图像质量及色彩科技知识分享平台 图像质量与色彩管理 - Powered by HDWiki!...

    做为拍照手机的核心模块之一 camera sensor效果的调整 涉及到众多的参数 如果对基本的光学原理及sensor软 硬件对图像处理的原理能有深入的理解和把握的话 对我们的工作将会起 到事半功倍的效果 否则 缺乏了理论的指导 只能是凭感
  • 【系统篇 / 文件】01. 文件服务安装与配置 ❀ Windows Server 2008 R2

    简介 文件服务提供帮助管理存储 启用文件复制 管理共享文件夹 确保快速搜索文件 以及启用对UNXI客户端计算机访问的技术 使用文件服务 组织可以将文件存储到中心位置 然后通过公司网络与用户共享 可以为这些共享文件创建索引 以帮助用户快速查找
  • K8S deployment可视化故障排查指南

    这是一个示意图 可帮助您调试Kubernetes中的deployemnt 当您希望在Kubernetes中部署应用程序时 通常定义三个组件 一个deployment 这是创建名为Pods的应用程序副本的秘诀 一个service 内部负载平衡
  • cocos creator 中读取Excel表格中的数据

    一 使用相应工具将Excel文件转化成JSON文件导入到cocos creator资源文件 二 在VS中对Excel文本中的数据进行转换 Excel文本中各项数据的名称对应代码中的data export default class Task
  • Apache-tomcat-8.5.82下载安装以及环境变量配置

    一 下载apache tomcat 8 5 82 1 进入apache官网 Apache Tomcat Welcome 选择Download gt Tomcat8 进入Apache Tomcat Apache Tomcat 8 Softwa
  • 分布式计算,泛在计算,BOINC

    BOINC平台简介 知乎 Download BOINC client software 开源源代码 https github com BOINC boinc 介绍 https www equn com wiki BOINC 使用指南 htt
  • 【Antdv】a-date-picker showTime带时间默认00:00:00

    show time 默认当前系统时间 设置默认 00 00 00
  • 预编码

    原则上说MIMO技术并不一定需要预编码 使用预编码的前提是发射端可以及时获取信道信息 也就是CSIT 在通常情况下 只有接收端可以知道信道信息CSIR 在这个情况下 接收端通过复杂的信号处理算法 如MMSE SIC 可以解调出多路的MIMO
  • Zookeeper 通知更新可靠吗? 解读源码找答案!

    欢迎大家前往腾讯云 社区 获取更多腾讯海量技术实践干货哦 本文由特鲁门发表于云 社区专栏 导读 遇到Keepper通知更新无法收到的问题 思考节点变更通知的可靠性 通过阅读源码解析了解到zk Watch的注册以及触发的机制 本地调试运行模拟
  • 软件架构及几种典型框架

    什么是软件架构 什么是软件框架 很多时候 我们常常会混用架构和框架这两个词 实际上 广义上的架构和框架在概念上有很大的不同 架构给人的感觉 包容上更大 所以实际上架构是包含了框架的概念的 广义的架构应为一个系统的架构 不仅仅涉及软件中的技巧
  • BOM编程

    1 BOM概述 BOM 浏览器对象模型 Browser Object Model 它提供了独立于内容的 可以与浏览器窗口进行互动的对象结构 通过BOM可以操作浏览器窗口 比如弹出框 控制浏览器跳转 获取分辨率等 BOM是把 浏览器 当做一个
  • 实操理解node_modules目录结构

    环境 2022 8 16 node v gt v16 15 1 npm v gt 8 11 0 yarn v gt 1 22 19 pnpm v gt 7 9 0 npm0 mkdir npm0 cd npm0 npm install el
  • 从源头理解Batch Normalization (顺带搞懂为什么做参数初始化)

    一 BN LN等一系列Normalization方法的动机 因为一个网络中某层的参数的梯度 最终是由训练样本中这层输入的各个feature的具体数值决定的 如果feature的数值变化范围过大 比如不同特征的含义就导致了取值范围不在一个数量
  • 标签传递算法:java版

    标签传递算法 java版 标签传递算法 java版 java labelpropagation 本地测试 数据集 LPAlgorithm loadJSON vertexAdjMap和vertexInAdjMap的区别在哪里 根据每个节点的权