From c764f299b531fdd078a9cdff0fdcc96b277ab77c Mon Sep 17 00:00:00 2001 From: Xin Qiu Date: Mon, 30 Sep 2019 14:29:28 +0800 Subject: [PATCH] Save KerasModel to pure keras or tf protobuf (#1606) * checkpoint * add unit test * revert neuralCF * revert neuralCF * some update * some update * some change --- layers/Dense.scala | 2 +- layers/Dropout.scala | 2 +- layers/Embedding.scala | 9 +++++++++ layers/Flatten.scala | 6 ++++++ layers/Input.scala | 6 ++++++ layers/LSTM.scala | 2 +- layers/Merge.scala | 20 +++++++++++++++++++ layers/Permute.scala | 2 +- layers/Reshape.scala | 2 +- layers/Select.scala | 7 +++++++ .../bigdl/dllib/keras/models/Topology.scala | 16 +++++++++++++++ 11 files changed, 69 insertions(+), 5 deletions(-) diff --git a/layers/Dense.scala b/layers/Dense.scala index 177b7c85454..29bb297432f 100644 --- a/layers/Dense.scala +++ b/layers/Dense.scala @@ -60,7 +60,7 @@ class Dense[T: ClassTag]( extends BigDLDense[T](outputDim, init, activation, wRegularizer, bRegularizer, bias, inputShape) with Net { - override private[zoo] def toKeras2(dir: String): String = { + override private[zoo] def toKeras2(): String = { val params = Net.inputShapeToString(inputShape) ++ Net.activationToString(activation) ++ Net.param(getName()) ++ diff --git a/layers/Dropout.scala b/layers/Dropout.scala index 57b6a1429e0..b14ace4f59c 100644 --- a/layers/Dropout.scala +++ b/layers/Dropout.scala @@ -38,7 +38,7 @@ class Dropout[T: ClassTag]( (implicit ev: TensorNumeric[T]) extends com.intel.analytics.bigdl.nn.keras.Dropout[T](p, inputShape) with Net { - override private[zoo] def toKeras2(dir: String): String = { + override private[zoo] def toKeras2(): String = { val params = Net.inputShapeToString(inputShape) ++ Net.param(getName()) ++ Net.param(p, "rate") diff --git a/layers/Embedding.scala b/layers/Embedding.scala index 33ea05e672a..19c68077e11 100644 --- a/layers/Embedding.scala +++ b/layers/Embedding.scala @@ -100,6 +100,15 @@ class Embedding[T: ClassTag]( model.add(layer) model.asInstanceOf[AbstractModule[Tensor[T], Tensor[T], T]] } + + override private[zoo] def toKeras2(): String = { + val params = Net.inputShapeToString(inputShape) ++ + Net.param(getName()) ++ + Net.param(inputDim, "input_dim") ++ + Net.param(outputDim, "output_dim") ++ + Net.param(maskZero, "mask_zero") + Net.kerasDef(this, params) + } } object Embedding { diff --git a/layers/Flatten.scala b/layers/Flatten.scala index 041bf4ccd1d..a4ed3329a9e 100644 --- a/layers/Flatten.scala +++ b/layers/Flatten.scala @@ -47,6 +47,12 @@ class Flatten[T: ClassTag]( Array(input.slice(1, input.length).product), batchMode = Some(true)) layer.asInstanceOf[AbstractModule[Tensor[T], Tensor[T], T]] } + + override private[zoo] def toKeras2(): String = { + val params = Net.inputShapeToString(inputShape) ++ + Net.param(getName()) + Net.kerasDef(this, params) + } } object Flatten { diff --git a/layers/Input.scala b/layers/Input.scala index 6d847a2de27..72e5d08bcb7 100644 --- a/layers/Input.scala +++ b/layers/Input.scala @@ -44,6 +44,12 @@ class Input[T: ClassTag](val inputShape: Shape)(implicit ev: TensorNumeric[T]) override def allowRebuilt(): Boolean = true override def skipDuplicateCheck(): Boolean = skipDuplicate + + override private[zoo] def toKeras2(): String = { + val params = Net.inputShapeToString(inputShape, "shape") ++ + Net.param(getName()) + Net.kerasDef(this, params) + } } /** diff --git a/layers/LSTM.scala b/layers/LSTM.scala index 00bacfd22ee..d2e90616dc6 100644 --- a/layers/LSTM.scala +++ b/layers/LSTM.scala @@ -79,7 +79,7 @@ class LSTM[T: ClassTag]( bRegularizer = bRegularizer) } - override private[zoo] def toKeras2(dir: String): String = { + override private[zoo] def toKeras2(): String = { val params = Net.inputShapeToString(inputShape) ++ Net.activationToString(activation) ++ Net.activationToString(innerActivation, "recurrent_activation") ++ diff --git a/layers/Merge.scala b/layers/Merge.scala index b5db24f4529..6c193b09979 100644 --- a/layers/Merge.scala +++ b/layers/Merge.scala @@ -53,6 +53,26 @@ class Merge[T: ClassTag]( extends KerasLayer[Tensor[T], Tensor[T], T](Merge.calcBatchInputShape(inputShape, layers)) with Net { + override private[zoo] def toKeras2(): String = { + var params = Net.inputShapeToString(inputShape) ++ + Net.param(getName()) + val kerasLayerName = mode match { + case "sum" => "Add" + case "mul" => "Multiply" + case "max" => "Maximum" + case "ave" => "Average" + case "sub" => "Subtract" + case "min" => "Minimum" + case "concat" => + params ++= Net.param(concatAxis, "axis") + "Concatenate" + case "dot" => "Dot" + case _ => + throw new IllegalArgumentException(s"Merge ${mode} is not supported in Keras2") + } + Net.kerasDef(kerasLayerName, params) + } + private val mergeMode = mode.toLowerCase() private var axis = concatAxis diff --git a/layers/Permute.scala b/layers/Permute.scala index 95572521551..b02ead1c34e 100644 --- a/layers/Permute.scala +++ b/layers/Permute.scala @@ -41,7 +41,7 @@ class Permute[T: ClassTag]( extends BigDLPermute[T]( dims, inputShape) with Net { - override private[zoo] def toKeras2(dir: String): String = { + override private[zoo] def toKeras2(): String = { val params = Net.inputShapeToString(inputShape) ++ Net.param(getName()) ++ Net.arrayToString(dims, "dims") diff --git a/layers/Reshape.scala b/layers/Reshape.scala index a1e97198c74..8f085ef1252 100644 --- a/layers/Reshape.scala +++ b/layers/Reshape.scala @@ -99,7 +99,7 @@ class Reshape[T: ClassTag]( layer.asInstanceOf[AbstractModule[Tensor[T], Tensor[T], T]] } - override private[zoo] def toKeras2(dir: String): String = { + override private[zoo] def toKeras2(): String = { val params = Net.inputShapeToString(inputShape) ++ Net.param(getName()) ++ Net.arrayToString(targetShape, "target_shape") diff --git a/layers/Select.scala b/layers/Select.scala index c052e6a85bd..ee94b492339 100644 --- a/layers/Select.scala +++ b/layers/Select.scala @@ -78,6 +78,13 @@ class Select[T: ClassTag]( val layer = com.intel.analytics.bigdl.nn.Select(positiveDim + 1, positiveIndex + 1) layer.asInstanceOf[AbstractModule[Tensor[T], Tensor[T], T]] } + + override private[zoo] def toKeras2(): String = { + val params = Net.inputShapeToString(inputShape) ++ + Net.param(getName()) ++ + Net.param(dim, "dim") + Net.kerasDef(this, params) + } } object Select { diff --git a/scala/dllib/src/main/scala/com/intel/analytics/bigdl/dllib/keras/models/Topology.scala b/scala/dllib/src/main/scala/com/intel/analytics/bigdl/dllib/keras/models/Topology.scala index ed4b64e259f..a858cc7e69c 100644 --- a/scala/dllib/src/main/scala/com/intel/analytics/bigdl/dllib/keras/models/Topology.scala +++ b/scala/dllib/src/main/scala/com/intel/analytics/bigdl/dllib/keras/models/Topology.scala @@ -609,6 +609,10 @@ class Model[T: ClassTag] private (private val _inputs : Seq[ModuleNode[T]], KerasLayerRef(this).setOutShape(Shape(_outputs.map{_.element.getOutputShape()}.toList)) + private[zoo] def getInputs(): Seq[ModuleNode[T]] = _inputs + + private[zoo] def getOutputs(): Seq[ModuleNode[T]] = _outputs + override def isKerasStyle(): Boolean = true override def computeOutputShape(inputShape: Shape): Shape = { @@ -664,6 +668,18 @@ class Model[T: ClassTag] private (private val _inputs : Seq[ModuleNode[T]], override def toKeras(): Model[T] = this + override private[zoo] def getKerasWeights(): Array[Tensor[Float]] = { + val weights = new ArrayBuffer[Tensor[Float]]() + modules(0).asInstanceOf[StaticGraph[T]].modules.foreach(m => { + val params = m.asInstanceOf[Net].getKerasWeights() + if (params != null) { + params.foreach(weights += _) + } + }) + weights.toArray + } + + override def summary( lineLength: Int = 120, positions: Array[Double] = Array(.33, .55, .67, 1)): Unit = {