You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: Layer/src/main/scala/com/thoughtworks/deeplearning/Layer.scala
+42-37Lines changed: 42 additions & 37 deletions
Original file line number
Diff line number
Diff line change
@@ -11,6 +11,7 @@ object Layer {
11
11
12
12
private[CloseableOnce] finalclassClosingFlag {
13
13
varclosed=false
14
+
14
15
@elidable(elidable.ASSERTION)
15
16
defclose() = {
16
17
assert(!closed)
@@ -55,7 +56,6 @@ object Layer {
55
56
* `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.
56
57
*
57
58
* @note [[close]] method must be called when this [[Tape]] will not be used any more.
58
-
*
59
59
* @see [[https://en.wikipedia.org/wiki/Automatic_differentiation tape auto differentiation]]
60
60
*/
61
61
traitTapeextendsAutoCloseable {
@@ -76,14 +76,13 @@ object Layer {
76
76
77
77
/**
78
78
* Returns a new [[Layer.Tape Tape]] that shares the same [[value]] and [[backward]] behavior with this `Tape`.
79
+
*
79
80
* @note The newly created `Tape` and this `Tape` must be [[close]]d independently.
* 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` ===
126
127
*
127
-
* === `Layer` 的树结构 ===
128
128
* {{{
129
129
* val myLayer: Layer.Aux[Tape.Aux[Double, Double], Tape.Aux[Double, Double]] = {
* 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.
* [[com.thoughtworks.deeplearning.DifferentiableDouble.Layers.Weight Weight]] is a `Layer` containing weight, of which the initial value is `2.0`.
147
145
*
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`.
* 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]]
155
153
*
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:
157
159
* {{{
158
160
* val inputTape: Tape.Aux[Double, Double] = Literal(a)
* 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.
* 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:
* 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`.
* Therefore, via layer-by-layer propagation, the same `myLayer.forward(inputTape)` is finally returned by `Identity` and combined into the newly generated `Tape` tree.
* `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`.
* 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.
* `Weight` updates during `backward`, refer to [[com.thoughtworks.deeplearning.DifferentiableDouble.Optimizers.LearningRate#updateDouble updateDouble]]
* `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`.
228
233
*
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.
* 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`.
232
237
*
233
238
* @see [[https://gigiigig.github.io/posts/2015/09/13/aux-pattern.html aux pattern]]
234
239
* @see [[http://www.vlachjosef.com/aux-pattern-evolution/ aux pattern evolution]]
* Combining with [[https://github.com/ThoughtWorksInc/implicit-dependent-type implicit-dependent-type]] compiler plugin,
15
15
* 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.
16
16
*
17
-
* == `@Symbolic` 的三种用法 ==
17
+
* == Three usages of `@Symbolic` ==
18
18
*
19
-
* === 用于符号方法的隐式参数类型 ===
19
+
* === Implicit parameter types used for symbol methods ===
* 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]}}}
* 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]`
34
34
*
35
-
* === 用于符号方法内部变量和返回值 ===
35
+
* === Used for symbol method internal variable and return value ===
* 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:
0 commit comments