【论文解读 ICLR 2020 | LambdaNet】Probabilistic Type Inference using Graph Neural Networks

提出LambdaNet框架,使用图神经网络(GNN)进行类型推断,尤其适用于Python或TypeScript等语言的代码类型注释。通过生成类型依赖图并利用GNN进行消息传递,该方法不仅能预测标准类型,还能处理训练中未出现的用户自定义类型。

论文题目:LambdaNet: Probabilistic Type Inference using Graph Neural Networks

论文来源:ICLR 2020

论文链接:https://openreview.net/forum?id=r1lZ7AEKvB

代码链接:https://github.com/MrVPlusOne/LambdaNet

关键词:GNN,谓词,代码类型注释,attention,超边,指针网络



1 摘要

本文使用图神经网络进行推理,具体的场景是在 Python 或者 Typescript 之类的语言中自动进行代码的类型注释

该方法首先使用轻量级的源代码分析生成一个程序抽象——类型依赖图。该图将类型变量和逻辑约束、名称以及使用信息联系在一起。给定这个图后,使用GNN在相关的类型变量间进行消息传播,最终进行类型的预测。

本文提出的方法可以预测标准的类型,例如number、string,也可以预测出训练中未出现过的用户自定义的类型。


2 引言

在过去的十年中,例如Python、Ruby、Javascript之类的动态类型语言获得了极大的普及,但它们缺乏静态类型系统,缺乏在编译时捕获错误的能力以及code completion的支持在可维护性方面存在一定的缺陷

Gradual typing可以解决这些不足:程序变量有可选的类型注释,这样类型系统就可以在需要的时候执行静态类型检查。有许多流行的编程语言可支持gradual typing,但由于它们大量使用动态语言结构并且缺乏主要的类型,编译器不能使用来自编程语言社区的标准算法进行类型推断。并且,手动向现有的代码库添加类型注释非常繁琐而且易出错。

为了减少从无类型的代码向静态类型代码过渡所涉及的人工工作,本文的工作使用基于学习的方法,自动地为无类型(或有部分类型)的代码库推断出可能的类型注释


已有方法的缺点

本文使用的是TypeScript,是Javascript的一种变形,该语言有大量的类型注释的程序作为训练数据。已经有一些使用机器学习为TypeScript推断类型标注的方法,但这些方法都有一些缺点:

(1)推断的结果来源于有限的类型词典,即推断的类型都是在训练过程中出现过的,不能推断出用户定义的数据类型

(2)即使不考虑用户定义的类型,这些方法的准确率也不高

(3)这些方法可能会产生不一致的结果,对于相同的变量可能因为出现位置的不同,导致预测出来的类型不同。


作者提出

使用GNN对TypeScript进行类型推断,避免了上述问题。

本文的方法先使用轻量级的源代码分析将程序转换成类型依赖图。图由节点和有标签的超边(hyperedges)组成,图中的节点代表类型变量节点间的关系编码在了超边里。类型依赖图中除了表达了逻辑约束之外,还结合了设计命名和变量使用的上下文提示

给定类型依赖图后,使用GNN为每种类型变量计算出一个向量表示,然后使用类似指针网络的结构进行类型预测。

GNN本身需要处理各种类型的超边(有些具有可变数量的参数),为此作者定义了恰当的图传播操作

预测层比较了类型变量的向量表示候选类型的向量表示,从而可以灵活地处理在训练阶段未出现过的用户定义的类型

另外,模型的预测结果具有一致性,因为模型进行的是变量级别的预测,而不是位置级别的预测


贡献

(1)提出了一个TypeScript的概率类型推断算法)(LambdaNet),使用了深度学习的方法,根据程序对应的类型依赖图的表示进行预测。

(2)使用GNN方法进行了类型变量的向量表示的计算,并且提出类似指针网络的方法对用户定义的类型进行预测。

(3)实验证明了LambdaNet的有效性以及和之前的方法相比的优越性


3 动机举例和问题设置

在这里插入图片描述

图1展示了一个(type-annotated)TypeScript程序,本文工作的目的是给定未标注版本的代码,推断出图中所展示的类型。接下来以图1为例,来解释本文方法的各个方面。

1、类型限制(Typing constraints)

图1中的某些函数/操作符对可以被分配给程序变量的类型施加了强约束。例如,forward函数中的 x , y x, y x,y的类型必须能支持concat操作,因此 x , y x, y x,y的类型可以是string, array, Tensor,但不能是boolean。这启发了作者,将类型限制添加到了模型中。

2、上下文提示(Contextual hints)

只使用类型限制并不能确定变量的类型,例如对于restore函数中的network变量,在类型限制的条件下,需要network的类型是有time的类,但是有许多类都有这样的属性(例如 Date)。然而,变量名称network和类名MyNetwork间的相似度提示了network可能有类型MyNetwork。基于这一点,我们可以进一步传播库函数readNumber返回的类型(假定我们知道类型是number),进而推断出MyNetworktime的类型有可能是number

3、类型依赖图的需要

有很多种展示程序的方式,例如token序列、抽象语义树、控制流图等等。然而这些表示方法都不利于推断出最可能的类型注释。因此本文使用静态分析的方法来推断一组与类型推断问题相关的谓词,并使用程序抽象的方式(类型依赖图)来表示这些谓词。

4、处理用户定义的类型

先前的方法的预测结果只能是训练中出现过的类型。如图1所示,MyNetwork是自定义的类型,并且restore方法中使用了这一类型的变量。一个成功的模型应该能基于用户定义类型的定义动态地进行推断。


3.1 问题设置

本文的目标是训练出一个类型推断模型,将完全或部分未注释TypeScript程序 g g g作为输入,为每个缺失的注释预测出类型的概率分布。

预测空间为 Y ( g ) = Y l i b ∪ Y u s e r ( g ) \mathcal{Y}(g)=\mathcal{Y}_{lib}\cup \mathcal{Y}_{user}(g) Y(g)=YlibYuser(g),其中 Y u s e r ( g ) \mathcal{Y}_{user}(g) Yuser(g)为用 g g g声明的所有用户定义类型的集合(类/接口), Y l i b \mathcal{Y}_{lib} Ylib是通常使用的固定的库类型集合。

预测范围限定在非多态(non-polymorphic)和非函数(non-function)的类型。也就是说,不区别“ L i s t < T > , L i s t < n u m b e r > , L i s t < s t r i n g > List<T>, List<number>, List<string> List<T>,List<number>,List<string>”,把它们都看成是List类型。类似地,作者还将例如number → \rightarrow string、string → \rightarrow string这样的函数类型转换成为Function的单个类型。并将预测结构化的类型作为未来的研究工作。


4 类型依赖图

在这里插入图片描述

类型依赖图 G = ( N , E ) \mathcal{G}=(N,E) G=(N,E)是一个超图,图中的节点 N N N代表类型变量,超边 E E E编码了节点之间的关系信息。通过对TypeScript程序源代码的中间表示形式进行静态分析,提取出给定程序的类型依赖图,这使得我们将唯一的变量与每个程序子表达式关联起来。图2展示了图1代码的中间表示。

在这里插入图片描述

类型依赖图编码了类型变量的属性和它们之间的关系每一个超边都对应表1中的一个谓词。将这些谓词分为LogicalContextual两类,第一类可看成对类型变量施加了强约束,第二类编码了从变量名、函数名和类名中抽取出来的有用的提示。

在这里插入图片描述

图3展示了从图2的中间表示中抽取出来的类型依赖图 G \mathcal{G} G中的一些超边。

图3 A所示,我们分析后从代码中抽取出了谓词 S u b T y p e ( τ 13 , τ 5 ) SubType(\tau_{13}, \tau_5) SubType(τ13,τ5),因为和返回的表达式 v 4 v4 v4关联的类型变量必须是封闭函数返回类型的子类型。如图3 B所示,我们抽取出了谓词 O b j e c t n a m e , t i m e , f o r w a r d ( τ 8 , τ 1 , τ 2 , τ 9 ) Object_{name, time, forward}(\tau_8, \tau_1, \tau_2, \tau_9) Objectname,time,forward(τ8,τ1<

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值