Repository: systemml Updated Branches: refs/heads/master b5ef21fdc -> 61dcc85e4
http://git-wip-us.apache.org/repos/asf/systemml/blob/61dcc85e/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 c8159be..1466f4f 100644 --- a/src/main/scala/org/apache/sysml/api/dl/CaffeLayer.scala +++ b/src/main/scala/org/apache/sysml/api/dl/CaffeLayer.scala @@ -135,6 +135,28 @@ trait CaffeLayer extends BaseDMLGenerator { trait IsLossLayer extends CaffeLayer { def computeLoss(dmlScript: StringBuilder, numTabs: Int): Unit + override def init(dmlScript: StringBuilder) = { } + def scores(): String = { + val ret = net.getBottomLayers(param.getName).map(l => net.getCaffeLayer(l)).toList + ret.size.toLong match { + case 0L => throw new LanguageException("Expected atleast 1 bottom layer") + case 1L => ret.get(0).out + case _ => { + val ret1 = ret.filter(!_.out.equals("Xb")).toList + ret1.size.toLong match { + case 0L => throw new LanguageException("Atleast one of the output of previous layer should be Xb") + case 1L => ret1.get(0).out + case _ => throw new LanguageException("More than 2 bottom layers is not supported") + } + } + } + } + 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) + } } trait HasWeight extends CaffeLayer { @@ -508,16 +530,35 @@ class Concat(val param: LayerParameter, val id: Int, val net: CaffeNetwork) exte override def biasShape(): Array[Int] = null } +// L2 loss function. +class EuclideanLoss(val param: LayerParameter, val id: Int, val net: CaffeNetwork) extends CaffeLayer with IsLossLayer { + override def sourceFileName: String = if (!isSegmentationProblem()) "l2_loss" else throw new DMLRuntimeException("Segmentation is not supported for EuclideanLoss in Caffe2DML yet") + override def weightShape(): Array[Int] = null + override def biasShape(): Array[Int] = null + + override def forward(dmlScript: StringBuilder, isPrediction: Boolean) = + invokeForward(dmlScript, List[String](out), scores, "yb") + + override def backward(dmlScript: StringBuilder,outSuffix: String): Unit = + invokeBackward(dmlScript, outSuffix, List[String]("dOut" + id + outSuffix), scores, "yb") + + override def computeLoss(dmlScript: StringBuilder,numTabs: Int): Unit = + if (!isSegmentationProblem()) { + val tabBuilder = new StringBuilder + for (i <- 0 until numTabs) tabBuilder.append("\t") + val tabs = tabBuilder.toString + dmlScript.append("tmp_loss = l2_loss::forward(" + commaSep(out, "yb") + ")\n") + dmlScript.append(tabs).append("loss = loss + tmp_loss\n") + dmlScript.append(tabs).append("accuracy = -1\n") + } else { + throw new RuntimeException("Computation of loss for SoftmaxWithLoss is not implemented for segmentation problem") + } +} + 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 = - try { - return outputShape._2.toInt != 1 && outputShape._3.toInt != 1 - } catch { - case _: Throwable => throw new RuntimeException("Cannot infer the output dimensions:" + outputShape) - } override def forward(dmlScript: StringBuilder, isPrediction: Boolean) = if (!isSegmentationProblem()) { invokeForward(dmlScript, List[String](out), scores) @@ -549,18 +590,6 @@ class SoftmaxWithLoss(val param: LayerParameter, val id: Int, val net: CaffeNetw } 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") - } override def weightShape(): Array[Int] = null override def biasShape(): Array[Int] = null // ------------------------------------------------- @@ -574,6 +603,72 @@ class SoftmaxWithLoss(val param: LayerParameter, val id: Int, val net: CaffeNetw } } +class Sigmoid(val param: LayerParameter, val id: Int, val net: CaffeNetwork) extends CaffeLayer { + override def sourceFileName = "sigmoid" + override def init(dmlScript: StringBuilder) = {} + /* + * Computes the forward pass for a sigmoid nonlinearity layer. + * + * `sigmoid(x) = 1 / (1 + e^-x)` + * + * If `X` contains a single feature column, the output of a sigmoid + * layer can be interpreted as a predicted probability of a true + * class when paired with a log loss function in a binary + * classification problem. + * + * Inputs: + * - X: Inputs, of shape (any, any). + * + * Outputs: + * - out: Outputs, of same shape as `X`. + */ + override def forward(dmlScript: StringBuilder, isPrediction: Boolean) = invokeForward(dmlScript, List[String](out), X) + /* + * Computes the backward pass for a sigmoid nonlinearity layer. + * + * Inputs: + * - dout: Gradient wrt `out` from upstream, of same shape as `X`. + * - X: Inputs, of shape (any, any). + * + * 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 + // ------------------------------------------------- +} + + +class TanH(val param: LayerParameter, val id: Int, val net: CaffeNetwork) extends CaffeLayer { + override def sourceFileName = "tanh" + override def init(dmlScript: StringBuilder) = {} + /* + * Computes the forward pass for a tanh nonlinearity layer. + * + * Inputs: + * - X: Inputs, of shape (any, any). + * + * Outputs: + * - out: Outputs, of same shape as `X`. + */ + override def forward(dmlScript: StringBuilder, isPrediction: Boolean) = invokeForward(dmlScript, List[String](out), X) + /* + * Computes the backward pass for a tanh nonlinearity layer. + * + * Inputs: + * - dout: Gradient wrt `out` from upstream, of same shape as `X`. + * - X: Inputs, of shape (any, any). + * + * 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 + // ------------------------------------------------- +} + 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. // ------------------------------------------------- http://git-wip-us.apache.org/repos/asf/systemml/blob/61dcc85e/src/main/scala/org/apache/sysml/api/dl/CaffeNetwork.scala ---------------------------------------------------------------------- diff --git a/src/main/scala/org/apache/sysml/api/dl/CaffeNetwork.scala b/src/main/scala/org/apache/sysml/api/dl/CaffeNetwork.scala index 2b07788..93afbc0 100644 --- a/src/main/scala/org/apache/sysml/api/dl/CaffeNetwork.scala +++ b/src/main/scala/org/apache/sysml/api/dl/CaffeNetwork.scala @@ -212,7 +212,10 @@ class CaffeNetwork(netFilePath: String, val currentPhase: Phase, var numChannels else throw new LanguageException("Only maxpooling is supported:" + param.getPoolingParam.getPool.name) case "innerproduct" => new InnerProduct(param, id, this) case "relu" => new ReLU(param, id, this) + case "tanh" => new TanH(param, id, this) + case "sigmoid" => new Sigmoid(param, id, this) case "softmaxwithloss" => new SoftmaxWithLoss(param, id, this) + case "euclideanloss" => new EuclideanLoss(param, id, this) case "dropout" => new Dropout(param, id, this) case "data" => new Data(param, id, this, numChannels, height, width) case "input" => new Data(param, id, this, numChannels, height, width)