You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@systemml.apache.org by ni...@apache.org on 2017/09/15 18:03:10 UTC
[3/4] systemml git commit: [SYSTEMML-540] Support loading of batch
normalization weights in .caffemodel file using Caffe2DML
http://git-wip-us.apache.org/repos/asf/systemml/blob/f07b5a2d/src/main/scala/org/apache/sysml/api/dl/CaffeLayer.scala
----------------------------------------------------------------------
diff --git a/src/main/scala/org/apache/sysml/api/dl/CaffeLayer.scala b/src/main/scala/org/apache/sysml/api/dl/CaffeLayer.scala
index cbd5fa3..c8159be 100644
--- a/src/main/scala/org/apache/sysml/api/dl/CaffeLayer.scala
+++ b/src/main/scala/org/apache/sysml/api/dl/CaffeLayer.scala
@@ -6,9 +6,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -32,81 +32,79 @@ import java.util.ArrayList
trait CaffeLayer extends BaseDMLGenerator {
// -------------------------------------------------
// Any layer that wants to reuse SystemML-NN has to override following methods that help in generating the DML for the given layer:
- def sourceFileName:String;
- def init(dmlScript:StringBuilder):Unit;
- def forward(dmlScript:StringBuilder, isPrediction:Boolean):Unit;
- def backward(dmlScript:StringBuilder, outSuffix:String):Unit;
- var computedOutputShape:(String, String, String) = null
- def outputShape:(String, String, String) = {
- if(computedOutputShape == null) computedOutputShape = bottomLayerOutputShape
+ def sourceFileName: String;
+ def init(dmlScript: StringBuilder): Unit;
+ def forward(dmlScript: StringBuilder, isPrediction: Boolean): Unit;
+ def backward(dmlScript: StringBuilder, outSuffix: String): Unit;
+ var computedOutputShape: (String, String, String) = null
+ def outputShape: (String, String, String) = {
+ if (computedOutputShape == null) computedOutputShape = bottomLayerOutputShape
computedOutputShape
}
// -------------------------------------------------
- var computedBottomLayerOutputShape:(String, String, String) = null
- def bottomLayerOutputShape:(String, String, String) = {
- if(computedBottomLayerOutputShape == null) {
+ var computedBottomLayerOutputShape: (String, String, String) = null
+ def bottomLayerOutputShape: (String, String, String) = {
+ if (computedBottomLayerOutputShape == null) {
// Note: if you get org.apache.sysml.parser.LanguageException: Map is null exception
// from org.apache.sysml.api.dl.CaffeNetwork.org$apache$sysml$api$dl$CaffeNetwork$$convertLayerParameterToCaffeLayer
// you are attempting to get traverse the network (for example: bottomLayerOutputShape) before it is created.
val ret = net.getBottomLayers(param.getName).map(l => net.getCaffeLayer(l)).toList
- if(ret.size == 0) throw new LanguageException("Expected atleast 1 bottom layer for " + param.getName)
+ if (ret.size == 0) throw new LanguageException("Expected atleast 1 bottom layer for " + param.getName)
computedBottomLayerOutputShape = ret(0).outputShape
}
computedBottomLayerOutputShape
}
- def param:LayerParameter
- def id:Int
- def net:CaffeNetwork
+ def param: LayerParameter
+ def id: Int
+ def net: CaffeNetwork
// --------------------------------------------------------------------------------------
// No need to override these methods in subclasses
// Exception: Only Data layer overrides "out" method to use 'Xb' for consistency
// Naming of the below methods is consistent with the nn library:
// X (feature map from the previous layer) ----> Forward pass ----> out (feature map to the next layer)
// dX (errors to the previous layer) <---- Backward pass <---- dout (errors from the next layer)
- def out = "out" + id
- var computedX:String = null
- def X:String = {
- if(computedX == null) {
+ def out = "out" + id
+ var computedX: String = null
+ def X: String = {
+ if (computedX == null) {
val ret = net.getBottomLayers(param.getName).map(l => net.getCaffeLayer(l)).toList
- if(ret.size == 0) throw new LanguageException("Expected atleast 1 bottom layer for " + param.getName)
- else if(ret.size == 1) computedX = ret(0).out
- else computedX = sum(new StringBuilder, ret.map(_.out).toList).toString()
+ if (ret.size == 0) throw new LanguageException("Expected atleast 1 bottom layer for " + param.getName)
+ else if (ret.size == 1) computedX = ret(0).out
+ else computedX = sum(new StringBuilder, ret.map(_.out).toList).toString()
}
computedX
}
- var computedDout:String = null
+ var computedDout: String = null
def dout: String = {
- if(computedDout == null) {
+ if (computedDout == null) {
val ret = net.getTopLayers(param.getName).map(l => net.getCaffeLayer(l)).toList
- if(ret.size == 0) throw new LanguageException("Expected atleast 1 top layer for " + param.getName)
- else if(ret.size == 1) computedDout = ret(0).dX(id)
- else computedDout = sum(new StringBuilder, ret.map(_.dX(id)).toList).toString()
+ if (ret.size == 0) throw new LanguageException("Expected atleast 1 top layer for " + param.getName)
+ else if (ret.size == 1) computedDout = ret(0).dX(id)
+ else computedDout = sum(new StringBuilder, ret.map(_.dX(id)).toList).toString()
}
computedDout
}
- def dX(bottomLayerID:Int) = "dOut" + id + "_" + bottomLayerID
+ def dX(bottomLayerID: Int) = "dOut" + id + "_" + bottomLayerID
// --------------------------------------------------------------------------------------
- // No need to override these methods in subclasses, instead classes that have weights and biases
+ // No need to override these methods in subclasses, instead classes that have weights and biases
// should implement HasWeight and HasBias traits.
- def dWeight():String = throw new DMLRuntimeException("dWeight is not implemented in super class")
- def dBias():String = throw new DMLRuntimeException("dBias is not implemented in super class")
- def weight():String = null;
- def weightShape():Array[Int];
- def bias():String = null;
- def biasShape():Array[Int];
- def shouldUpdateWeight():Boolean = if(weight != null) true else false
- def shouldUpdateBias():Boolean = if(bias != null) true else false
+ def dWeight(): String = throw new DMLRuntimeException("dWeight is not implemented in super class")
+ def dBias(): String = throw new DMLRuntimeException("dBias is not implemented in super class")
+ def weight(): String = null;
+ def weightShape(): Array[Int];
+ def bias(): String = null;
+ def biasShape(): Array[Int];
+ def shouldUpdateWeight(): Boolean = if (weight != null) true else false
+ def shouldUpdateBias(): Boolean = if (bias != null) true else false
// --------------------------------------------------------------------------------------
// Helper methods to simplify the code of subclasses
- def invokeInit(dmlScript:StringBuilder, returnVariables:List[String], arguments:String*):Unit = {
+ def invokeInit(dmlScript: StringBuilder, returnVariables: List[String], arguments: String*): Unit =
invoke(dmlScript, sourceFileName + "::", returnVariables, "init", arguments.toList)
- }
- def invokeForward(dmlScript:StringBuilder, returnVariables:List[String], arguments:String*):Unit = {
+ def invokeForward(dmlScript: StringBuilder, returnVariables: List[String], arguments: String*): Unit =
invoke(dmlScript, sourceFileName + "::", returnVariables, "forward", arguments.toList)
- }
// -----------------------------------------------------------------------------------
// All the layers (with the exception of Concat) call one of the below methods in the backward function.
- // The preceding layer expects that 'dX(bottomLayerID) + outSuffix' is assigned.
+ // The preceding layer expects that 'dX(bottomLayerID) + outSuffix' is assigned.
// l1 <--- dX(1) <-----|
// |-- [current layer: dOut3 (computed by backward)] <---- "dOut" + id + outSuffix
// l2 <--- dX(2) <-----|
@@ -114,73 +112,70 @@ trait CaffeLayer extends BaseDMLGenerator {
// 1. Compute backward: either call dml file's backward (for example: invokeBackward) or just propagate next layers errors (assignDoutToDX)
// 2. Then make sure that all the preceding layer get the errors using:
// bottomLayerIDs.map(bottomLayerID => dmlScript.append( dX(bottomLayerID) + outSuffix + " = " + "dOut" + id + outSuffix + "; "))
-
+
// The layers that have a corresponding dml script call this method.
// Assumption: the first variable of resultVariables is always dX
- def invokeBackward(dmlScript:StringBuilder, outSuffix:String, resultVariables:List[String], arguments:String*):Unit = {
+ def invokeBackward(dmlScript: StringBuilder, outSuffix: String, resultVariables: List[String], arguments: String*): Unit = {
invoke(dmlScript, sourceFileName + "::", resultVariables.map(_ + outSuffix), "backward", arguments.toList, false)
val bottomLayerIDs = net.getBottomLayers(param.getName).map(l => net.getCaffeLayer(l).id)
dmlScript.append("; ")
- bottomLayerIDs.map(bottomLayerID => dmlScript.append( dX(bottomLayerID) + outSuffix + " = " + resultVariables(0) + outSuffix + "; "))
+ bottomLayerIDs.map(bottomLayerID => dmlScript.append(dX(bottomLayerID) + outSuffix + " = " + resultVariables(0) + outSuffix + "; "))
dmlScript.append("\n")
}
// On-the-fly layers (such as Scale and Elementwise) call this function to propagate next layers errors to the previous layer
- def assignDoutToDX(dmlScript:StringBuilder, outSuffix:String):Unit = {
- dmlScript.append("dOut" + id + outSuffix + " = " + dout)
+ def assignDoutToDX(dmlScript: StringBuilder, outSuffix: String): Unit = {
+ dmlScript.append("dOut" + id + outSuffix + " = " + dout)
val bottomLayerIDs = net.getBottomLayers(param.getName).map(l => net.getCaffeLayer(l).id)
dmlScript.append("; ")
- bottomLayerIDs.map(bottomLayerID => dmlScript.append( dX(bottomLayerID) + outSuffix + " = " + "dOut" + id + outSuffix + "; "))
+ bottomLayerIDs.map(bottomLayerID => dmlScript.append(dX(bottomLayerID) + outSuffix + " = " + "dOut" + id + outSuffix + "; "))
dmlScript.append("\n")
}
// --------------------------------------------------------------------------------------
}
-
trait IsLossLayer extends CaffeLayer {
- def computeLoss(dmlScript:StringBuilder, numTabs:Int):Unit
+ def computeLoss(dmlScript: StringBuilder, numTabs: Int): Unit
}
trait HasWeight extends CaffeLayer {
- override def weight = param.getName + "_weight"
+ override def weight = param.getName + "_weight"
override def dWeight = param.getName + "_dWeight"
}
trait HasBias extends CaffeLayer {
- override def bias = param.getName + "_bias"
+ override def bias = param.getName + "_bias"
override def dBias = param.getName + "_dBias"
}
-class Data(val param:LayerParameter, val id:Int, val net:CaffeNetwork, val numChannels:String, val height:String, val width:String) extends CaffeLayer {
+class Data(val param: LayerParameter, val id: Int, val net: CaffeNetwork, val numChannels: String, val height: String, val width: String) extends CaffeLayer {
// -------------------------------------------------
override def sourceFileName = null
- override def init(dmlScript:StringBuilder) = {
- if(param.hasTransformParam && param.getTransformParam.hasScale) {
+ override def init(dmlScript: StringBuilder) = {
+ if (param.hasTransformParam && param.getTransformParam.hasScale) {
dmlScript.append("X_full = X_full * " + param.getTransformParam.getScale + "\n")
}
- if(param.hasDataParam && param.getDataParam.hasBatchSize) {
+ if (param.hasDataParam && param.getDataParam.hasBatchSize) {
dmlScript.append("BATCH_SIZE = " + param.getDataParam.getBatchSize + "\n")
- }
- else {
+ } else {
Caffe2DML.LOG.debug("Using default batch size of 64 as batch size is not set with DataParam")
dmlScript.append("BATCH_SIZE = 64\n")
}
}
- var dataOutputShape = ("$num_channels", "$height", "$width")
- override def forward(dmlScript:StringBuilder, isPrediction:Boolean) = { }
- override def out = "Xb"
- override def backward(dmlScript:StringBuilder, outSuffix:String) = { }
- override def outputShape = (numChannels, height, width)
- override def weightShape():Array[Int] = null
- override def biasShape():Array[Int] = null
+ var dataOutputShape = ("$num_channels", "$height", "$width")
+ override def forward(dmlScript: StringBuilder, isPrediction: Boolean) = {}
+ override def out = "Xb"
+ override def backward(dmlScript: StringBuilder, outSuffix: String) = {}
+ override def outputShape = (numChannels, height, width)
+ override def weightShape(): Array[Int] = null
+ override def biasShape(): Array[Int] = null
// -------------------------------------------------
}
-
// ------------------------------------------------------------------
// weight is ema_mean and bias is ema_var
-// Fuse
-class BatchNorm(val param:LayerParameter, val id:Int, val net:CaffeNetwork) extends CaffeLayer with HasWeight with HasBias {
- // val scale =
+// Fuse
+class BatchNorm(val param: LayerParameter, val id: Int, val net: CaffeNetwork) extends CaffeLayer with HasWeight with HasBias {
+ // val scale =
override def sourceFileName = "batch_norm2d"
/*
* Initialize the parameters of this layer.
@@ -199,8 +194,8 @@ class BatchNorm(val param:LayerParameter, val id:Int, val net:CaffeNetwork) exte
* - ema_var: Exponential moving average of the variance, of
* shape (C, 1).
*/
- override def init(dmlScript:StringBuilder) = invokeInit(dmlScript, List[String](gamma, beta, ema_mean, ema_var), numChannels)
- var update_mean_var = true
+ override def init(dmlScript: StringBuilder) = invokeInit(dmlScript, List[String](gamma, beta, ema_mean, ema_var), numChannels)
+ var update_mean_var = true
/*
* Computes the forward pass for a 2D (spatial) batch normalization
* layer. The input data has N examples, each represented as a 3D
@@ -258,9 +253,22 @@ class BatchNorm(val param:LayerParameter, val id:Int, val net:CaffeNetwork) exte
* during training.
*/
def forward(dmlScript: StringBuilder, isPrediction: Boolean): Unit = {
- val mode = if(isPrediction) "\"test\"" else "\"train\""
- invokeForward(dmlScript, List[String](out, withSuffix(ema_mean), withSuffix(ema_var), withSuffix(cache_mean), withSuffix(cache_var), withSuffix(cache_norm)),
- X, gamma, beta, numChannels, Hin, Win, mode, ema_mean, ema_var, ma_fraction, eps)
+ val mode = if (isPrediction) "\"test\"" else "\"train\""
+ invokeForward(
+ dmlScript,
+ List[String](out, withSuffix(ema_mean), withSuffix(ema_var), withSuffix(cache_mean), withSuffix(cache_var), withSuffix(cache_norm)),
+ X,
+ gamma,
+ beta,
+ numChannels,
+ Hin,
+ Win,
+ mode,
+ ema_mean,
+ ema_var,
+ ma_fraction,
+ eps
+ )
}
/*
* Computes the backward pass for a 2D (spatial) batch normalization
@@ -309,89 +317,105 @@ class BatchNorm(val param:LayerParameter, val id:Int, val net:CaffeNetwork) exte
* - dbeta: Gradient wrt `b`, of shape (C, 1).
*
*/
- def backward(dmlScript: StringBuilder, outSuffix:String): Unit = {
- invokeBackward(dmlScript, outSuffix, List[String]("dOut" + id, dgamma, dbeta), dout, out, ema_mean, ema_var, cache_mean, cache_var, cache_norm, X, gamma, beta, numChannels,
- Hin, Win, "\"train\"", ema_mean, ema_var, ma_fraction, eps)
- }
-
- private def withSuffix(str:String):String = if(update_mean_var) str else str + "_ignore"
- override def weight = "ema_mean" + id
- override def weightShape():Array[Int] = Array(numChannels.toInt, 1)
- override def biasShape():Array[Int] = Array(numChannels.toInt, 1)
- override def bias = "ema_var" + id
- def cache_mean(): String = "cache_mean" + id
- def cache_var():String = "cache_mean" + id
- def cache_norm():String = "cache_norm" + id
- var scaleLayer:Scale = null
- def gamma():String = { checkNextLayer(); scaleLayer.weight }
- def ma_fraction():String = if(param.getBatchNormParam.hasMovingAverageFraction()) param.getBatchNormParam.getMovingAverageFraction.toString else "0.999"
- def eps():String = if(param.getBatchNormParam.hasEps()) param.getBatchNormParam.getEps.toString else "1e-5"
- def beta():String = { checkNextLayer(); scaleLayer.bias }
- def dgamma():String = { checkNextLayer(); scaleLayer.dWeight }
- def dbeta():String = { checkNextLayer(); scaleLayer.dBias }
- override def shouldUpdateWeight():Boolean = false
- override def shouldUpdateBias():Boolean = false
- def ema_mean(): String = weight
- def ema_var(): String = bias
- def checkNextLayer(): Unit = {
- if(scaleLayer == null) {
+ def backward(dmlScript: StringBuilder, outSuffix: String): Unit =
+ invokeBackward(
+ dmlScript,
+ outSuffix,
+ List[String]("dOut" + id, dgamma, dbeta),
+ dout,
+ out,
+ ema_mean,
+ ema_var,
+ cache_mean,
+ cache_var,
+ cache_norm,
+ X,
+ gamma,
+ beta,
+ numChannels,
+ Hin,
+ Win,
+ "\"train\"",
+ ema_mean,
+ ema_var,
+ ma_fraction,
+ eps
+ )
+
+ private def withSuffix(str: String): String = if (update_mean_var) str else str + "_ignore"
+ override def weightShape(): Array[Int] = Array(numChannels.toInt, 1)
+ override def biasShape(): Array[Int] = Array(numChannels.toInt, 1)
+ def cache_mean(): String = "cache_mean" + id
+ def cache_var(): String = "cache_mean" + id
+ def cache_norm(): String = "cache_norm" + id
+ var scaleLayer: Scale = null
+ def gamma(): String = { checkNextLayer(); scaleLayer.weight }
+ def ma_fraction(): String = if (param.getBatchNormParam.hasMovingAverageFraction()) param.getBatchNormParam.getMovingAverageFraction.toString else "0.999"
+ def eps(): String = if (param.getBatchNormParam.hasEps()) param.getBatchNormParam.getEps.toString else "1e-5"
+ def beta(): String = { checkNextLayer(); scaleLayer.bias }
+ def dgamma(): String = { checkNextLayer(); scaleLayer.dWeight }
+ def dbeta(): String = { checkNextLayer(); scaleLayer.dBias }
+ override def shouldUpdateWeight(): Boolean = false
+ override def shouldUpdateBias(): Boolean = false
+ def ema_mean(): String = weight
+ def ema_var(): String = bias
+ def checkNextLayer(): Unit =
+ if (scaleLayer == null) {
val topLayers = net.getTopLayers(param.getName).map(l => net.getCaffeLayer(l)).toList
- if(topLayers.length != 1 && !topLayers(0).isInstanceOf[Scale]) throw new LanguageException("Only one top layer of type Scale allowed for BatchNorm")
+ if (topLayers.length != 1 && !topLayers(0).isInstanceOf[Scale]) throw new LanguageException("Only one top layer of type Scale allowed for BatchNorm")
scaleLayer = topLayers(0).asInstanceOf[Scale]
}
- }
def numChannels = bottomLayerOutputShape._1
- def Hin = bottomLayerOutputShape._2
- def Win = bottomLayerOutputShape._3
+ def Hin = bottomLayerOutputShape._2
+ def Win = bottomLayerOutputShape._3
}
// weight is gamma and bias is beta
-class Scale(val param:LayerParameter, val id:Int, val net:CaffeNetwork) extends CaffeLayer with HasWeight with HasBias {
- if(!param.getScaleParam.getBiasTerm) throw new LanguageException("Add \"scale_param { bias_term: true }\" to the layer " + param.getName)
- override def sourceFileName = null
+class Scale(val param: LayerParameter, val id: Int, val net: CaffeNetwork) extends CaffeLayer with HasWeight with HasBias {
+ if (!param.getScaleParam.getBiasTerm) throw new LanguageException("Add \"scale_param { bias_term: true }\" to the layer " + param.getName)
+ override def sourceFileName = null
override def init(dmlScript: StringBuilder): Unit = {}
// TODO: Generalize this !!
- def forward(dmlScript: StringBuilder, isPrediction: Boolean): Unit = assign(dmlScript, out, X)
- override def backward(dmlScript: StringBuilder, outSuffix:String): Unit = assignDoutToDX(dmlScript, outSuffix)
- override def weightShape():Array[Int] = Array(bottomLayerOutputShape._1.toInt, 1)
- override def biasShape():Array[Int] = Array(bottomLayerOutputShape._1.toInt, 1)
+ def forward(dmlScript: StringBuilder, isPrediction: Boolean): Unit = assign(dmlScript, out, X)
+ override def backward(dmlScript: StringBuilder, outSuffix: String): Unit = assignDoutToDX(dmlScript, outSuffix)
+ override def weightShape(): Array[Int] = Array(bottomLayerOutputShape._1.toInt, 1)
+ override def biasShape(): Array[Int] = Array(bottomLayerOutputShape._1.toInt, 1)
}
// ------------------------------------------------------------------
-class Elementwise(val param:LayerParameter, val id:Int, val net:CaffeNetwork) extends CaffeLayer {
- override def sourceFileName = null
+class Elementwise(val param: LayerParameter, val id: Int, val net: CaffeNetwork) extends CaffeLayer {
+ override def sourceFileName = null
override def init(dmlScript: StringBuilder): Unit = {}
- if(param.getEltwiseParam.hasOperation && param.getEltwiseParam.getOperation != EltwiseOp.SUM)
+ if (param.getEltwiseParam.hasOperation && param.getEltwiseParam.getOperation != EltwiseOp.SUM)
throw new LanguageException("Currently only elementwise sum operation supported")
- override def forward(dmlScript: StringBuilder, isPrediction: Boolean): Unit = {
+ override def forward(dmlScript: StringBuilder, isPrediction: Boolean): Unit =
addAndAssign(dmlScript, out, param.getBottomList.map(b => net.getCaffeLayer(b).out).toList)
- }
- override def backward(dmlScript: StringBuilder, outSuffix:String): Unit = assignDoutToDX(dmlScript, outSuffix)
+ override def backward(dmlScript: StringBuilder, outSuffix: String): Unit = assignDoutToDX(dmlScript, outSuffix)
override def outputShape = {
- if(_out == null) _out = net.getCaffeLayer(net.getBottomLayers(param.getName).take(1).toSeq.get(0)).outputShape
+ if (_out == null) _out = net.getCaffeLayer(net.getBottomLayers(param.getName).take(1).toSeq.get(0)).outputShape
_out
}
- var _out:(String, String, String) = null
- override def weightShape():Array[Int] = null
- override def biasShape():Array[Int] = null
+ var _out: (String, String, String) = null
+ override def weightShape(): Array[Int] = null
+ override def biasShape(): Array[Int] = null
}
-class Concat(val param:LayerParameter, val id:Int, val net:CaffeNetwork) extends CaffeLayer {
- override def sourceFileName = null
+class Concat(val param: LayerParameter, val id: Int, val net: CaffeNetwork) extends CaffeLayer {
+ override def sourceFileName = null
override def init(dmlScript: StringBuilder): Unit = {}
- var _childLayers:List[CaffeLayer] = null
-
+ var _childLayers: List[CaffeLayer] = null
+
// Utility function to create string of format:
// fn(fn(fn(_childLayers(0).out, _childLayers(1).out), _childLayers(2).out), ...)
// This is useful because we do not support multi-input cbind and rbind in DML.
- def _getMultiFn(fn:String):String = {
- if(_childLayers == null) _childLayers = net.getBottomLayers(param.getName).map(l => net.getCaffeLayer(l)).toList
+ def _getMultiFn(fn: String): String = {
+ if (_childLayers == null) _childLayers = net.getBottomLayers(param.getName).map(l => net.getCaffeLayer(l)).toList
var tmp = fn + "(" + _childLayers(0).out + ", " + _childLayers(1).out + ")"
- for(i <- 2 until _childLayers.size) {
- tmp = fn + "(" + tmp + ", " + _childLayers(i).out + ")"
+ for (i <- 2 until _childLayers.size) {
+ tmp = fn + "(" + tmp + ", " + _childLayers(i).out + ")"
}
tmp
}
-
+
/*
* Computes the forward pass for a concatenation layer.
*
@@ -399,174 +423,162 @@ class Concat(val param:LayerParameter, val id:Int, val net:CaffeNetwork) extends
* - n_i * c_i * h * w for each input blob i from 1 to K.
*
* Outputs:
- * - out: Outputs, of shape
+ * - out: Outputs, of shape
* - if axis = 0: (n_1 + n_2 + ... + n_K) * c_1 * h * w, and all input c_i should be the same.
* - if axis = 1: n_1 * (c_1 + c_2 + ... + c_K) * h * w, and all input n_i should be the same.
*/
- override def forward(dmlScript: StringBuilder, isPrediction: Boolean): Unit = {
- if(param.getConcatParam.getAxis == 0) {
+ override def forward(dmlScript: StringBuilder, isPrediction: Boolean): Unit =
+ if (param.getConcatParam.getAxis == 0) {
// rbind the inputs
assign(dmlScript, out, _getMultiFn("rbind"))
- }
- else if(param.getConcatParam.getAxis == 1) {
+ } else if (param.getConcatParam.getAxis == 1) {
// cbind the inputs
assign(dmlScript, out, _getMultiFn("cbind"))
- }
- else {
+ } else {
throw new DMLRuntimeException("Incorrect axis parameter for the layer " + param.getName)
}
- }
-
- def startIndex(outSuffix:String):String = "concat_start_index_" + outSuffix
- def endIndex(outSuffix:String):String = "concat_start_index_" + outSuffix
- def getConcatIndex(bottomLayerOut:String, outSuffix:String):String =
- startIndex(outSuffix) + " = " + endIndex(outSuffix) + " + 1; " +
- endIndex(outSuffix) + " = " + startIndex(outSuffix) + " + nrow(" + bottomLayerOut + "); "
-
+
+ def startIndex(outSuffix: String): String = "concat_start_index_" + outSuffix
+ def endIndex(outSuffix: String): String = "concat_start_index_" + outSuffix
+ def getConcatIndex(bottomLayerOut: String, outSuffix: String): String =
+ startIndex(outSuffix) + " = " + endIndex(outSuffix) + " + 1; " +
+ endIndex(outSuffix) + " = " + startIndex(outSuffix) + " + nrow(" + bottomLayerOut + "); "
+
/*
* Computes the backward pass for a concatenation layer.
*
* The top gradients are deconcatenated back to the inputs.
*
*/
- override def backward(dmlScript: StringBuilder, outSuffix:String): Unit = {
+ override def backward(dmlScript: StringBuilder, outSuffix: String): Unit = {
val bottomLayers = net.getBottomLayers(param.getName).map(l => net.getCaffeLayer(l)).toList
- val dOutVar = "dOut" + id + outSuffix
+ val dOutVar = "dOut" + id + outSuffix
// concat_end_index = 0
dmlScript.append(dOutVar + " = " + dout + "; concat_end_index" + outSuffix + " = 0; ")
-
+
val indexString = "concat_start_index" + outSuffix + " : concat_end_index" + outSuffix
- val doutVarAssignment = if(param.getConcatParam.getAxis == 0) " = " + dOutVar + "[" + indexString + ", ]; "
- else " = " + dOutVar + "[," + indexString + " ]; "
-
+ val doutVarAssignment =
+ if (param.getConcatParam.getAxis == 0) " = " + dOutVar + "[" + indexString + ", ]; "
+ else " = " + dOutVar + "[," + indexString + " ]; "
+
// concat_start_index = concat_end_index + 1
// concat_end_index = concat_start_index + $$ - 1
- val initializeIndexString = "concat_start_index" + outSuffix + " = concat_end_index" + outSuffix + " + 1; concat_end_index" + outSuffix +
- " = concat_start_index" + outSuffix + " + $$ - 1; "
- if(param.getConcatParam.getAxis == 0) {
+ val initializeIndexString = "concat_start_index" + outSuffix + " = concat_end_index" + outSuffix + " + 1; concat_end_index" + outSuffix +
+ " = concat_start_index" + outSuffix + " + $$ - 1; "
+ if (param.getConcatParam.getAxis == 0) {
bottomLayers.map(l => {
- dmlScript.append(initializeIndexString.replaceAll("$$", nrow(l.out)))
- // X1 = Z[concat_start_index:concat_end_index,]
- .append( dX(l.id) + outSuffix + doutVarAssignment)
+ dmlScript
+ .append(initializeIndexString.replaceAll("$$", nrow(l.out)))
+ // X1 = Z[concat_start_index:concat_end_index,]
+ .append(dX(l.id) + outSuffix + doutVarAssignment)
})
- }
- else {
+ } else {
bottomLayers.map(l => {
- dmlScript.append(initializeIndexString.replaceAll("$$", int_mult(l.outputShape._1, l.outputShape._2, l.outputShape._3) ))
- // X1 = Z[concat_start_index:concat_end_index,]
- .append( dX(l.id) + outSuffix + doutVarAssignment)
+ dmlScript
+ .append(initializeIndexString.replaceAll("$$", int_mult(l.outputShape._1, l.outputShape._2, l.outputShape._3)))
+ // X1 = Z[concat_start_index:concat_end_index,]
+ .append(dX(l.id) + outSuffix + doutVarAssignment)
})
}
dmlScript.append("\n")
}
- def sumChannels():String = {
+ def sumChannels(): String = {
val channels = _childLayers.map(_.outputShape._1)
- try {
+ try {
channels.reduce((c1, c2) => (c1.toInt + c2.toInt).toString())
- }
- catch {
- case _:Throwable => sum(new StringBuilder, channels).toString
+ } catch {
+ case _: Throwable => sum(new StringBuilder, channels).toString
}
}
override def outputShape = {
- if(_out == null) {
- if(_childLayers == null) _childLayers = net.getBottomLayers(param.getName).map(l => net.getCaffeLayer(l)).toList
- if(param.getConcatParam.getAxis == 0) {
+ if (_out == null) {
+ if (_childLayers == null) _childLayers = net.getBottomLayers(param.getName).map(l => net.getCaffeLayer(l)).toList
+ if (param.getConcatParam.getAxis == 0) {
_out = _childLayers(0).outputShape
- }
- else if(param.getConcatParam.getAxis == 1) {
+ } else if (param.getConcatParam.getAxis == 1) {
_out = (sumChannels(), _childLayers(0).outputShape._2, _childLayers(0).outputShape._3)
- }
- else {
+ } else {
throw new DMLRuntimeException("Incorrect axis parameter for the layer " + param.getName)
}
}
_out
}
- var _out:(String, String, String) = null
- override def weightShape():Array[Int] = null
- override def biasShape():Array[Int] = null
+ var _out: (String, String, String) = null
+ override def weightShape(): Array[Int] = null
+ override def biasShape(): Array[Int] = null
}
-class SoftmaxWithLoss(val param:LayerParameter, val id:Int, val net:CaffeNetwork) extends CaffeLayer with IsLossLayer {
+class SoftmaxWithLoss(val param: LayerParameter, val id: Int, val net: CaffeNetwork) extends CaffeLayer with IsLossLayer {
// -------------------------------------------------
- override def sourceFileName = if(!isSegmentationProblem()) "softmax" else "softmax2d"
- override def init(dmlScript:StringBuilder) = {}
- def isSegmentationProblem():Boolean = {
+ override def sourceFileName = if (!isSegmentationProblem()) "softmax" else "softmax2d"
+ override def init(dmlScript: StringBuilder) = {}
+ def isSegmentationProblem(): Boolean =
try {
return outputShape._2.toInt != 1 && outputShape._3.toInt != 1
- } catch {
- case _:Throwable => throw new RuntimeException("Cannot infer the output dimensions:" + outputShape)
+ } catch {
+ case _: Throwable => throw new RuntimeException("Cannot infer the output dimensions:" + outputShape)
}
- }
- override def forward(dmlScript:StringBuilder, isPrediction:Boolean) = {
- if(!isSegmentationProblem()) {
+ override def forward(dmlScript: StringBuilder, isPrediction: Boolean) =
+ if (!isSegmentationProblem()) {
invokeForward(dmlScript, List[String](out), scores)
- }
- else {
+ } else {
invokeForward(dmlScript, List[String](out), scores, outputShape._1)
}
- }
- override def backward(dmlScript:StringBuilder, outSuffix:String) = {
- if(!isSegmentationProblem()) {
+ override def backward(dmlScript: StringBuilder, outSuffix: String) =
+ if (!isSegmentationProblem()) {
invoke(dmlScript, "cross_entropy_loss::", List[String]("dProbs" + outSuffix), "backward", false, out, "yb")
- dmlScript.append("; ")
+ dmlScript.append("; ")
invoke(dmlScript, "softmax::", List[String]("dOut" + id + outSuffix), "backward", false, "dProbs", scores)
val bottomLayerIDs = net.getBottomLayers(param.getName).map(l => net.getCaffeLayer(l).id)
dmlScript.append("; ")
- bottomLayerIDs.map(bottomLayerID => dmlScript.append( dX(bottomLayerID) + outSuffix + " = " + "dOut" + id + outSuffix + "; "))
+ bottomLayerIDs.map(bottomLayerID => dmlScript.append(dX(bottomLayerID) + outSuffix + " = " + "dOut" + id + outSuffix + "; "))
dmlScript.append("\n")
- }
- else {
+ } else {
throw new RuntimeException("backward for SoftmaxWithLoss is not implemented for segmentation problem")
}
- }
- override def computeLoss(dmlScript:StringBuilder, numTabs:Int) = {
- if(!isSegmentationProblem()) {
+ override def computeLoss(dmlScript: StringBuilder, numTabs: Int) =
+ if (!isSegmentationProblem()) {
val tabBuilder = new StringBuilder
- for(i <- 0 until numTabs) tabBuilder.append("\t")
+ for (i <- 0 until numTabs) tabBuilder.append("\t")
val tabs = tabBuilder.toString
dmlScript.append("tmp_loss = cross_entropy_loss::forward(" + commaSep(out, "yb") + ")\n")
dmlScript.append(tabs).append("loss = loss + tmp_loss\n")
dmlScript.append(tabs).append("true_yb = rowIndexMax(yb)\n")
dmlScript.append(tabs).append("predicted_yb = rowIndexMax(" + out + ")\n")
dmlScript.append(tabs).append("accuracy = mean(predicted_yb == true_yb)*100\n")
- }
- else {
+ } else {
throw new RuntimeException("Computation of loss for SoftmaxWithLoss is not implemented for segmentation problem")
}
+ def scores(): String = {
+ val ret = net.getBottomLayers(param.getName).map(l => net.getCaffeLayer(l)).toList
+ if (ret.size == 1) return ret.get(0).out
+ else if (ret.size == 2) {
+ val ret1 = if (!ret.get(0).out.equals("Xb")) ret.get(0).out else "";
+ val ret2 = if (!ret.get(1).out.equals("Xb")) ret.get(1).out else "";
+ if (!ret1.equals("") && !ret2.equals("")) throw new LanguageException("Atleast one of the output of previous layer should be Xb")
+ else if (!ret1.equals("")) return ret1
+ else return ret2
+ } else
+ throw new LanguageException("More than 2 bottom layers is not supported")
}
- def scores():String = {
- val ret = net.getBottomLayers(param.getName).map(l => net.getCaffeLayer(l)).toList
- if(ret.size == 1) return ret.get(0).out
- else if(ret.size == 2) {
- val ret1 = if(!ret.get(0).out.equals("Xb")) ret.get(0).out else "";
- val ret2 = if(!ret.get(1).out.equals("Xb")) ret.get(1).out else "";
- if(!ret1.equals("") && !ret2.equals("")) throw new LanguageException("Atleast one of the output of previous layer should be Xb")
- else if(!ret1.equals("")) return ret1
- else return ret2
- }
- else
- throw new LanguageException("More than 2 bottom layers is not supported")
- }
- override def weightShape():Array[Int] = null
- override def biasShape():Array[Int] = null
+ override def weightShape(): Array[Int] = null
+ override def biasShape(): Array[Int] = null
// -------------------------------------------------
- override def bottomLayerOutputShape:(String, String, String) = {
- if(computedBottomLayerOutputShape == null) {
+ override def bottomLayerOutputShape: (String, String, String) = {
+ if (computedBottomLayerOutputShape == null) {
val ret = net.getBottomLayers(param.getName).map(l => net.getCaffeLayer(l)).filter(l => !l.isInstanceOf[Data]).toList
- if(ret.size != 1) throw new LanguageException("Expected exactly 1 bottom non-Data layer for " + param.getName)
+ if (ret.size != 1) throw new LanguageException("Expected exactly 1 bottom non-Data layer for " + param.getName)
computedBottomLayerOutputShape = ret(0).outputShape
}
computedBottomLayerOutputShape
}
}
-class ReLU(val param:LayerParameter, val id:Int, val net:CaffeNetwork) extends CaffeLayer {
+class ReLU(val param: LayerParameter, val id: Int, val net: CaffeNetwork) extends CaffeLayer {
// TODO: Leaky ReLU: negative_slope [default 0]: specifies whether to leak the negative part by multiplying it with the slope value rather than setting it to 0.
// -------------------------------------------------
- override def sourceFileName = "relu"
- override def init(dmlScript:StringBuilder) = { }
+ override def sourceFileName = "relu"
+ override def init(dmlScript: StringBuilder) = {}
/*
* Computes the forward pass for a ReLU nonlinearity layer.
*
@@ -578,7 +590,7 @@ class ReLU(val param:LayerParameter, val id:Int, val net:CaffeNetwork) extends C
* Outputs:
* - out: Outputs, of same shape as `X`.
*/
- override def forward(dmlScript:StringBuilder, isPrediction:Boolean) = invokeForward(dmlScript, List[String](out), X)
+ override def forward(dmlScript: StringBuilder, isPrediction: Boolean) = invokeForward(dmlScript, List[String](out), X)
/*
* Computes the backward pass for a ReLU nonlinearity layer.
*
@@ -592,16 +604,16 @@ class ReLU(val param:LayerParameter, val id:Int, val net:CaffeNetwork) extends C
* Outputs:
* - dX: Gradient wrt `X`, of same shape as `X`.
*/
- override def backward(dmlScript:StringBuilder, outSuffix:String) = invokeBackward(dmlScript, outSuffix, List[String]("dOut" + id), dout, X)
- override def weightShape():Array[Int] = null
- override def biasShape():Array[Int] = null
+ override def backward(dmlScript: StringBuilder, outSuffix: String) = invokeBackward(dmlScript, outSuffix, List[String]("dOut" + id), dout, X)
+ override def weightShape(): Array[Int] = null
+ override def biasShape(): Array[Int] = null
// -------------------------------------------------
}
-class Softmax(val param:LayerParameter, val id:Int, val net:CaffeNetwork) extends CaffeLayer {
+class Softmax(val param: LayerParameter, val id: Int, val net: CaffeNetwork) extends CaffeLayer {
// -------------------------------------------------
- override def sourceFileName = "softmax"
- override def init(dmlScript:StringBuilder) = { }
+ override def sourceFileName = "softmax"
+ override def init(dmlScript: StringBuilder) = {}
/*
* Computes the forward pass for a softmax classifier. The inputs
* are interpreted as unnormalized, log-probabilities for each of
@@ -619,7 +631,7 @@ class Softmax(val param:LayerParameter, val id:Int, val net:CaffeNetwork) extend
* Outputs:
* - probs: Outputs, of shape (N, D).
*/
- override def forward(dmlScript:StringBuilder, isPrediction:Boolean) = invokeForward(dmlScript, List[String](out), X)
+ override def forward(dmlScript: StringBuilder, isPrediction: Boolean) = invokeForward(dmlScript, List[String](out), X)
/*
* Computes the backward pass for a softmax classifier.
*
@@ -641,28 +653,26 @@ class Softmax(val param:LayerParameter, val id:Int, val net:CaffeNetwork) extend
* Outputs:
* - dscores: Gradient wrt `scores`, of shape (N, D).
*/
- override def backward(dmlScript:StringBuilder, outSuffix:String) = invokeBackward(dmlScript, outSuffix, List[String]("dOut" + id), dout, X)
- override def weightShape():Array[Int] = null
- override def biasShape():Array[Int] = null
+ override def backward(dmlScript: StringBuilder, outSuffix: String) = invokeBackward(dmlScript, outSuffix, List[String]("dOut" + id), dout, X)
+ override def weightShape(): Array[Int] = null
+ override def biasShape(): Array[Int] = null
// -------------------------------------------------
}
-
-class Threshold(val param:LayerParameter, val id:Int, val net:CaffeNetwork) extends CaffeLayer {
- override def sourceFileName = null
- override def init(dmlScript:StringBuilder) = { }
- val threshold = if(param.getThresholdParam.hasThreshold) param.getThresholdParam.getThreshold else 0
- override def forward(dmlScript:StringBuilder, isPrediction:Boolean) = assign(dmlScript, out, X + " > " + threshold)
- override def backward(dmlScript:StringBuilder, outSuffix:String) = throw new DMLRuntimeException("Backward operation for Threshold layer is not supported.")
- override def weightShape():Array[Int] = null
- override def biasShape():Array[Int] = null
+class Threshold(val param: LayerParameter, val id: Int, val net: CaffeNetwork) extends CaffeLayer {
+ override def sourceFileName = null
+ override def init(dmlScript: StringBuilder) = {}
+ val threshold = if (param.getThresholdParam.hasThreshold) param.getThresholdParam.getThreshold else 0
+ override def forward(dmlScript: StringBuilder, isPrediction: Boolean) = assign(dmlScript, out, X + " > " + threshold)
+ override def backward(dmlScript: StringBuilder, outSuffix: String) = throw new DMLRuntimeException("Backward operation for Threshold layer is not supported.")
+ override def weightShape(): Array[Int] = null
+ override def biasShape(): Array[Int] = null
}
-
-class Dropout(val param:LayerParameter, val id:Int, val net:CaffeNetwork) extends CaffeLayer {
+class Dropout(val param: LayerParameter, val id: Int, val net: CaffeNetwork) extends CaffeLayer {
// -------------------------------------------------
- override def sourceFileName = "dropout"
- override def init(dmlScript:StringBuilder) = { }
+ override def sourceFileName = "dropout"
+ override def init(dmlScript: StringBuilder) = {}
/*
* Computes the forward pass for an inverted dropout layer.
*
@@ -680,8 +690,8 @@ class Dropout(val param:LayerParameter, val id:Int, val net:CaffeNetwork) extend
* - out: Outputs, of same shape as `X`.
* - mask: Dropout mask used to compute the output.
*/
- override def forward(dmlScript:StringBuilder, isPrediction:Boolean) =
- if(!isPrediction)
+ override def forward(dmlScript: StringBuilder, isPrediction: Boolean) =
+ if (!isPrediction)
invokeForward(dmlScript, List[String](out, mask), X, p, seed)
else
assign(dmlScript, out, X) // Forward-pass not required to be performed during prediction for Dropout layer
@@ -700,18 +710,17 @@ class Dropout(val param:LayerParameter, val id:Int, val net:CaffeNetwork) extend
* Outputs:
* - dX: Gradient wrt `X`, of same shape as `X`.
*/
- override def backward(dmlScript:StringBuilder, outSuffix:String) = invokeBackward(dmlScript, outSuffix,
- List[String]("dOut" + id), dout, X, p, mask)
+ override def backward(dmlScript: StringBuilder, outSuffix: String) = invokeBackward(dmlScript, outSuffix, List[String]("dOut" + id), dout, X, p, mask)
// -------------------------------------------------
def mask = "mask" + id
// dropout ratio
- def p = if(param.getDropoutParam.hasDropoutRatio()) param.getDropoutParam.getDropoutRatio.toString else "0.5"
- def seed = "-1"
- override def weightShape():Array[Int] = null
- override def biasShape():Array[Int] = null
+ def p = if (param.getDropoutParam.hasDropoutRatio()) param.getDropoutParam.getDropoutRatio.toString else "0.5"
+ def seed = "-1"
+ override def weightShape(): Array[Int] = null
+ override def biasShape(): Array[Int] = null
}
-class InnerProduct(val param:LayerParameter, val id:Int, val net:CaffeNetwork) extends CaffeLayer with HasWeight with HasBias {
+class InnerProduct(val param: LayerParameter, val id: Int, val net: CaffeNetwork) extends CaffeLayer with HasWeight with HasBias {
// -------------------------------------------------
// TODO: bias_filler [default type: 'constant' value: 0]; bias_term [default true]: specifies whether to learn and apply a set of additive biases to the filter outputs
override def sourceFileName = "affine"
@@ -735,7 +744,7 @@ class InnerProduct(val param:LayerParameter, val id:Int, val net:CaffeNetwork) e
* - W: Weights, of shape (D, M).
* - b: Biases, of shape (1, M).
*/
- override def init(dmlScript:StringBuilder) = invokeInit(dmlScript, List[String](weight, bias), numFeatures, numNeurons)
+ override def init(dmlScript: StringBuilder) = invokeInit(dmlScript, List[String](weight, bias), numFeatures, numNeurons)
/*
* Computes the forward pass for an affine (fully-connected) layer
* with M neurons. The input data has N examples, each with D
@@ -749,8 +758,8 @@ class InnerProduct(val param:LayerParameter, val id:Int, val net:CaffeNetwork) e
* Outputs:
* - out: Outputs, of shape (N, M).
*/
- override def forward(dmlScript:StringBuilder, isPrediction:Boolean) =
- invokeForward(dmlScript, List[String](out), X, weight, bias)
+ override def forward(dmlScript: StringBuilder, isPrediction: Boolean) =
+ invokeForward(dmlScript, List[String](out), X, weight, bias)
/*
* Computes the backward pass for a fully-connected (affine) layer
* with M neurons.
@@ -766,23 +775,22 @@ class InnerProduct(val param:LayerParameter, val id:Int, val net:CaffeNetwork) e
* - dW: Gradient wrt `W`, of shape (D, M).
* - db: Gradient wrt `b`, of shape (1, M).
*/
- override def backward(dmlScript:StringBuilder, outSuffix:String) =
- invokeBackward(dmlScript, outSuffix, List[String]("dOut" + id, dWeight, dBias), dout, X, weight, bias)
+ override def backward(dmlScript: StringBuilder, outSuffix: String) =
+ invokeBackward(dmlScript, outSuffix, List[String]("dOut" + id, dWeight, dBias), dout, X, weight, bias)
// -------------------------------------------------
// num_output (c_o): the number of filters
- def numNeurons = param.getInnerProductParam.getNumOutput.toString
+ def numNeurons = param.getInnerProductParam.getNumOutput.toString
def numFeatures = int_mult(bottomLayerOutputShape._1, bottomLayerOutputShape._2, bottomLayerOutputShape._3)
// n * c_o * 1 * 1
- override def outputShape = ( param.getInnerProductParam.getNumOutput.toString, "1", "1" )
- override def weightShape():Array[Int] = Array(numFeatures.toInt, numNeurons.toInt)
- override def biasShape():Array[Int] = Array(1, numNeurons.toInt)
+ override def outputShape = (param.getInnerProductParam.getNumOutput.toString, "1", "1")
+ override def weightShape(): Array[Int] = Array(numFeatures.toInt, numNeurons.toInt)
+ override def biasShape(): Array[Int] = Array(1, numNeurons.toInt)
}
-
-class MaxPooling(val param:LayerParameter, val id:Int, val net:CaffeNetwork) extends CaffeLayer {
+class MaxPooling(val param: LayerParameter, val id: Int, val net: CaffeNetwork) extends CaffeLayer {
// -------------------------------------------------
- override def sourceFileName = "max_pool2d_builtin"
- override def init(dmlScript:StringBuilder) = {}
+ override def sourceFileName = "max_pool2d_builtin"
+ override def init(dmlScript: StringBuilder) = {}
/*
* Computes the forward pass for a 2D spatial max pooling layer.
* The input data has N examples, each represented as a 3D volume
@@ -810,9 +818,8 @@ class MaxPooling(val param:LayerParameter, val id:Int, val net:CaffeNetwork) ext
* - Hout: Output height.
* - Wout: Output width.
*/
- override def forward(dmlScript:StringBuilder, isPrediction:Boolean) =
- invokeForward(dmlScript, List[String](out, "ignoreHout_"+id, "ignoreWout_"+id),
- X, numChannels, Hin, Win, kernel_h, kernel_w, stride_h, stride_w, pad_h, pad_w)
+ override def forward(dmlScript: StringBuilder, isPrediction: Boolean) =
+ invokeForward(dmlScript, List[String](out, "ignoreHout_" + id, "ignoreWout_" + id), X, numChannels, Hin, Win, kernel_h, kernel_w, stride_h, stride_w, pad_h, pad_w)
/*
* Computes the backward pass for a 2D spatial max pooling layer.
* The input data has N examples, each represented as a 3D volume
@@ -839,50 +846,58 @@ class MaxPooling(val param:LayerParameter, val id:Int, val net:CaffeNetwork) ext
* Outputs:
* - dX: Gradient wrt `X`, of shape (N, C*Hin*Win).
*/
- override def backward(dmlScript:StringBuilder, outSuffix:String) =
+ override def backward(dmlScript: StringBuilder, outSuffix: String) =
invokeBackward(dmlScript, outSuffix, List[String]("dOut" + id), dout, Hout, Wout, X, numChannels, Hin, Win, kernel_h, kernel_w, stride_h, stride_w, pad_h, pad_w)
// n * c * h_o * w_o, where h_o and w_o are computed in the same way as convolution.
- override def outputShape = ( numChannels, Hout, Wout )
+ override def outputShape = (numChannels, Hout, Wout)
// -------------------------------------------------
- def Hin = bottomLayerOutputShape._2
- def Win = bottomLayerOutputShape._3
- def Hout = ConvolutionUtils.getConv2dOutputMap(bottomLayerOutputShape._2, kernel_h, stride_h, pad_h)
- def Wout = ConvolutionUtils.getConv2dOutputMap(bottomLayerOutputShape._3, kernel_w, stride_w, pad_w)
+ def Hin = bottomLayerOutputShape._2
+ def Win = bottomLayerOutputShape._3
+ def Hout = ConvolutionUtils.getConv2dOutputMap(bottomLayerOutputShape._2, kernel_h, stride_h, pad_h)
+ def Wout = ConvolutionUtils.getConv2dOutputMap(bottomLayerOutputShape._3, kernel_w, stride_w, pad_w)
def poolingParam = param.getPoolingParam
- def numChannels = bottomLayerOutputShape._1
+ def numChannels = bottomLayerOutputShape._1
// kernel_size (or kernel_h and kernel_w): specifies height and width of each filter
- def kernel_h = if(poolingParam.hasKernelH) poolingParam.getKernelH.toString
- else poolingParam.getKernelSize.toString
- def kernel_w = if(poolingParam.hasKernelW) poolingParam.getKernelW.toString
- else poolingParam.getKernelSize.toString
+ def kernel_h =
+ if (poolingParam.hasKernelH) poolingParam.getKernelH.toString
+ else poolingParam.getKernelSize.toString
+ def kernel_w =
+ if (poolingParam.hasKernelW) poolingParam.getKernelW.toString
+ else poolingParam.getKernelSize.toString
// stride (or stride_h and stride_w) [default 1]: specifies the intervals at which to apply the filters to the input
- def stride_h = if(poolingParam.hasStrideH) poolingParam.getStrideH.toString
- else if(poolingParam.hasStride) poolingParam.getStride.toString
- else "1"
- def stride_w = if(poolingParam.hasStrideW) poolingParam.getStrideW.toString
- else if(poolingParam.hasStride) poolingParam.getStride.toString
- else "1"
+ def stride_h =
+ if (poolingParam.hasStrideH) poolingParam.getStrideH.toString
+ else if (poolingParam.hasStride) poolingParam.getStride.toString
+ else "1"
+ def stride_w =
+ if (poolingParam.hasStrideW) poolingParam.getStrideW.toString
+ else if (poolingParam.hasStride) poolingParam.getStride.toString
+ else "1"
// pad (or pad_h and pad_w) [default 0]: specifies the number of pixels to (implicitly) add to each side of the input
- def pad_h = if(poolingParam.hasPadH) poolingParam.getPadH.toString
- else if(poolingParam.hasPad) poolingParam.getPad.toString
- else "0"
- def pad_w = if(poolingParam.hasPadW) poolingParam.getPadW.toString
- else if(poolingParam.hasPad) poolingParam.getPad.toString
- else "0"
- override def weightShape():Array[Int] = null
- override def biasShape():Array[Int] = null
+ def pad_h =
+ if (poolingParam.hasPadH) poolingParam.getPadH.toString
+ else if (poolingParam.hasPad) poolingParam.getPad.toString
+ else "0"
+ def pad_w =
+ if (poolingParam.hasPadW) poolingParam.getPadW.toString
+ else if (poolingParam.hasPad) poolingParam.getPad.toString
+ else "0"
+ override def weightShape(): Array[Int] = null
+ override def biasShape(): Array[Int] = null
}
-class Convolution(val param:LayerParameter, val id:Int, val net:CaffeNetwork) extends CaffeLayer with HasWeight with HasBias {
- def isDepthWise():Boolean = {
- if(param.getConvolutionParam.hasGroup && param.getConvolutionParam.getGroup != 1 && numChannels.toInt % param.getConvolutionParam.getGroup != 0)
- throw new DMLRuntimeException("The number of groups=" + param.getConvolutionParam.getGroup + " is not supported as it is not divisible by number of channels" + numChannels + ".")
+class Convolution(val param: LayerParameter, val id: Int, val net: CaffeNetwork) extends CaffeLayer with HasWeight with HasBias {
+ def isDepthWise(): Boolean = {
+ if (param.getConvolutionParam.hasGroup && param.getConvolutionParam.getGroup != 1 && numChannels.toInt % param.getConvolutionParam.getGroup != 0)
+ throw new DMLRuntimeException(
+ "The number of groups=" + param.getConvolutionParam.getGroup + " is not supported as it is not divisible by number of channels" + numChannels + "."
+ )
param.getConvolutionParam.hasGroup && param.getConvolutionParam.getGroup != 1
}
- def depthMultiplier():String = if(isDepthWise) (numChannels.toInt / param.getConvolutionParam.getGroup).toString else throw new DMLRuntimeException("Incorrect usage of depth")
-
+ def depthMultiplier(): String = if (isDepthWise) (numChannels.toInt / param.getConvolutionParam.getGroup).toString else throw new DMLRuntimeException("Incorrect usage of depth")
+
// -------------------------------------------------
- override def sourceFileName = if(isDepthWise) "conv2d_builtin_depthwise" else "conv2d_builtin"
+ override def sourceFileName = if (isDepthWise) "conv2d_builtin_depthwise" else "conv2d_builtin"
/*
* Initialize the parameters of this layer.
*
@@ -911,12 +926,11 @@ class Convolution(val param:LayerParameter, val id:Int, val net:CaffeNetwork) ex
* - W: Weights, of shape (F, C*Hf*Wf).
* - b: Biases, of shape (F, 1).
*/
- override def init(dmlScript:StringBuilder) = {
- if(isDepthWise)
+ override def init(dmlScript: StringBuilder) =
+ if (isDepthWise)
invokeInit(dmlScript, List[String](weight, bias), numChannels, depthMultiplier, kernel_h, kernel_w)
else
invokeInit(dmlScript, List[String](weight, bias), numKernels, numChannels, kernel_h, kernel_w)
- }
/*
* Computes the forward pass for a 2D spatial convolutional layer with
* F filters. The input data has N examples, each represented as a 3D
@@ -953,14 +967,40 @@ class Convolution(val param:LayerParameter, val id:Int, val net:CaffeNetwork) ex
* - Hout: Output height.
* - Wout: Output width.
*/
- override def forward(dmlScript:StringBuilder, isPrediction:Boolean) = {
- if(isDepthWise)
- invokeForward(dmlScript, List[String](out, "ignoreHout_"+id, "ignoreWout_"+id),
- X, weight, bias, numChannels, Hin, Win, depthMultiplier, kernel_h, kernel_w, stride_h, stride_w, pad_h, pad_w)
+ override def forward(dmlScript: StringBuilder, isPrediction: Boolean) =
+ if (isDepthWise)
+ invokeForward(
+ dmlScript,
+ List[String](out, "ignoreHout_" + id, "ignoreWout_" + id),
+ X,
+ weight,
+ bias,
+ numChannels,
+ Hin,
+ Win,
+ depthMultiplier,
+ kernel_h,
+ kernel_w,
+ stride_h,
+ stride_w,
+ pad_h,
+ pad_w
+ )
else
- invokeForward(dmlScript, List[String](out, "ignoreHout_"+id, "ignoreWout_"+id),
- X, weight, bias, numChannels, Hin, Win, kernel_h, kernel_w, stride_h, stride_w, pad_h, pad_w)
- }
+ invokeForward(dmlScript,
+ List[String](out, "ignoreHout_" + id, "ignoreWout_" + id),
+ X,
+ weight,
+ bias,
+ numChannels,
+ Hin,
+ Win,
+ kernel_h,
+ kernel_w,
+ stride_h,
+ stride_w,
+ pad_h,
+ pad_w)
/*
* Computes the backward pass for a 2D spatial convolutional layer
* with F filters.
@@ -997,71 +1037,114 @@ class Convolution(val param:LayerParameter, val id:Int, val net:CaffeNetwork) ex
* - dW: Gradient wrt `W`, of shape (F, C*Hf*Wf).
* - db: Gradient wrt `b`, of shape (F, 1).
*/
- override def backward(dmlScript:StringBuilder, outSuffix:String) = {
- if(isDepthWise)
- invokeBackward(dmlScript, outSuffix, List[String]("dOut" + id, dWeight, dBias), dout, Hout, Wout, X, weight, bias, numChannels, Hin, Win, depthMultiplier, kernel_h, kernel_w, stride_h, stride_w, pad_h, pad_w)
+ override def backward(dmlScript: StringBuilder, outSuffix: String) =
+ if (isDepthWise)
+ invokeBackward(
+ dmlScript,
+ outSuffix,
+ List[String]("dOut" + id, dWeight, dBias),
+ dout,
+ Hout,
+ Wout,
+ X,
+ weight,
+ bias,
+ numChannels,
+ Hin,
+ Win,
+ depthMultiplier,
+ kernel_h,
+ kernel_w,
+ stride_h,
+ stride_w,
+ pad_h,
+ pad_w
+ )
else
- invokeBackward(dmlScript, outSuffix, List[String]("dOut" + id, dWeight, dBias), dout, Hout, Wout, X, weight, bias, numChannels, Hin, Win, kernel_h, kernel_w, stride_h, stride_w, pad_h, pad_w)
- }
+ invokeBackward(
+ dmlScript,
+ outSuffix,
+ List[String]("dOut" + id, dWeight, dBias),
+ dout,
+ Hout,
+ Wout,
+ X,
+ weight,
+ bias,
+ numChannels,
+ Hin,
+ Win,
+ kernel_h,
+ kernel_w,
+ stride_h,
+ stride_w,
+ pad_h,
+ pad_w
+ )
// if not depthwise, n * c_o * h_o * w_o, where h_o = (h_i + 2 * pad_h - kernel_h) / stride_h + 1 and w_o likewise.
// else (N, C*M*Hout*Wout)
- override def outputShape = {
- if(isDepthWise) ( (numChannels.toInt*depthMultiplier.toInt).toString, Hout, Wout )
- else ( numKernels, Hout, Wout )
- }
+ override def outputShape =
+ if (isDepthWise) ((numChannels.toInt * depthMultiplier.toInt).toString, Hout, Wout)
+ else (numKernels, Hout, Wout)
// -------------------------------------------------
def numChannels = bottomLayerOutputShape._1
- def Hin = bottomLayerOutputShape._2
- def Win = bottomLayerOutputShape._3
- def Hout = ConvolutionUtils.getConv2dOutputMap(bottomLayerOutputShape._2, kernel_h, stride_h, pad_h)
- def Wout = ConvolutionUtils.getConv2dOutputMap(bottomLayerOutputShape._3, kernel_w, stride_w, pad_w)
+ def Hin = bottomLayerOutputShape._2
+ def Win = bottomLayerOutputShape._3
+ def Hout = ConvolutionUtils.getConv2dOutputMap(bottomLayerOutputShape._2, kernel_h, stride_h, pad_h)
+ def Wout = ConvolutionUtils.getConv2dOutputMap(bottomLayerOutputShape._3, kernel_w, stride_w, pad_w)
// -------------------------------------------------
def convParam = param.getConvolutionParam
// if depthwise (C, M*Hf*Wf) else (F, C*Hf*Wf)
- override def weightShape():Array[Int] = {
- if(isDepthWise) Array(numChannels.toInt, int_mult(depthMultiplier, kernel_h, kernel_w).toInt)
+ override def weightShape(): Array[Int] =
+ if (isDepthWise) Array(numChannels.toInt, int_mult(depthMultiplier, kernel_h, kernel_w).toInt)
else Array(numKernels.toInt, int_mult(numChannels, kernel_h, kernel_w).toInt)
- }
// if depthwise (C*M, 1) else (F, 1)
- override def biasShape():Array[Int] = {
- if(isDepthWise) Array(numChannels.toInt*depthMultiplier.toInt, 1)
+ override def biasShape(): Array[Int] =
+ if (isDepthWise) Array(numChannels.toInt * depthMultiplier.toInt, 1)
else Array(numKernels.toInt, 1)
- }
// num_output (c_o): the number of filters
def numKernels = convParam.getNumOutput.toString
// kernel_size (or kernel_h and kernel_w): specifies height and width of each filter
- def kernel_h = if(convParam.hasKernelH) convParam.getKernelH.toString
- else if(convParam.getKernelSizeCount > 0) convParam.getKernelSize(0).toString
- else throw new LanguageException("Incorrect kernel parameters")
- def kernel_w = if(convParam.hasKernelW) convParam.getKernelW.toString
- else if(convParam.getKernelSizeCount > 0) convParam.getKernelSize(0).toString
- else throw new LanguageException("Incorrect kernel parameters")
+ def kernel_h =
+ if (convParam.hasKernelH) convParam.getKernelH.toString
+ else if (convParam.getKernelSizeCount > 0) convParam.getKernelSize(0).toString
+ else throw new LanguageException("Incorrect kernel parameters")
+ def kernel_w =
+ if (convParam.hasKernelW) convParam.getKernelW.toString
+ else if (convParam.getKernelSizeCount > 0) convParam.getKernelSize(0).toString
+ else throw new LanguageException("Incorrect kernel parameters")
// stride (or stride_h and stride_w) [default 1]: specifies the intervals at which to apply the filters to the input
- def stride_h = if(convParam.hasStrideH) convParam.getStrideH.toString
- else if(convParam.getStrideCount > 0) convParam.getStride(0).toString
- else "1"
- def stride_w = if(convParam.hasStrideW) convParam.getStrideW.toString
- else if(convParam.getStrideCount > 0) convParam.getStride(0).toString
- else "1"
+ def stride_h =
+ if (convParam.hasStrideH) convParam.getStrideH.toString
+ else if (convParam.getStrideCount > 0) convParam.getStride(0).toString
+ else "1"
+ def stride_w =
+ if (convParam.hasStrideW) convParam.getStrideW.toString
+ else if (convParam.getStrideCount > 0) convParam.getStride(0).toString
+ else "1"
// pad (or pad_h and pad_w) [default 0]: specifies the number of pixels to (implicitly) add to each side of the input
- def pad_h = if(convParam.hasPadH) convParam.getPadH.toString
- else if(convParam.getPadCount > 0) convParam.getPad(0).toString
- else "0"
- def pad_w = if(convParam.hasPadW) convParam.getPadW.toString
- else if(convParam.getPadCount > 0) convParam.getPad(0).toString
- else "0"
+ def pad_h =
+ if (convParam.hasPadH) convParam.getPadH.toString
+ else if (convParam.getPadCount > 0) convParam.getPad(0).toString
+ else "0"
+ def pad_w =
+ if (convParam.hasPadW) convParam.getPadW.toString
+ else if (convParam.getPadCount > 0) convParam.getPad(0).toString
+ else "0"
}
-class DeConvolution(val param:LayerParameter, val id:Int, val net:CaffeNetwork) extends CaffeLayer with HasWeight with HasBias {
- def isDepthWise():Boolean = {
- if(param.getConvolutionParam.hasGroup && param.getConvolutionParam.getGroup != 1 && numChannels.toInt % param.getConvolutionParam.getGroup != 0)
- throw new DMLRuntimeException("The number of groups=" + param.getConvolutionParam.getGroup + " is not supported as it is not divisible by number of channels" + numChannels + ".")
+class DeConvolution(val param: LayerParameter, val id: Int, val net: CaffeNetwork) extends CaffeLayer with HasWeight with HasBias {
+ def isDepthWise(): Boolean = {
+ if (param.getConvolutionParam.hasGroup && param.getConvolutionParam.getGroup != 1 && numChannels.toInt % param.getConvolutionParam.getGroup != 0)
+ throw new DMLRuntimeException(
+ "The number of groups=" + param.getConvolutionParam.getGroup + " is not supported as it is not divisible by number of channels" + numChannels + "."
+ )
param.getConvolutionParam.hasGroup && param.getConvolutionParam.getGroup != 1
}
- def depthMultiplier():String = if(isDepthWise) (numChannels.toInt / param.getConvolutionParam.getGroup).toString else throw new DMLRuntimeException("Incorrect usage of depth")
-
- override def sourceFileName: String = if(isDepthWise) "conv2d_transpose_depthwise" else "conv2d_transpose"
-
+ def depthMultiplier(): String = if (isDepthWise) (numChannels.toInt / param.getConvolutionParam.getGroup).toString else throw new DMLRuntimeException("Incorrect usage of depth")
+
+ override def sourceFileName: String = if (isDepthWise) "conv2d_transpose_depthwise" else "conv2d_transpose"
+
/*
* Utility function to initialize the parameters of this layer.
*
@@ -1082,37 +1165,34 @@ class DeConvolution(val param:LayerParameter, val id:Int, val net:CaffeNetwork)
* - M: Depth of each filter (C must be divisible by M).
* - Hf: Filter height.
* - Wf: Filter width.
- *
+ *
* Outputs:
* - W: Weights, of shape (C, F*Hf*Wf).
* - b: Biases, of shape (F, 1).
*/
- override def init(dmlScript: StringBuilder): Unit = {
- if(isDepthWise)
+ override def init(dmlScript: StringBuilder): Unit =
+ if (isDepthWise)
invokeInit(dmlScript, List[String](weight, bias), numChannels, depthMultiplier, kernel_h, kernel_w)
else
invokeInit(dmlScript, List[String](weight, bias), numKernels, numChannels, kernel_h, kernel_w)
- }
-
- private def C_DivideBy_M():Int = numChannels.toInt / depthMultiplier.toInt
-
- // if depthwise (C/M, M*Hf*Wf), else (C, F*Hf*Wf)
- override def weightShape():Array[Int] = {
- if(isDepthWise)
+
+ private def C_DivideBy_M(): Int = numChannels.toInt / depthMultiplier.toInt
+
+ // if depthwise (C/M, M*Hf*Wf), else (C, F*Hf*Wf)
+ override def weightShape(): Array[Int] =
+ if (isDepthWise)
Array(C_DivideBy_M, int_mult(depthMultiplier, kernel_h, kernel_w).toInt)
else
Array(numChannels.toInt, int_mult(numKernels, kernel_h, kernel_w).toInt)
- }
// if depthwise (C/M, 1), else (F, 1)
- override def biasShape():Array[Int] = {
- if(isDepthWise)
+ override def biasShape(): Array[Int] =
+ if (isDepthWise)
Array(C_DivideBy_M, 1)
else
Array(numKernels.toInt, 1)
- }
-
- private def numGroups:Int = if(param.getConvolutionParam.hasGroup) param.getConvolutionParam.getGroup else 1
-
+
+ private def numGroups: Int = if (param.getConvolutionParam.hasGroup) param.getConvolutionParam.getGroup else 1
+
/*
* Computes the forward pass for a 2D spatial transpose convolutional
* layer with F filters. The input data has N examples, each
@@ -1142,15 +1222,47 @@ class DeConvolution(val param:LayerParameter, val id:Int, val net:CaffeNetwork)
* - Hout: Output height.
* - Wout: Output width.
*/
- override def forward(dmlScript: StringBuilder,isPrediction: Boolean): Unit = {
- if(isDepthWise)
- invokeForward(dmlScript, List[String](out, "ignoreHout_"+id, "ignoreWout_"+id),
- X, weight, bias, numChannels, Hin, Win, depthMultiplier, kernel_h, kernel_w, stride_h, stride_w, pad_h, pad_w, "0", "0")
+ override def forward(dmlScript: StringBuilder, isPrediction: Boolean): Unit =
+ if (isDepthWise)
+ invokeForward(
+ dmlScript,
+ List[String](out, "ignoreHout_" + id, "ignoreWout_" + id),
+ X,
+ weight,
+ bias,
+ numChannels,
+ Hin,
+ Win,
+ depthMultiplier,
+ kernel_h,
+ kernel_w,
+ stride_h,
+ stride_w,
+ pad_h,
+ pad_w,
+ "0",
+ "0"
+ )
else
- invokeForward(dmlScript, List[String](out, "ignoreHout_"+id, "ignoreWout_"+id),
- X, weight, bias, numChannels, Hin, Win, kernel_h, kernel_w, stride_h, stride_w, pad_h, pad_w, "0", "0")
- }
-
+ invokeForward(
+ dmlScript,
+ List[String](out, "ignoreHout_" + id, "ignoreWout_" + id),
+ X,
+ weight,
+ bias,
+ numChannels,
+ Hin,
+ Win,
+ kernel_h,
+ kernel_w,
+ stride_h,
+ stride_w,
+ pad_h,
+ pad_w,
+ "0",
+ "0"
+ )
+
/*
* Computes the backward pass for a 2D spatial transpose
* convolutional layer with F filters.
@@ -1179,58 +1291,100 @@ class DeConvolution(val param:LayerParameter, val id:Int, val net:CaffeNetwork)
* - dW: Gradient wrt `W`, of shape (C, F*Hf*Wf).
* - db: Gradient wrt `b`, of shape (F, 1).
*/
- override def backward(dmlScript:StringBuilder, outSuffix:String) = {
- if(isDepthWise)
- invokeBackward(dmlScript, outSuffix, List[String]("dOut" + id, dWeight, dBias),
- dout, Hout, Wout, X, weight, bias, numChannels, Hin, Win, depthMultiplier, kernel_h, kernel_w, stride_h, stride_w, pad_h, pad_w)
+ override def backward(dmlScript: StringBuilder, outSuffix: String) =
+ if (isDepthWise)
+ invokeBackward(
+ dmlScript,
+ outSuffix,
+ List[String]("dOut" + id, dWeight, dBias),
+ dout,
+ Hout,
+ Wout,
+ X,
+ weight,
+ bias,
+ numChannels,
+ Hin,
+ Win,
+ depthMultiplier,
+ kernel_h,
+ kernel_w,
+ stride_h,
+ stride_w,
+ pad_h,
+ pad_w
+ )
else
- invokeBackward(dmlScript, outSuffix, List[String]("dOut" + id, dWeight, dBias),
- dout, Hout, Wout, X, weight, bias, numChannels, Hin, Win, kernel_h, kernel_w, stride_h, stride_w, pad_h, pad_w)
- }
+ invokeBackward(
+ dmlScript,
+ outSuffix,
+ List[String]("dOut" + id, dWeight, dBias),
+ dout,
+ Hout,
+ Wout,
+ X,
+ weight,
+ bias,
+ numChannels,
+ Hin,
+ Win,
+ kernel_h,
+ kernel_w,
+ stride_h,
+ stride_w,
+ pad_h,
+ pad_w
+ )
// if not depthwise n * c_o * h_o * w_o, where h_o = (h_i + 2 * pad_h - kernel_h) / stride_h + 1 and w_o likewise.
// else (N, C/M*Hout*Wout)
- override def outputShape = if(isDepthWise) ( C_DivideBy_M().toString, Hout, Wout ) else ( numChannels, Hout, Wout )
+ override def outputShape = if (isDepthWise) (C_DivideBy_M().toString, Hout, Wout) else (numChannels, Hout, Wout)
// -------------------------------------------------
def numChannels = bottomLayerOutputShape._1
- def Hin = bottomLayerOutputShape._2
- def Win = bottomLayerOutputShape._3
+ def Hin = bottomLayerOutputShape._2
+ def Win = bottomLayerOutputShape._3
// Hout = strideh * (Hin-1) - 2*padh + Hf + out_padh
- def Hout:String = try {
- (stride_h.toInt * (Hin.toInt-1) - 2*pad_h.toInt + kernel_h.toInt).toString()
- }
- catch {
- case _:Throwable => stride_h + " * " + "(" + Hin + "-1) - 2*" + pad_h + " + " + kernel_h
- }
+ def Hout: String =
+ try {
+ (stride_h.toInt * (Hin.toInt - 1) - 2 * pad_h.toInt + kernel_h.toInt).toString()
+ } catch {
+ case _: Throwable => stride_h + " * " + "(" + Hin + "-1) - 2*" + pad_h + " + " + kernel_h
+ }
// Wout = stridew * (Win-1) - 2*padw + Wf + out_padw
- def Wout:String = try {
- (stride_w.toInt * (Win.toInt-1) - 2*pad_w.toInt + kernel_w.toInt).toString()
- }
- catch {
- case _:Throwable => stride_w + " * " + "(" + Win + "-1) - 2*" + pad_w + " + " + kernel_w
- }
+ def Wout: String =
+ try {
+ (stride_w.toInt * (Win.toInt - 1) - 2 * pad_w.toInt + kernel_w.toInt).toString()
+ } catch {
+ case _: Throwable => stride_w + " * " + "(" + Win + "-1) - 2*" + pad_w + " + " + kernel_w
+ }
// -------------------------------------------------
def convParam = param.getConvolutionParam
// num_output (c_o): the number of filters
def numKernels = convParam.getNumOutput.toString
// kernel_size (or kernel_h and kernel_w): specifies height and width of each filter
- def kernel_h = if(convParam.hasKernelH) convParam.getKernelH.toString
- else if(convParam.getKernelSizeCount > 0) convParam.getKernelSize(0).toString
- else throw new LanguageException("Incorrect kernel parameters")
- def kernel_w = if(convParam.hasKernelW) convParam.getKernelW.toString
- else if(convParam.getKernelSizeCount > 0) convParam.getKernelSize(0).toString
- else throw new LanguageException("Incorrect kernel parameters")
+ def kernel_h =
+ if (convParam.hasKernelH) convParam.getKernelH.toString
+ else if (convParam.getKernelSizeCount > 0) convParam.getKernelSize(0).toString
+ else throw new LanguageException("Incorrect kernel parameters")
+ def kernel_w =
+ if (convParam.hasKernelW) convParam.getKernelW.toString
+ else if (convParam.getKernelSizeCount > 0) convParam.getKernelSize(0).toString
+ else throw new LanguageException("Incorrect kernel parameters")
// stride (or stride_h and stride_w) [default 1]: specifies the intervals at which to apply the filters to the input
- def stride_h = if(convParam.hasStrideH) convParam.getStrideH.toString
- else if(convParam.getStrideCount > 0) convParam.getStride(0).toString
- else "1"
- def stride_w = if(convParam.hasStrideW) convParam.getStrideW.toString
- else if(convParam.getStrideCount > 0) convParam.getStride(0).toString
- else "1"
+ def stride_h =
+ if (convParam.hasStrideH) convParam.getStrideH.toString
+ else if (convParam.getStrideCount > 0) convParam.getStride(0).toString
+ else "1"
+ def stride_w =
+ if (convParam.hasStrideW) convParam.getStrideW.toString
+ else if (convParam.getStrideCount > 0) convParam.getStride(0).toString
+ else "1"
// pad (or pad_h and pad_w) [default 0]: specifies the number of pixels to (implicitly) add to each side of the input
- def pad_h = if(convParam.hasPadH) convParam.getPadH.toString
- else if(convParam.getPadCount > 0) convParam.getPad(0).toString
- else "0"
- def pad_w = if(convParam.hasPadW) convParam.getPadW.toString
- else if(convParam.getPadCount > 0) convParam.getPad(0).toString
- else "0"
+ def pad_h =
+ if (convParam.hasPadH) convParam.getPadH.toString
+ else if (convParam.getPadCount > 0) convParam.getPad(0).toString
+ else "0"
+ def pad_w =
+ if (convParam.hasPadW) convParam.getPadW.toString
+ else if (convParam.getPadCount > 0) convParam.getPad(0).toString
+ else "0"
}