第八周.直播.Transformer in Graph


本文内容整理自深度之眼《GNN核心能力培养计划》
公式输入请参考: 在线Latex公式

注意力基础知识

这块是Transformer的基础,之前有写过很多,最主要就是《attention is all you need》,还有两篇之前写过的文章:
Seq2Seq几个要点
Transformer
老师推荐的地址:https://jalammar.github.io/illustrated-transformer/
这里就不重复了,列几个之前的问题,如果能答上来,那么说明你对Transformer结构了解非常好:
a. 自注意力与注意力的区别?
b. 为什么要进行残差连接?
c. 为什么要设置多头注意力 ?
d. 一个自注意力层计算的复杂度是多少,为什么?
e. 为什么要进行mask?
f. 位置嵌入除了文中的这种形式还有哪些?

论文带读

Do Transformers Really Perform Bad for Graph Representation?
本篇论文是刚刚出炉的预印版。这个文章的模型在斯坦福OGB Graph-level 预测任务上拿了第一名
配套代码在此:https://github.com/Microsoft/Graphormer

摘要

Transformer 的应用很好~!
The Transformer architecture has become a dominant choice in many domains, such as natural language processing and computer vision.

但是在GNN领域还没人搞起。
Yet, it has not achieved competitive performance on popular leaderboards of graph-level prediction compared to mainstream GNN variants.

点题+过渡句
Therefore, it remains a mystery how Transformers could perform well for graph representation learning.

总的来说,本文用标准的Transformer结构解决了啥问题
In this paper, we solve this mystery by presenting Graphormer, which is built upon the standard Transformer architecture, and could attain excellent results on a broad range of graph representation learning tasks, especially on the recent OGB Large-Scale Challenge.

详细说模型的特点
Our key insight to utilizing Transformer in the graph is the necessity of effectively encoding the structural information of a graph into the model. To this end, we propose several simple yet effective structural encoding methods to help Graphormer better model graph-structured data. Besides, we mathematically characterize the expressive power of Graphormer and exhibit that with our ways of encoding the structural information of graphs, many popular GNN variants could be covered as the special cases of Graphormer.

论文结构

1 Introduction
2 Preliminary
3 Graphormer
3.1 Structural Encodings in Graphormer
3.2 Implementation Details of Graphormer
3.3 How Powerful is Graphormer?
4 Experiments
4.1 OGB Large-Scale Challenge
4.2 Graph Representation
4.3 Ablation Studies
5 Related Work
5.1 Graph Transformer
5.2 Structural Encodings in GNNs
6 Conclusion
附录A Proofs
附录B Experiment Details
附录C More Experiments
附录D Discussion & Future Work

第一节是介绍,从Transformer的应用开始聊,然后回到本文的出发点,在GNN里面Transformer的研究未见,然后提出本文研究的内容:Graphormer,简要展开介绍后,点出两个类比Transformer结构Graphormer中两个创新点:Centrality Encoding和Spatial Encoding,具体在3.1里面介绍。
第二节主要是GNN和Transformer的数学表达的回顾,不展开。

在这里插入图片描述
原文图1描述了Graphormer结构,上面主要注意三个额外的表征是哪里加入的。
下面详细看3.1

3.1 Structural Encodings in Graphormer

3.1.1Centrality Encoding

这个其实对应Transformer里面的位置嵌入,序列之所以是序列,是因为它由顺序,因此里面元素的位置当然是有隐含有一些辅助表征的信息的,但是GNN中的图结构,邻居是没有顺序的,这里也不是采用DeepWalk那种随机游走思想来先生成序列,因此,这个文章考虑图特有的信息来替换位置嵌入:Centrality Encoding。这个玩意就是图结构里面的刻画节点中心性(Centrality)的最直接度量指标,简单说就是用节点的出入度来作为一个Encoding:
h i ( 0 ) = x i + z d e g − ( v i ) − + z d e g + ( v i ) + h_i^{(0)}=x_i+z^-_{deg^-(v_i)}+z^+_{deg^+(v_i)} hi(0)=xi+zdeg(vi)+zdeg+(vi)+
这里用可学习向量 z z z作为不同出入度的表征,如果是无向图,这可以把出入度合并为 d e g ( v i ) deg(v_i) deg(vi)
除了出入度之外,还有别的指标,具体可以看下Networkx的官方文档

3.1.2 Spatial Encoding

除了度的信息之外,这里还用了Spatial Encoding,其实就是用一个玩意来表示两个节点的距离:
ϕ ( v i , v j ) \phi(v_i,v_j) ϕ(vi,vj)
文章中的 ϕ \phi ϕ使用的是最短路径SPD(shortest path distances)算法,这个不明白的可以看下数据结构。然后用 ϕ \phi ϕ得到的距离对应到一个可学习的常量 b ϕ ( v i , v j ) b_{\phi(v_i,v_j)} bϕ(vi,vj)

目测这里估计还可以换别的方法进行改进,我也看了一下,这个思想在另外两个文章里面有提出来,不过这里用在了Transformer里面。下面两个文章都是Jure组的工作(就是斯坦福讲CS224W图神经网络算法的那位)
19年的PGNN:Position-aware Graph Neural Networks
20年的Distance Encoding – Design Provably More Powerful Graph Neural Networks for Structural Representation Learning

3.1.3 Edge Encoding in the Attention

原文提到边的表征是GNN中非常重要的组成部分(例如:化学分子中碳碳结构有特殊含义),Edge Encoding的方法现有两种:1、Edge特征关联到节点特征上;2、在图卷积的过程中汇聚的时候加入边的特征,并学习之。
上面两种方式存在一个问题:就在在传播过程中只会把边的特征传递给与之相连的节点,无法有效将边的信息扩展到整个图中。
本文的方法可以考虑图中任意两个节点 ( v i , v j ) (v_i,v_j) (vi,vj)的边的信息,就是考虑两个节点的最短路径(有多条就随机取一条)所经过的边: S P i j = { e 1 , e 2 , ⋯   , e N } SP_{ij}=\{e_1,e_2,\cdots,e_N\} SPij={e1,e2,,eN},把这些边拿出来做平均,得到两个节点的边表征,然后用于注意力计算:
c i j = 1 N ∑ n = 1 N x e n ( W n E ) T c_{ij}=\cfrac{1}{N}\sum_{n=1}^Nx_{e_n}(W_n^E)^T cij=N1n=1Nxen(WnE)T
其中 N N N是最短路径经过了多少条边, x e n x_{e_n} xen是最短路径中的第n条边的特征, W n E W_n^E WnE是该条边对应的权重

<think>我们正在讨论一个工具类的设计问题。用户之前询问了如何命名一个用于调用多个外部服务的工具类,现在他们想知道XML转换代码应该放在哪里:是放在现有的ServiceHelper中,还是创建一个新的工具类。 参考引用: [^1] 提到:公共方法应该放在最前面(第一屏),因为它们是消费者和提供者最关心的。受保护的方法只被子类关心,私有方法对客户端不重要。Getter/setter方法应该放在类的最后。 [^2] 提到:推荐使用"test".equals(object)而不是object.equals("test"),并且推荐使用java.util.Objects#equals工具类。 [^3] 提到:使用DateUtils时要注意线程安全。 但是,这些引用并不是直接关于XML转换代码应该放在哪里的。我们需要根据软件设计原则和最佳实践来回答。 分析: 1. 单一职责原则(SRP):一个类应该只有一个引起变化的原因。如果现有的ServiceHelper类已经负责调用外部服务,那么XML转换应该是一个独立的职责。 2. 高内聚低耦合:将相关的功能放在一起,减少类之间的依赖。XML转换功能应该属于数据转换的范畴,与调用服务可能不是直接相关。 因此,建议创建一个新的工具类来专门处理XML转换。理由如下: - 如果XML转换是独立的逻辑,那么它应该被封装在自己的类中,这样更易于维护和测试。 - 如果将来需要支持其他数据格式(如JSON),那么可以扩展这个转换工具类,而不会影响服务调用的代码。 但是,如果XML转换与特定的服务调用紧密相关(例如,该转换只用于某个特定服务的响应),那么也可以考虑将其作为ServiceHelper的一个私有方法(如果只有这个类使用)或者一个公共方法(如果其他类也需要使用)。但是,根据引用[^1],公共方法应该是重要的,而XML转换可能是一个实现细节,不应该作为公共API暴露。 因此,更合理的方式是: 1. 创建一个新的工具类,例如:`XmlConversionUtils` 或 `XmlParser`,专门处理XML的解析和转换。 2. 在ServiceHelper中调用这个工具类的方法来完成转换。 这样,两个类各自负责单一职责,符合设计原则。 另外,引用[^2]提到了工具类(java.util.Objects)的使用,这支持了创建专用工具类的做法。 引用[^3]提醒我们注意工具类的线程安全,所以新的XML转换工具类应该设计为线程安全的(无状态或使用同步机制)。 总结建议: 创建一个新的工具类来处理XML转换,并在ServiceHelper中使用它。 示例代码结构: ```java // 新的XML转换工具类 public final class XmlParser { private XmlParser() {} // 防止实例化 // 线程安全的静态方法 public static SomeObject parse(String xml) { // 解析逻辑 } public static String toXml(SomeObject obj) { // 转换逻辑 } } // 在ServiceHelper中使用 public class ServiceHelper { public SomeObject callServiceAndParseResponse() { // 调用服务获取XML响应 String xmlResponse = ...; return XmlParser.parse(xmlResponse); } } ``` 这样,如果将来需要修改XML解析逻辑,只需要修改XmlParser类,而不会影响ServiceHelper。同时,XmlParser也可以被其他类复用。 相关问题: 1. 如何设计线程安全的工具类? 2. XML解析工具类应该使用哪种解析库(如DOM, SAX, StAX)? 3. 如何处理XML解析过程中的异常? 4. 如何为工具类编写单元测试?</think>### 建议方案:创建独立 XML 转换工具类 根据软件设计原则和引用内容,我建议**创建新的专用工具类**来处理 XML 转换,而非放入 `ServiceHelper` 中。理由如下: #### 1. **符合单一职责原则** [^1] > "public methods should be put on the first screen... Getter/setter methods should be put at the end" - `ServiceHelper` 的核心职责是协调外部服务调用(如 HTTP 请求、错误处理) - XML 转换属于**数据格式处理**的独立职责 - 混合职责会导致: - 类膨胀(公共方法过多,违反引用[1]的可见性建议) - 维护困难(修改 XML 逻辑可能意外影响服务调用) #### 2. **复用性与内聚性** ```java // ✅ 推荐方案:专用工具类 public final class XmlConverter { // 禁止继承 private XmlConverter() {} // 防止实例化 // 高内聚的公共方法 public static Object parse(String xml) { ... } public static String serialize(Object data) { ... } } // ❌ 不推荐:污染 ServiceHelper public class ServiceHelper { // 无关的服务调用方法... public void callService() { ... } // 低内聚的转换方法(破坏类结构) public static Object parseXml(String xml) { ... } } ``` #### 3. **线程安全与稳定性** [^3] XML 解析常涉及: - 非线程安全的解析器(如 DOM) - 资源密集型操作 独立工具类更容易实现: ```java public class XmlConverter { // 使用 ThreadLocal 保证线程安全 private static final ThreadLocal<Parser> parserPool = ...; } ``` #### 4. **符合项目规范** [^2] - 类似引用[2]推荐的 `java.util.Objects#equals` - 统一工具类命名风格(如 `XxxUtils`/`XxxConverter`) ### 实施建议 1. **类命名**(选其一): - `XmlConversionUtils`(通用转换) - `ServiceResponseParser`(强调服务响应场景) - `XmlDataAdapter`(体现格式适配) 2. **方法设计**: ```java public class XmlConversionUtils { // 核心公共方法放顶部 [^1] public static ServiceData parseServiceResponse(String xml) { ... } // 内部辅助方法私有化 private static Document validateXml(String xml) { ... } } ``` 3. **在 ServiceHelper 中调用**: ```java public class ServiceHelper { public ServiceData fetchData() { String rawXml = callExternalService(); return XmlConversionUtils.parseServiceResponse(rawXml); // 委托转换 } } ``` ### 决策流程图 ```mermaid graph TD A[新功能:XML转换] --> B{是否与核心职责直接耦合?} B -->|是:仅用于当前服务| C[作为ServiceHelper的私有方法] B -->|否:通用/复用需求| D[创建独立工具类] C --> E[需验证是否导致类膨胀] D --> F[命名符合工具类规范] ``` > **最终结论**:创建 `XmlConversionUtils` 或类似专用工具类,通过组合方式在 `ServiceHelper` 中调用。这符合引用[1]的类结构设计原则,同时满足引用[2][3]的线程安全与工具类最佳实践[^1][^2][^3]。 --- ### 相关问题 1. 如何设计线程安全的 XML 解析工具类? 2. 工具类中的静态方法与非静态方法如何选择? 3. 如何处理 XML 转换中的异常传播机制? 4. 服务层与工具类的职责边界如何界定?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

oldmao_2000

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值