The Template
@@ -305,7 +285,63 @@ The Template
-[WIP]
+So how does the
+Affine
+ template work? We don't want to duplicate the code above whenever we need more than one affine layer:
+
+W₁, b₁ = randn(...)
+affine₁(x) = W₁*x + b₁
+W₂, b₂ = randn(...)
+affine₂(x) = W₂*x + b₂
+model = Chain(affine₁, affine₂)
+
+Here's one way we could solve this: just keep the parameters in a Julia type, and define how that type acts as a function:
+
+type MyAffine
+ W
+ b
+end
+
+# Use the `MyAffine` layer as a model
+(l::MyAffine)(x) = l.W * x + l.b
+
+# Convenience constructor
+MyAffine(in::Integer, out::Integer) =
+ MyAffine(randn(out, in), randn(out))
+
+model = Chain(MyAffine(5, 5), MyAffine(5, 5))
+
+model(x1) # [-1.54458,0.492025,0.88687,1.93834,-4.70062]
+
+This is much better: we can now make as many affine layers as we want. This is a very common pattern, so to make it more convenient we can use the
+@net
+ macro:
+
+@net type MyAffine
+ W
+ b
+ x -> W * x + b
+end
+
+The function provided,
+x -> W * x + b
+, will be used when
+MyAffine
+ is used as a model; it's just a shorter way of defining the
+(::MyAffine)(x)
+ method above.
+
+
+However,
+@net
+ does not simply save us some keystrokes; it's the secret sauce that makes everything else in Flux go. For example, it analyses the code for the forward function so that it can differentiate it or convert it to a TensorFlow graph.
+
+
+The above code is almost exactly how
+Affine
+ is defined in Flux itself! There's no difference between "library-level" and "user-level" models, so making your code reusable doesn't involve a lot of extra complexity. Moreover, much more complex models than
+Affine
+ are equally simple to define, and equally close to the mathematical notation; read on to find out how.
diff --git a/latest/models/debugging.html b/latest/models/debugging.html
index 47d8be55..e9a64799 100644
--- a/latest/models/debugging.html
+++ b/latest/models/debugging.html
@@ -107,7 +107,7 @@ Debugging
-