Skip to content

Commit 3ab14e8

Browse files
committed
improve scaladoc
1 parent f6efdce commit 3ab14e8

File tree

2 files changed

+69
-62
lines changed
  • Layer/src/main/scala/com/thoughtworks/deeplearning
  • Symbolic/src/main/scala/com/thoughtworks/deeplearning

2 files changed

+69
-62
lines changed

Layer/src/main/scala/com/thoughtworks/deeplearning/Layer.scala

Lines changed: 42 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ object Layer {
1111

1212
private[CloseableOnce] final class ClosingFlag {
1313
var closed = false
14+
1415
@elidable(elidable.ASSERTION)
1516
def close() = {
1617
assert(!closed)
@@ -55,7 +56,6 @@ object Layer {
5556
* `Tape` is a intermediate data structure generated by the [[Layer#forward forward]] of neural network , which contains result of the `forward`, and can perform [[backward]] for back-propagation.
5657
*
5758
* @note [[close]] method must be called when this [[Tape]] will not be used any more.
58-
*
5959
* @see [[https://en.wikipedia.org/wiki/Automatic_differentiation tape auto differentiation]]
6060
*/
6161
trait Tape extends AutoCloseable {
@@ -76,14 +76,13 @@ object Layer {
7676

7777
/**
7878
* Returns a new [[Layer.Tape Tape]] that shares the same [[value]] and [[backward]] behavior with this `Tape`.
79+
*
7980
* @note The newly created `Tape` and this `Tape` must be [[close]]d independently.
8081
*/
8182
def duplicate(): Tape.Aux[Data, Delta]
8283

83-
8484
protected def forceBackward(delta: Delta): Unit
8585

86-
8786
def isTrainable: Boolean
8887

8988
/**
@@ -121,10 +120,11 @@ object Layer {
121120
}
122121

123122
/**
124-
* 一个`Layer`表示一个神经网络。每个`Layer`可以作为子网络被包含在其它`Layer`中,构成更复杂的神经网络。`Layer`的嵌套结构可以用来表示数学公式或粗粒度神经网络结构。
125-
* 当神经网络被编写完成后,其中大部分元素都是占位符,当网络开始训练时数据才真正进入到网络。
123+
* A `Layer` represents a neural network. Each `Layer` can be included in as a sub-network of another `Layer`, forming a more complex neural network. The nesting structure of `Layer` can be used to represent mathematical expression or Coarse-grain neural network structure.
124+
* When a neural network is written, the most elements in it are placeholders. When network training begins, the data enter into the network.
125+
*
126+
* === Tree structure of `Layer` ===
126127
*
127-
* === `Layer` 的树结构 ===
128128
* {{{
129129
* val myLayer: Layer.Aux[Tape.Aux[Double, Double], Tape.Aux[Double, Double]] = {
130130
* Times(
@@ -137,55 +137,59 @@ object Layer {
137137
* }
138138
* }}}
139139
*
140-
* 以上代码等价的数学公式可以用[[Symbolic]]写作:`(1.0 + x) * 2.0.toWeight``2.0.toWeight`表示一个变量,其初始值是`2`,在神经网络迭代时,其值会更新。
141-
* [[com.thoughtworks.deeplearning.DifferentiableDouble.Layers.Times Times]]、[[com.thoughtworks.deeplearning.DifferentiableDouble.Layers.Plus Plus]]都是 case class,
142-
* 因此`myLayer`是一个case class构成的嵌套结构的树。`Times``Plus`都是占位符。
140+
* The above mathematical expression with equivalent codes can be written, by [[Symbolic]], as: `(1.0 + x) * 2.0.toWeight`. `2.0.toWeight` represents a variable, of which the initial value is `2`. The value updates during neural network iteration.
141+
*
142+
* Both [[com.thoughtworks.deeplearning.DifferentiableDouble.Layers.Times Times]] and [[com.thoughtworks.deeplearning.DifferentiableDouble.Layers.Plus Plus]] are of case class, therefore, `myLayer` is a tree in nested structure consisted of the case class. `Times` and `Plus` are placeholders.
143143
*
144-
* [[com.thoughtworks.deeplearning.DifferentiableDouble.Layers.Weight Weight]]是一个包含权重的`Layer`,初始值是`2.0`。
145-
* [[com.thoughtworks.deeplearning.Symbolic.Layers.Identity Identity]]是一个输入和输出相同的`Layer`,它会将输入原样返回。`Identity`在这里是`Input`的占位符。
146-
* [[com.thoughtworks.deeplearning.Symbolic.Layers.Literal Literal]]是一个包含常量的`Layer`。
144+
* [[com.thoughtworks.deeplearning.DifferentiableDouble.Layers.Weight Weight]] is a `Layer` containing weight, of which the initial value is `2.0`.
147145
*
148-
* === 迭代 ===
146+
* [[com.thoughtworks.deeplearning.Symbolic.Layers.Identity Identity]] is a `Layer` with equal input and output, which return the same input back. The `Identity` here is the placeholder of `Input`.
149147
*
150-
* 网络每次训练称为一个迭代,分为[[forward]]和[[com.thoughtworks.deeplearning.Layer.Tape#backward backward]]两个阶段,构成一次完整的[[https://en.wikipedia.org/wiki/Backpropagation 反向传播]]流程。
148+
* [[com.thoughtworks.deeplearning.Symbolic.Layers.Literal Literal]] is a `Layer` containing a constant.
151149
*
152-
* ==== forward ====
150+
* === Iteration ===
153151
*
154-
* 在`Layer.Aux[A,B]`中调用`forward`时,`A`是输入类型,`B`是输出类型,`A`和`B`都是[[com.thoughtworks.deeplearning.Layer.Tape Tape]]。下面开始逐段解释代码:
152+
* Each training of the network is called as an iteration, including two stages: [[forward]] and [[com.thoughtworks.deeplearning.Layer.Tape#backward backward]], forming a complete process of [[https://en.wikipedia.org/wiki/Backpropagation]]
155153
*
156-
* 例如:
154+
* ==== Forward ====
155+
*
156+
* When invoking `forward` in `Layer.Aux[A,B]`, `A` is input type, `B` is output type, and both `A` and `B` are [[com.thoughtworks.deeplearning.Layer.Tape Tape]]. Now, the codes are interpreted segment by segment as follows.
157+
*
158+
* For example:
157159
* {{{
158160
* val inputTape: Tape.Aux[Double, Double] = Literal(a)
159161
* val outputTape = myLayer.forward(inputTape)
160162
* }}}
161163
*
162164
*
163-
* 当调用`myLayer.forward(inputData)`时,首先调用`Times`的`forward`,其伪代码如下:
165+
* When invoking `myLayer.forward(inputData)`, `forward` of `Times` shall be invoked first, of which the pseudo codes are as follows:
164166
* {{{
165167
* final case class Times(operand1: Layer, operand2: Layer) extends Layer {
166168
* def forward(inputData: Tape): Output = {
167169
* val upstream1 = operand1.forward(input)
168170
* val upstream2 = operand2.forward(input)
169-
* new Output(upstream1, upstream2)//这里忽略具体实现,而关注递归细节
171+
* new Output(upstream1, upstream2)// the concrete realization is ignored here, and recursion details are focused on
170172
* }
171173
* final class Output(upstream1: Tape, upstream2: Tape) extends Tape { ... }
172174
* }
173175
* }}}
174176
*
175-
* 在`myLayer.operand1`是`Plus`,`myLayer.operand2`是`Weight`,因此,`upstream1``upstream2`分别是`operand1`和`operand2` `forward` 的结果。
177+
* It is `Plus` at `myLayer.operand1`, and `Weight` at `myLayer.operand2`. Therefore, `upstream1` and `upstream2` are the results of `forward` of `operand1` and `operand2` respectively.
176178
*
177-
* 以此类推,`Plus`的`forward`代码与`Times`的`forward`类似,当调用`Plus`的`forward`时,[[com.thoughtworks.deeplearning.DifferentiableDouble.Layers.Plus#operand1 operand1]]是`Literal`,[[com.thoughtworks.deeplearning.DifferentiableDouble.Layers.Plus.operand2 operand2]]是`Identity`,这时会各自调用`Literal`和`Identity`的`forward`。
179+
* In a similar way, the `forward` code of `Plus` is similar to `forward` of `Times`. During the invoking for `forward` of `Plus`, [[com.thoughtworks.deeplearning.DifferentiableDouble.Layers.Plus#operand1 operand1]] is `Literal`, and [[com.thoughtworks.deeplearning.DifferentiableDouble.Layers.Plus.operand2 operand2]] is `Identity`. At this point, `forward` of `Literal` and `Identity` of each are invoked respectively.
180+
*
181+
* During the invoking for `forward` of `Identity`, the same input will be returned. The pseudo code for `forward` of `Identity` is as follows:
178182
*
179-
* 当调用`Identity`的`forward`时会原样返回输入, `Identity`的`forward`的伪代码如下:
180183
* {{{
181184
* def forward(inputTape: Tape.Aux[Double, Double]) = inputTape
182185
* }}}
183-
* 所以`Input`即 数学公式`(1.0 + x) * 2.0.toWeight` 中的`x`,这样`Input`就被传递给了神经网络。
186+
* Therefore, `Input` is the `x` in mathematical expression `(1.0 + x) * 2.0.toWeight`, and in this way, `Input` is propagated to the neural network.
187+
*
188+
* The return value `outputTape` of `myLayer.forward` is in `Tape` type. Therefore, a tree consisted of `Tape` will be generated finally with the structure similar to that of `myLayer`.
184189
*
185-
* `myLayer.forward`的返回值`outputTape` 是 `Tape`类型,所以最终会生成一棵`Tape`构成的树,结构和`myLayer`一样。
186-
* 因此,通过层层传播 `myLayer.forward(inputTape)`最终被`Identity`原样返回,组合进新生成的`Tape`树。
190+
* Therefore, via layer-by-layer propagation, the same `myLayer.forward(inputTape)` is finally returned by `Identity` and combined into the newly generated `Tape` tree.
187191
*
188-
* `outputTape` 的包含`forward` 的计算结果,计算结果可以用来 `backward` 比如:
192+
* The computation result including `forward` of `outputTape` can be used for `outputTape`, for example:
189193
* {{{
190194
* try {
191195
* val loss = outputTape.value
@@ -196,11 +200,10 @@ object Layer {
196200
* }
197201
* }}}
198202
*
199-
* `outputTape.value` 是数学公式 `(1.0 + x) * 2.0.toWeight` 的计算结果。
203+
* `outputTape.value` is the computation result of mathematical expression `(1.0 + x) * 2.0.toWeight`
204+
* ==== Backward ====
200205
*
201-
* ==== backward ====
202-
*
203-
* `outputTape.backward`即`Times.Output`的`backward` ,伪代码如下:
206+
* `outputTape.backward` is the `outputTape.backward` of `Times.Output`, of which the pseudo code is as follows:
204207
* {{{
205208
* case class Times(operand1: Layer, operand2: Layer) extends Layer {
206209
* def forward = ...
@@ -215,20 +218,22 @@ object Layer {
215218
* }
216219
* }}}
217220
*
218-
* `outputTape.upstream1`和`outputTape.upstream2`分别是`operand1`和`operand2` `forward` 的结果。然后`outputTape.upstream1`和`outputTape.upstream2`分别进行`backward`。
221+
* `outputTape.upstream1` and `outputTape.upstream2` are the results of `forward` of `operand1` and `operand2` respectively, which are followed by `backward` of `outputTape.upstream1` and `outputTape.upstream2`.
222+
*
219223
*
220-
* 以此类推,`Plus`的`backward`代码与`Times``backward`类似,当调用`Plus`的`backward`时,`upstream1``upstream2`分别是`Literal``Identity` `forward`的结果,这时会各自调用`upstream1``upstream2`的`backward`。
224+
* In a similar way, the `backward` code of `Plus`` is similar to `backward` of `Times`. During the invoking for `backward` of `Plus`, `upstream1` and `upstream2` are the results of `forward` of `Literal` and `Identity` respectively. At this point, `backward` of `upstream1` and `upstream2` of each are invoked respectively.
221225
*
222-
* `Weight``backward`时会更新自己,参考[[com.thoughtworks.deeplearning.DifferentiableDouble.Optimizers.LearningRate#updateDouble updateDouble]]
226+
* `Weight` updates during `backward`, refer to [[com.thoughtworks.deeplearning.DifferentiableDouble.Optimizers.LearningRate#updateDouble updateDouble]]
223227
*
224228
* === Aux & Symbolic API ===
225229
*
226-
* `Layer.Aux[A,B]`表示`Input`的类型是`A`,`Output`的类型是`B`。`Tape.Aux[C,D]`表示`Data`的类型是`C`,`Delta`的类型是`D`。
227-
* `Layer.Aux`和`Type.Aux`可以组合起来使用,比如`Layer.Aux[Tape.Aux[A,B]`,`Tape.Aux[C,D]]`可以用来表示一个`layer`的输入类型是一个`Tape`,这个`Tape`的数据类型为`A`,`delta`类型为`B`,`layer`的输出类型是一个`Tape`,这个`Tape`的数据类型为`C`,`delta`类型为`D`。
230+
* `Layer.Aux[A,B]` represents that `Input` is of `A` type, and `Output` is of `B` type. `Tape.Aux[C,D]` represents that `Data` is of `C` type, and `Delta` is of `D` type.
231+
*
232+
* `Layer.Aux` and `Type.Aux` can be combined for use. For example, `Layer.Aux[Tape.Aux[A,B]`,`Tape.Aux[C,D]]` can be used to represent that the input type of a `layer` is a `Tape`, and the data type of this `Tape` is `A`, `delta` type is `B`; the output type of a `layer` is a `Tape`, and the data type of this `Tape` is `C`, `delta` type is `D`.
228233
*
229-
* [[https://gigiigig.github.io/posts/2015/09/13/aux-pattern.html Aux]]是一种实现了[[https://www.scala-lang.org/files/archive/spec/2.12/03-types.html type refinement]]的设计模式,可以用来限制类型参数的范围。
234+
* [[https://gigiigig.github.io/posts/2015/09/13/aux-pattern.html Aux]] is a design pattern which realized [[https://www.scala-lang.org/files/archive/spec/2.12/03-types.html type refinement]] and can be used to limit the range of type parameters.
230235
*
231-
* 通常我们不会手写`Aux`类型,因为我们可以使用`Symbolic`实现同样的功能,例如在用于符号方法内部变量和返回值时:`Layer.Aux[Tape.Aux[INDArray, INDArray], Tape.Aux[INDArray, INDArray` `INDArray @Symbolic` 是等价的,所以我们经常使用`Symbolic`来替代`Aux`的写法。
236+
* Generally, we will not handwrite `Aux` type, because we can use `Symbolic` to acquire the same effect. For example, when used for symbolic method internal variable and return value: `Layer.Aux[Tape.Aux[INDArray, INDArray], Tape.Aux[INDArray, INDArray` and `INDArray @Symbolic` are equivalent, so we usually use `Symbolic` to replace the writing method of `Aux`.
232237
*
233238
* @see [[https://gigiigig.github.io/posts/2015/09/13/aux-pattern.html aux pattern]]
234239
* @see [[http://www.vlachjosef.com/aux-pattern-evolution/ aux pattern evolution]]

Symbolic/src/main/scala/com/thoughtworks/deeplearning/Symbolic.scala

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,30 +14,31 @@ import scala.language.{existentials, implicitConversions}
1414
* Combining with [[https://github.com/ThoughtWorksInc/implicit-dependent-type implicit-dependent-type]] compiler plugin,
1515
* it can be treated as a type [[http://www.scala-lang.org/files/archive/spec/2.12/11-annotations.html annotation]] in the form of `NativeOutput @Symbolic`, converting `NativeOutput` to a specific [[Layer]] type.
1616
*
17-
* == `@Symbolic` 的三种用法 ==
17+
* == Three usages of `@Symbolic` ==
1818
*
19-
* === 用于符号方法的隐式参数类型 ===
19+
* === Implicit parameter types used for symbol methods ===
2020
*
21-
* 如果某个方法的隐式类型参数标注了`@Symbolic`,那么这个方法就是符号方法,`@Symbolic`所标注的隐式参数类型是这个符号方法的'''输入类型'''
22-
* 这种情况下,`NativeOutput @Symbolic`会被展开为:
23-
* {{{Identity[NativeOutput, NativeOutput的导数类型]}}}
21+
* In case that the implicit parameter of an method is marked with `@Symbolic`, then this method is symbol method. The implicit parameter type marked with `@Symbolic` is the '''input type''' of this symbol method.
22+
* In this case, `NativeOutput @Symbolic` will be expanded as:
23+
* {{{Identity[NativeOutput, Derivative type of NativeOutput]}}}
2424
*
25-
* 例如:
25+
* For example:
2626
*
2727
* {{{
2828
* def sumNetwork(implicit scores: INDArray @Symbolic): Double = {
2929
* exp(scores).sum
3030
* }
3131
* }}}
3232
*
33-
* 上述代码中,由于`INDArray`的[[Layer.Tape#Delta 导数类型]]也是`INDArray`,所以`sumNetwork`的输入类型`INDArray @Symbolic`展开后是`Identity[INDArray, INDArray]`
33+
* In the above code, because [[Layer.Tape#Delta the derivative type]] of `INDArray` is also `INDArray`, the input type `INDArray @Symbolic` of `sumNetwork`, once expanded, is `Identity[INDArray, INDArray]`
3434
*
35-
* === 用于符号方法内部变量和返回值 ===
35+
* === Used for symbol method internal variable and return value ===
3636
*
37-
* 在符号方法内部和返回值处,`NativeOutput @Symbolic`会被展开为:
38-
* {{{Layer.Aux[Tape.Aux[输入类型的值类型, 输入类型的导数类型], Tape.Aux[NativeOutput, NativeOutput的导数类型]]}}}
37+
* A `NativeOutput @Symbolic` inside a symbol method, or at the return position of a symbol method, will be expanded as:
38+
* {{{Layer.Aux[Tape.Aux[value type of input type, derivative type of input type], Tape.Aux[NativeOutput, derivative type of NativeOutput]]}}}
39+
*
40+
* For example:
3941
*
40-
* 例如:
4142
*
4243
* {{{
4344
* def sumNetwork(implicit scores: INDArray @Symbolic): Double @Symbolic = {
@@ -47,32 +48,34 @@ import scala.language.{existentials, implicitConversions}
4748
* }
4849
* }}}
4950
*
50-
* 上述代码中,`expScores`的类型`INDArray @Symbolic`展开后是:
51+
* In the above code, the type `INDArray @Symbolic` of `expScores` is expanded as:
5152
* {{{Layer.Aux[Tape.Aux[INDArray, INDArray], Tape.Aux[INDArray, INDArray]]}}}
5253
*
53-
* 而`result`的类型`Double @Symbolic`展开后是:
54+
* The type `Double @Symbolic` of `result` is expanded as:
5455
* {{{Layer.Aux[Tape.Aux[INDArray, INDArray], Tape.Aux[Double, Double]]}}}
5556
*
56-
* === 用于符号方法之外 ===
57+
* === Used for cases excluding symbol method ===
5758
*
58-
* 在符号方法之外,`(NativeInput => NativeOutput) @Symbolic`会被展开为:
59-
* {{{Layer.Aux[Tape.Aux[NativeInput, NativeInput的导数类型], Tape.Aux[NativeOutput, NativeOutput的导数类型]]}}}
59+
* `(NativeInput => NativeOutput) @Symbolic` outside a symbol method, will be expanded as:
60+
* {{{Layer.Aux[Tape.Aux[NativeInput, derivative type of NativeInput], Tape.Aux[NativeOutput, derivative type of NativeOutput]]}}}
6061
*
61-
* 例如:
62+
* For example:
6263
*
6364
* {{{
6465
* val predictor: (INDArray => Double) @Symbolic = sumNetwork
6566
* }}}
6667
*
67-
* 上述代码中,`predictor`的类型`(INDArray => Double) @Symbolic`展开后是:
68+
* In the above code, type `(INDArray => Double) @Symbolic` of `predictor` is expanded as:
69+
*
6870
* {{{Layer.Aux[Tape.Aux[INDArray, INDArray], Tape.Aux[Double, Double]]}}}
6971
*
70-
* == 定制符号类型 ==
72+
* == Custom symbol type ==
73+
*
7174
*
72-
* `@Symbolic`通过检查[[Symbolic.ToLiteral]]隐式值来确定原生类型和导数之间的映射关系。
73-
* 因此,只要定义[[Symbolic.ToLiteral]]类型的隐式值,`@Symbolic`就可以支持定制符号类型。
75+
* The `@Symbolic` determines the mapping relation between the primitive type and derivative by checking [[Symbolic.ToLiteral]] implicit value. Therefore, `@Symbolic` can be a custom symbol type once you define your own the implicit [[Symbolic.ToLiteral]].
76+
*
77+
* For example, if you want to support `Short @Symbolic`, using [[scala.Float Float]] as the derivative type of [[scala.Short Short]], then you can conduct the follows:
7478
*
75-
* 比如,假如你希望支持`Short @Symbolic`,其中使用[[scala.Float Float]]作为[[scala.Short Short]]的导数类型,那么可以这样做:
7679
*
7780
* {{{
7881
* implicit object ShortToLiteral extends ToLiteral[Short] {
@@ -88,9 +91,8 @@ import scala.language.{existentials, implicitConversions}
8891
* val shortNetwork: (Short => Short) @Symbolic = makeShortNetwork
8992
* }}}
9093
*
91-
* 这样一来`shortNetwork`的类型就会展开为:
94+
* Thus, type of `shortNetwork` is expanded as:
9295
* {{{Layer.Aux[Tape.Aux[Short, Float], Tape.Aux[Short, Float]]}}}
93-
*
9496
* @see [[Symbolic.Layers.Identity]]
9597
* @see [[Symbolic.ToLiteral]]
9698
* @see [[Layer.Tape#Delta]]
@@ -121,7 +123,7 @@ private[deeplearning] trait LowPrioritySymbolic { this: Symbolic.type =>
121123
* val floatLayer: Float @Symbolic = 1.0f.toLayer
122124
* floatLayer
123125
* }
124-
*}}}
126+
* }}}
125127
*
126128
* The second way is [[Symbolic.autoToLayer autoToLayer]], such as:
127129
* {{{

0 commit comments

Comments
 (0)