答:似乎以相同名称构造的模块将具有不同的名称和可变 scope。在内部,Sonnet 使用tf.make_template,它基本上是与一些 tf.VariableScope 一起包装了一个python函数,来确保对该函数的每次调用都发生在同一个 scope 内,并且第一个调用之后的所有调用都设置为重用变量。模板的一个特点是,如果已经在同一 scope 内输入了任何名称,它将使其唯一化。例如:
问:我必须给我的模块命名吗? 答:不。模块有默认名,应该是snake_case中的class name,如果必要的话,它也会被用作唯一化的名称(见上)。然而,我们推荐大家为模块起一个包含变量的名称,因为这一名称也会成为内部 scope 的名称,由此也定义了变量的名称。大多数模块的名称带有“w”(weights)和“b”(bias),来显示内部权重。大家都喜欢这么命名:
你选的名称会出现在 TensorBoard 中。 问:我怎么知道一个模块 declare 了什么变量? 答:你可以对一个模块用 get_variables() 的方法,来查询 scope 内的所有变量。注意如果模块没有连到 graph 上,就会显示错误,因为变量此时不存在,所以相关的 scope 是空的。 问:Sonnet中的所有内容都应该作为模块实现吗? 答:不,不创建tf.Variables并且不存储内部配置的计算可以在常规TF Op样式中实现,即接收输入张量,关键字参数和返回张量输出的python函数。 如果一个op要创建变量(即在内部的任何地方调用tf.get_variable,j2直播,包括间接的)它必须被作为snt.AbstractModule的一个子类,这样才能正确地处理变量共享。 需要注意,如果一个计算没有创建任何变量,可能仍然需要使用一个Module而不是Op来实现它。 除了可变共享之外,在我们希望将配置参数附加到操作系统的情况下,使用Sonnet模块可以很方便。一个例子是[content addressing](可微分神经计算机中的模块),这些模块接收多个配置参数(内存中的每个单词的大小,读写头的数量),这些输入的一些功能定义了有效输入。我们在这个模块之前使用正确输出大小的snt.Linear来提供正确的维度。由于是一个模块,实现起来很容易——在构建时提供configuration,然后提供一个method.param_size(),它给出所需输入的维数。然后我们就能得到正确的输入张量大小并进行连接。
如果上面的操作是作为op cosine_weights(memory, cos_params, word_size, num_heads) 实现的,那么指示cos_params所需大小的逻辑必须存储在一个单独的函数中。将相关功能封装到一个模块中会让代码更清晰。 问:可以将其与其他高级TF API(如TF Slim)混合使用吗? 答:Sonnet模块一旦构建出来,就遵循Tensor-In-Tensor-Out的原理,因此可以与TF-Slim等的功能混合。不过需要注意的是,这可能会导致意外行为的发生——TF-Slim控制共享是通过传递明确的scope =和 reuse = kwargs到层函数中——如果在Sonnet模块的_build()方法中使用TF-Slim层,多次调用的话就不太可能正常工作。 问:使用Sonnet与其他库与原始TF的开销(overhead)是多少? 答:没有。只有在构造计算图时才会涉及Sonnet。一旦你到了使用Session.run()的阶段,只需执行Ops就行了,不用考虑将该图合在一起用了什么库。 Hacker News 评论:窥见 DeepMind 内部研究 获得了最高支持的 HN 用户 gcr 评论称: 作为机器学习环境来说,TensorFlow 非常复杂,不同的研究小组必须定义自己的最佳 practice。使用 TF 就像学 C ++一样,每个人都学习一个稍微不同的,相互不相容的,但是广泛重叠的语言子集。 Sonnet 开源后,我们看到了DeepMind的专用工具(虽然只有一点点),以及他们在工作中使用的操作的参考实现。 对于那些想要搞透 DeepMind 工作的研究院人来说,这次开源非常有用。 不过,Sonnet 并不是彻底全新的神经网络库。目前还没有人宣称这次发布带来了什么范式上的改变,作为业内人还是很欣慰的。 研究论文:通过梯度下降学习通过梯度下降学习 (责任编辑:本港台直播) |