SAIL: Self-Augmented Graph Contrastive Learning

https://arxiv.org/pdf/2009.00934

SAIL: Self-Augmented Graph Contrastive Learning,2022,AAAI

总结:作者提出了一种自增强GCL方法SAIL,和普通GCL方法相比,SAIL没有使用任何增强技术,而是将节点原始输入特征和GNNs学习到的节点表示看作两个视角进行对比。再此基础上,作者认为模型还存在问题,这里正负样本对的选取是通过edge connectivity来进行的,可能无法代表整个节点表示分布的全貌,并且可能导致模型偏向于链路预测任务(在其他pretext task,比如节点分类中表现一般)。为了解决这个问题,作者提出了一种self-distilling方法,包含intra-和inter-distilling两个模块。intra-distilling可以保证学习到的节点表示和原始输入特征具有相同的分布。inter-distilliing可以让浅层GNNs模拟出深层GNNs的效果,并且不存在过平滑问题。

整体来说,文章还可以,实验比较丰富,实验结果也挺可观的。不过个人感觉,SAIL中的对比策略和知识蒸馏组合在一起有点A+B的意思,结构不是那么连贯,故事不够完整。

阅读更多...

Prototypical Graph Contrastive Learning

https://arxiv.org/pdf/2106.09645

https://github.com/ha-lins/pgcl

Prototypical Graph Contrastive Learning,2022,TNNLS

总结: 文章要解决的一个核心问题就是:GCL负样本采样阶段存在的“sampling bias”问题,即可能选取到的“false negative sample”(即和目标query具有相同语义的负样本)。现有的GCL方法,对于负样本的选取基本都是均匀采样,不考虑负样本和锚点之间的相似度。作者在PGCL中首先对样本进行聚类,计算每个类别的原型向量,然后将和锚点处于不同簇的其他样本视作正负样本,处于相同簇的样本视为假负样本。另外,作者根据样本所在簇的原型和锚点所在簇原型之间距离计算权重用于对比损失的定义。感觉目前学术界对于GCL的研究,基本都是将CV和NLP中对比学习方法拓展到图邻域,可以多多关注CV中对比学习的最新进展。2021ICLR中有一篇名为“ PROTOTYPICAL CONTRASTIVE LEARNING OF UNSUPERVISED REPRESENTATIONS”的CV论文,我没有看着篇文章,不知道和本文是否有联系。2021ICLR还有一篇“ CONTRASTIVE LEARNING WITH HARD NEGATIVE SAMPLES ”的论文,和本文负样本采样思想差不多。因此,总的来看作者可能还是将CV中的方法迁移到图学习中。

阅读更多...

行为型——责任链模式

概念

定义: 责任链模式是一种行为型设计模式,允许我们将请求沿着处理者链进行发送。收到请求后,每个处理者均可对请求进行处理,或将其传递给链上的下个处理者。

特点: 在责任链模式中,客户只需要将请求发送到责任链上即可,无需关心请求的处理细节和请求的传递过程,请求会自动进行传递。因此,责任链将请求的发送者和请求的处理者解耦了。

优点:

  • 降低对象之间的耦合度。
  • 增强系统的可扩展性。可以根据需求增加新的请求处理类,满足开闭原则
  • 增强给对象指派职责的灵活性。当工作流程发生变化,可以动态地改变链内的成员或者调整顺序,也可以动态地新增或删除责任。
  • 简化对象之间的连接。每个对象只需保持一个指向其后继者的引用,不需要保持其他所有处理者的引用,避免使用众多的if…else…
  • 责任分担。每个类只处理自己该处理的工作,不处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。

缺点:

  • 不能保证每个请求一定被处理。 由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理。
  • 对比较长的职责链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。
  • 职责链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于职责链的错误设置而导致系统出错,如可能会造成循环调用。

应用场景: 1、有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。 2、在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。 3、可动态指定一组对象处理请求

实现

结构

责任链模式具有三个角色:

  • 抽象处理者:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。
  • 具体处理者: 实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。
  • 客户类: 创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。

其类图如下:

示例

下面基于责任链模式实现一个简单的日志记录类,用于记录不同类型的日志。

我们创建抽象类 AbstractLogger,带有详细的日志记录级别。然后我们创建三种类型的记录器,都扩展了 AbstractLogger。每个记录器消息的级别是否属于自己的级别,如果是则相应地打印出来,否则将不打印并把消息传给下一个记录器。

步骤 1

创建抽象的记录器类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public abstract class AbstractLogger {
public static int INFO = 1;
public static int DEBUG = 2;
public static int ERROR = 3;

protected int level;

//责任链中的下一个元素
protected AbstractLogger nextLogger;

public void setNextLogger(AbstractLogger nextLogger){
this.nextLogger = nextLogger;
}

public void logMessage(int level, String message){
if(this.level <= level){
write(message);
}
if(nextLogger !=null){
nextLogger.logMessage(level, message);
}
}

abstract protected void write(String message);

}

步骤 2

创建扩展了该记录器类的实体类。

1
2
3
4
5
6
7
8
9
10
11
public class ConsoleLogger extends AbstractLogger {

public ConsoleLogger(int level){
this.level = level;
}

@Override
protected void write(String message) {
System.out.println("Standard Console::Logger: " + message);
}
}
1
2
3
4
5
6
7
8
9
10
11
public class ErrorLogger extends AbstractLogger {

public ErrorLogger(int level){
this.level = level;
}

@Override
protected void write(String message) {
System.out.println("Error Console::Logger: " + message);
}
}
1
2
3
4
5
6
7
8
9
10
11
public class FileLogger extends AbstractLogger {

public FileLogger(int level){
this.level = level;
}

@Override
protected void write(String message) {
System.out.println("File::Logger: " + message);
}
}

步骤 3

创建不同类型的记录器。赋予它们不同的错误级别,并在每个记录器中设置下一个记录器。每个记录器中的下一个记录器代表的是链的一部分。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class ChainPatternDemo {

private static AbstractLogger getChainOfLoggers(){

AbstractLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR);
AbstractLogger fileLogger = new FileLogger(AbstractLogger.DEBUG);
AbstractLogger consoleLogger = new ConsoleLogger(AbstractLogger.INFO);

errorLogger.setNextLogger(fileLogger);
fileLogger.setNextLogger(consoleLogger);

return errorLogger;
}

public static void main(String[] args) {
AbstractLogger loggerChain = getChainOfLoggers();

loggerChain.logMessage(AbstractLogger.INFO, "This is an information.");

loggerChain.logMessage(AbstractLogger.DEBUG,
"This is a debug level information.");

loggerChain.logMessage(AbstractLogger.ERROR,
"This is an error information.");
}
}

步骤 4

执行程序,输出结果:

1
2
3
4
5
6
Standard Console::Logger: This is an information.
File::Logger: This is a debug level information.
Standard Console::Logger: This is a debug level information.
Error Console::Logger: This is an error information.
File::Logger: This is an error information.
Standard Console::Logger: This is an error information.

应用

应用场景

  1. 当程序需要使用不同方式处理不同种类请求, 而且请求类型和顺序预先未知时, 可以使用责任链模式。

    该模式能将多个处理者连接成一条链。 接收到请求后, 它会 “询问” 每个处理者是否能够对其进行处理。 这样所有处理者都有机会来处理请求。

  2. 当必须按顺序执行多个处理者时, 可以使用该模式。

    无论你以何种顺序将处理者连接成一条链, 所有请求都会严格按照顺序通过链上的处理者。

  3. 如果所需处理者及其顺序必须在运行时进行改变, 可以使用责任链模式。

    如果在处理者类中有对引用成员变量的设定方法, 你将能动态地插入和移除处理者, 或者改变其顺序。

典型应用

  1. Tomcat中的Filter就是使用了责任链模式,创建一个Filter除了要在web.xml文件中做相应配置外,还需要实现javax.servlet.Filter接口。
  2. Netty 中的 PipelineChannelHandler 通过责任链设计模式来组织代码逻辑
  3. Spring Security 使用责任链模式,可以动态地添加或删除责任(处理 request 请求)
  4. Spring AOP 通过责任链模式来管理 Advisor
  5. Dubbo Filter 过滤器链也是用了责任链模式(链表),可以对方法调用做一些过滤处理,譬如超时(TimeoutFilter),异常(ExceptionFilter),Token(TokenFilter)等
  6. Mybatis 中的 Plugin 机制使用了责任链模式,配置各种官方或者自定义的 Plugin,与 Filter 类似,可以在执行 Sql 语句的时候做一些操作

参考资料

  1. https://segmentfault.com/a/1190000040450513

  2. https://www.runoob.com/design-pattern/chain-of-responsibility-pattern.html

  3. https://refactoringguru.cn/design-patterns/chain-of-responsibility

  4. https://juejin.cn/post/6844903702260629512

JVM调优

何时进行JVM调优

遇到以下情况,就需要考虑进行JVM调优了:

  • Heap内存(老年代)持续上涨达到设置的最大内存值;
  • Full GC 次数频繁;
  • GC 停顿时间过长(超过1秒);
  • 应用出现OutOfMemory 等内存异常;
  • 应用中有使用本地缓存且占用大量内存空间;
  • 系统吞吐量与响应性能不高或下降。
阅读更多...

Java静态绑定与动态绑定

文章转自这里

1、当子类和父类存在同一个方法,子类重写了父类的方法,程序在运行时调用方法是调用父类的方法还是子类的重写方法呢?
2、当一个类中存在方法名相同但参数不同(重载)的方法,程序在执行的时候该如何辨别区分使用哪个方法呢?
在Java中我们使用静态绑定(static binding)和动态绑定(Dynamic binding)来解决,那么什么是绑定?什么是静态绑定?什么又是动态绑定?有什么区别?

阅读更多...
  • Copyrights © 2021-2022 Yin Peng
  • 引擎: Hexo   |  主题:修改自 Ayer
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信