com.thoughtworks.deeplearning

Layer

trait Layer extends AnyRef

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. When a neural network is written, the most elements in it are placeholders. When network training begins, the data enter into the network.

Tree structure of Layer
val myLayer: Layer.Aux[Tape.Aux[Double, Double], Tape.Aux[Double, Double]] = {
Times(
  Plus(
    Literal(1.0),
    Identity[Double, Double]()
  ),
  Weight(2.0)
)
}

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.

Both Times and Plus are of case class, therefore, myLayer is a tree in nested structure consisted of the case class. Times and Plus are placeholders.

Weight is a Layer containing weight, of which the initial value is 2.0.

Identity is a Layer with equal input and output, which return the same input back. The Identity here is the placeholder of Input.

Literal is a Layer containing a constant.

Iteration

Each training of the network is called as an iteration, including two stages: forward and backward, forming a complete process of https://en.wikipedia.org/wiki/Backpropagation

Forward

When invoking forward in Layer.Aux[A,B], A is input type, B is output type, and both A and B are Tape. Now, the codes are interpreted segment by segment as follows.

For example:

val inputTape: Tape.Aux[Double, Double] = Literal(a)
val outputTape = myLayer.forward(inputTape)

When invoking myLayer.forward(inputData), forward of Times shall be invoked first, of which the pseudo codes are as follows:

final case class Times(operand1: Layer, operand2: Layer) extends Layer {
def forward(inputData: Tape): Output = {
  val upstream1 = operand1.forward(input)
  val upstream2 = operand2.forward(input)
  new Output(upstream1, upstream2)// the concrete realization is ignored here, and recursion details are focused on
}
final class Output(upstream1: Tape, upstream2: Tape) extends Tape { ... }
}

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, operand1 is Literal, and operand2 is Identity. At this point, forward of Literal and Identity of each are invoked respectively.

During the invoking for forward of Identity, the same input will be returned. The pseudo code for forward of Identity is as follows:

def forward(inputTape: Tape.Aux[Double, Double]) = inputTape

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.

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.

The computation result including forward of outputTape can be used for outputTape, for example:

try {
  val loss = outputTape.value
  outputTape.backward(loss)
  loss
} finally {
  outputTape.close()
}

outputTape.value is the computation result of mathematical expression (1.0 + x) * 2.0.toWeight

Backward

outputTape.backward is the outputTape.backward of Times.Output, of which the pseudo code is as follows:

case class Times(operand1: Layer, operand2: Layer) extends Layer {
def forward = ...
class Output(upstream1, upstream2) extends Tape {
  private def upstreamDelta1(outputDelta: Double) = ???
  private def upstreamDelta2(outputDelta: Double) = ???
  override protected def backward(outputDelta: Double): Unit = {
    upstream1.backward(upstreamDelta1(outputDelta))
    upstream2.backward(upstreamDelta2(outputDelta))
  }
}
}

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 updateDouble

Aux & Symbolic API

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.

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.

Aux is a design pattern which realized 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.

See also

Symbolic

Backpropagation

type refinement

aux pattern evolution

aux pattern

Linear Supertypes
Known Subclasses
Type Hierarchy Learn more about scaladoc diagrams
Ordering
  1. Alphabetic
  2. By inheritance
Inherited
  1. Layer
  2. AnyRef
  3. Any
Implicitly
  1. by any2stringadd
  2. by any2stringfmt
  3. by any2ArrowAssoc
  4. by any2Ensuring
  1. Hide All
  2. Show all
Learn more about member selection
Visibility
  1. Public
  2. All

Type Members

  1. abstract type Input <: Tape

  2. abstract type Output <: Tape

Abstract Value Members

  1. abstract def forward(input: Input): Output

Concrete Value Members

  1. final def !=(arg0: AnyRef): Boolean

    Definition Classes
    AnyRef
  2. final def !=(arg0: Any): Boolean

    Definition Classes
    Any
  3. final def ##(): Int

    Definition Classes
    AnyRef → Any
  4. def +(other: String): String

    Implicit information
    This member is added by an implicit conversion from Layer to StringAdd performed by method any2stringadd in scala.Predef.
    Definition Classes
    StringAdd
  5. def ->[B](y: B): (Layer, B)

    Implicit information
    This member is added by an implicit conversion from Layer to ArrowAssoc[Layer] performed by method any2ArrowAssoc in scala.Predef.
    Definition Classes
    ArrowAssoc
    Annotations
    @inline()
  6. final def ==(arg0: AnyRef): Boolean

    Definition Classes
    AnyRef
  7. final def ==(arg0: Any): Boolean

    Definition Classes
    Any
  8. final def asInstanceOf[T0]: T0

    Definition Classes
    Any
  9. def clone(): AnyRef

    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    @throws( ... )
  10. def ensuring(cond: (Layer) ⇒ Boolean, msg: ⇒ Any): Layer

    Implicit information
    This member is added by an implicit conversion from Layer to Ensuring[Layer] performed by method any2Ensuring in scala.Predef.
    Definition Classes
    Ensuring
  11. def ensuring(cond: (Layer) ⇒ Boolean): Layer

    Implicit information
    This member is added by an implicit conversion from Layer to Ensuring[Layer] performed by method any2Ensuring in scala.Predef.
    Definition Classes
    Ensuring
  12. def ensuring(cond: Boolean, msg: ⇒ Any): Layer

    Implicit information
    This member is added by an implicit conversion from Layer to Ensuring[Layer] performed by method any2Ensuring in scala.Predef.
    Definition Classes
    Ensuring
  13. def ensuring(cond: Boolean): Layer

    Implicit information
    This member is added by an implicit conversion from Layer to Ensuring[Layer] performed by method any2Ensuring in scala.Predef.
    Definition Classes
    Ensuring
  14. final def eq(arg0: AnyRef): Boolean

    Definition Classes
    AnyRef
  15. def equals(arg0: Any): Boolean

    Definition Classes
    AnyRef → Any
  16. def finalize(): Unit

    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    @throws( classOf[java.lang.Throwable] )
  17. def formatted(fmtstr: String): String

    Implicit information
    This member is added by an implicit conversion from Layer to StringFormat performed by method any2stringfmt in scala.Predef.
    Definition Classes
    StringFormat
    Annotations
    @inline()
  18. final def getClass(): Class[_]

    Definition Classes
    AnyRef → Any
  19. def hashCode(): Int

    Definition Classes
    AnyRef → Any
  20. final def isInstanceOf[T0]: Boolean

    Definition Classes
    Any
  21. final def ne(arg0: AnyRef): Boolean

    Definition Classes
    AnyRef
  22. final def notify(): Unit

    Definition Classes
    AnyRef
  23. final def notifyAll(): Unit

    Definition Classes
    AnyRef
  24. final def synchronized[T0](arg0: ⇒ T0): T0

    Definition Classes
    AnyRef
  25. def toString(): String

    Definition Classes
    AnyRef → Any
  26. final def wait(): Unit

    Definition Classes
    AnyRef
    Annotations
    @throws( ... )
  27. final def wait(arg0: Long, arg1: Int): Unit

    Definition Classes
    AnyRef
    Annotations
    @throws( ... )
  28. final def wait(arg0: Long): Unit

    Definition Classes
    AnyRef
    Annotations
    @throws( ... )
  29. def [B](y: B): (Layer, B)

    Implicit information
    This member is added by an implicit conversion from Layer to ArrowAssoc[Layer] performed by method any2ArrowAssoc in scala.Predef.
    Definition Classes
    ArrowAssoc

Shadowed Implicit Value Members

  1. val self: Any

    Implicit information
    This member is added by an implicit conversion from Layer to StringAdd performed by method any2stringadd in scala.Predef.
    Shadowing
    This implicitly inherited member is ambiguous. One or more implicitly inherited members have similar signatures, so calling this member may produce an ambiguous implicit conversion compiler error.
    To access this member you can use a type ascription:
    (layer: StringAdd).self
    Definition Classes
    StringAdd
  2. val self: Any

    Implicit information
    This member is added by an implicit conversion from Layer to StringFormat performed by method any2stringfmt in scala.Predef.
    Shadowing
    This implicitly inherited member is ambiguous. One or more implicitly inherited members have similar signatures, so calling this member may produce an ambiguous implicit conversion compiler error.
    To access this member you can use a type ascription:
    (layer: StringFormat).self
    Definition Classes
    StringFormat

Deprecated Value Members

  1. def x: Layer

    Implicit information
    This member is added by an implicit conversion from Layer to ArrowAssoc[Layer] performed by method any2ArrowAssoc in scala.Predef.
    Shadowing
    This implicitly inherited member is ambiguous. One or more implicitly inherited members have similar signatures, so calling this member may produce an ambiguous implicit conversion compiler error.
    To access this member you can use a type ascription:
    (layer: ArrowAssoc[Layer]).x
    Definition Classes
    ArrowAssoc
    Annotations
    @deprecated
    Deprecated

    (Since version 2.10.0) Use leftOfArrow instead

  2. def x: Layer

    Implicit information
    This member is added by an implicit conversion from Layer to Ensuring[Layer] performed by method any2Ensuring in scala.Predef.
    Shadowing
    This implicitly inherited member is ambiguous. One or more implicitly inherited members have similar signatures, so calling this member may produce an ambiguous implicit conversion compiler error.
    To access this member you can use a type ascription:
    (layer: Ensuring[Layer]).x
    Definition Classes
    Ensuring
    Annotations
    @deprecated
    Deprecated

    (Since version 2.10.0) Use resultOfEnsuring instead

Inherited from AnyRef

Inherited from Any

Inherited by implicit conversion any2stringadd from Layer to StringAdd

Inherited by implicit conversion any2stringfmt from Layer to StringFormat

Inherited by implicit conversion any2ArrowAssoc from Layer to ArrowAssoc[Layer]

Inherited by implicit conversion any2Ensuring from Layer to Ensuring[Layer]

Ungrouped