Skip to content

Commit

Permalink
Do not duplicate internal properties of the AbstractConv implementations
Browse files Browse the repository at this point in the history
  • Loading branch information
juliabeliaeva committed Jan 17, 2022
1 parent ce114f4 commit 6b1c592
Show file tree
Hide file tree
Showing 9 changed files with 157 additions and 206 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,43 +26,41 @@ import kotlin.math.roundToInt
* of any dimensionality. It should simplify the internal calculations needed in most convolutional
* layers and abstract the naming weights for these layers. It keeps the actual implementation
* of convolutional layers, i.e., the kernel and bias learnable variables that should
* be used in child classes in actual implementations of these layers. If the child class
* uses some values for its implementation in other form than it is kept in this child class,
* then this abstract class `internal` properties should keep the implementation values
* while the child class properties should keep the printable values that are more representative.
* But in most cases, the `internal` and child values will be the same.
* be used in child classes in actual implementations of these layers.
*
* @property [filtersInternal] number used by default in calculation of layer weights and i/o shapes
* @property [kernelSizeInternal] numbers used by default in calculation of layer weights and i/o shapes
* @property [stridesInternal] numbers used by default in calculation of layer weights and i/o shapes
* @property [dilationsInternal] numbers to keep for the dilations for implementation
* @property [activationInternal] activation used in [forward] operation implementation
* @property [kernelInitializerInternal] initializer used in actual kernel variable filling implementation
* @property [biasInitializerInternal] initializer used in actual bias variable filling implementation
* @property [kernelRegularizerInternal] regularizer function used in actual kernel variable filling implementation
* @property [biasRegularizerInternal] regularizer function used in actual bias variable filling implementation
* @property [activityRegularizerInternal] regularizer function applied to the output of the layer
* @property [paddingInternal] numbers to keep for the padding for implementation
* @property [useBiasInternal] flag if bias should be used during actual [forward] implementation
* @property [filters] number used by default in calculation of layer weights and i/o shapes
* @property [kernelSize] numbers used by default in calculation of layer weights and i/o shapes
* @property [strides] numbers used by default in calculation of layer weights and i/o shapes
* @property [dilations] numbers to keep for the dilations for implementation
* @property [activation] activation used in [forward] operation implementation
* @property [kernelInitializer] initializer used in actual kernel variable filling implementation
* @property [biasInitializer] initializer used in actual bias variable filling implementation
* @property [kernelRegularizer] regularizer function used in actual kernel variable filling implementation
* @property [biasRegularizer] regularizer function used in actual bias variable filling implementation
* @property [activityRegularizer] regularizer function applied to the output of the layer
* @property [padding] numbers to keep for the padding for implementation
* @property [useBias] flag if bias should be used during actual [forward] implementation
* @constructor Creates [AbstractConv] object
*
* @param name of the layer to name its variables
*/
public abstract class AbstractConv(
protected val filtersInternal: Int,
protected val kernelSizeInternal: IntArray,
protected val stridesInternal: IntArray,
protected val dilationsInternal: IntArray,
protected val activationInternal: Activations,
protected val kernelInitializerInternal: Initializer,
protected val biasInitializerInternal: Initializer,
protected val kernelRegularizerInternal: Regularizer?,
protected val biasRegularizerInternal: Regularizer?,
protected val activityRegularizerInternal: Regularizer?,
protected val paddingInternal: ConvPadding,
protected val useBiasInternal: Boolean,
name: String
) : Layer(name) {

protected abstract val filters: Int
protected abstract val kernelSize: IntArray
protected abstract val strides: IntArray
protected abstract val dilations: IntArray
protected abstract val activation: Activations
protected abstract val kernelInitializer: Initializer
protected abstract val biasInitializer: Initializer
protected abstract val kernelRegularizer: Regularizer?
protected abstract val biasRegularizer: Regularizer?
protected abstract val activityRegularizer: Regularizer?
protected abstract val padding: ConvPadding
protected abstract val useBias: Boolean

/** Tensor with kernel weights */
protected lateinit var kernel: KVariable

Expand All @@ -75,9 +73,9 @@ public abstract class AbstractConv(

val inputDepth = numberOfChannels // number of input channels
val outputDepth = getOutputDepth(numberOfChannels) // number of output channels
val fanIn = (inputDepth * multiply(kernelSizeInternal.toLongArray())).toInt()
val fanOut = ((outputDepth * multiply(kernelSizeInternal.toLongArray())).toDouble() /
multiply(stridesInternal.toLongArray()).toDouble()).roundToInt()
val fanIn = (inputDepth * multiply(kernelSize.toLongArray())).toInt()
val fanOut = ((outputDepth * multiply(kernelSize.toLongArray())).toDouble() /
multiply(strides.toLongArray()).toDouble()).roundToInt()

kernel = createVariable(
tf,
Expand All @@ -87,11 +85,11 @@ public abstract class AbstractConv(
computeKernelShape(numberOfChannels),
fanIn,
fanOut,
kernelInitializerInternal,
kernelRegularizerInternal
kernelInitializer,
kernelRegularizer
)

if (useBiasInternal) {
if (useBias) {
bias = createVariable(
tf,
kGraph,
Expand All @@ -100,8 +98,8 @@ public abstract class AbstractConv(
computeBiasShape(numberOfChannels),
fanIn,
fanOut,
biasInitializerInternal,
biasRegularizerInternal
biasInitializer,
biasRegularizer
)
}
}
Expand All @@ -122,7 +120,7 @@ public abstract class AbstractConv(

val withBias = bias?.let { tf.nn.biasAdd(convolution, it.variable) } ?: convolution

return Activations.convert(activationInternal).apply(tf, withBias, name)
return Activations.convert(activation).apply(tf, withBias, name)
}

/** Returns the shape of kernel weights. */
Expand All @@ -142,25 +140,25 @@ public abstract class AbstractConv(

/** Define the number of output channels given the number of input channels.
* Defaults to the number of filter in convolutional layer. */
protected open fun getOutputDepth(numberOfChannels: Long): Long = filtersInternal.toLong()
protected open fun getOutputDepth(numberOfChannels: Long): Long = filters.toLong()

/**
* Define the [kernel] shape by default from its [kernelSizeInternal],
* [filtersInternal] and the given [numberOfChannels] from input Tensor.
* Define the [kernel] shape by default from its [kernelSize],
* [filters] and the given [numberOfChannels] from input Tensor.
*
* @param numberOfChannels for input of this layer
*/
protected open fun computeKernelShape(numberOfChannels: Long): Shape =
shapeFromDims(*kernelSizeInternal.toLongArray(), numberOfChannels, filtersInternal.toLong())
shapeFromDims(*kernelSize.toLongArray(), numberOfChannels, filters.toLong())

/**
* Define the [bias] shape by default from its [filtersInternal] and
* Define the [bias] shape by default from its [filters] and
* the given [numberOfChannels] from input Tensor.
*
* @param numberOfChannels for input of this layer
*/
protected open fun computeBiasShape(numberOfChannels: Long): Shape =
Shape.make(filtersInternal.toLong())
Shape.make(filters.toLong())

/** Given a layer name specify its kernel name. */
protected abstract fun kernelVarName(name: String): String
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ private const val EXTRA_DIM = 1L
* ```
*
* @property [filters] The dimensionality of the output space (i.e. the number of filters in the convolution).
* @property [kernelSize] Long number, specifying the width of the 1D convolution window.
* @property [kernelLength] Long number, specifying the width of the 1D convolution window.
* @property [strides] Three numbers specifying the strides of the pooling operation for each dimension of input tensor.
* NOTE: Specifying stride value != 1 is incompatible with specifying `dilation` value != 1.
* @property [dilations] Three numbers specifying the dilation rate to use for
Expand All @@ -57,39 +57,28 @@ private const val EXTRA_DIM = 1L
* @since 0.3
*/
public class Conv1D(
public val filters: Int = 32,
public val kernelSize: Int = 3,
public val strides: IntArray = intArrayOf(1, 1, 1),
public val dilations: IntArray = intArrayOf(1, 1, 1),
public val activation: Activations = Activations.Relu,
public val kernelInitializer: Initializer = HeNormal(),
public val biasInitializer: Initializer = HeUniform(),
public val kernelRegularizer: Regularizer? = null,
public val biasRegularizer: Regularizer? = null,
public val activityRegularizer: Regularizer? = null,
public val padding: ConvPadding = ConvPadding.SAME,
public val useBias: Boolean = true,
public override val filters: Int = 32,
public val kernelLength: Int = 3,
public override val strides: IntArray = intArrayOf(1, 1, 1),
public override val dilations: IntArray = intArrayOf(1, 1, 1),
public override val activation: Activations = Activations.Relu,
public override val kernelInitializer: Initializer = HeNormal(),
public override val biasInitializer: Initializer = HeUniform(),
public override val kernelRegularizer: Regularizer? = null,
public override val biasRegularizer: Regularizer? = null,
public override val activityRegularizer: Regularizer? = null,
public override val padding: ConvPadding = ConvPadding.SAME,
public override val useBias: Boolean = true,
name: String = "",
) : AbstractConv(
filtersInternal = filters,
kernelSizeInternal = intArrayOf(kernelSize),
stridesInternal = strides,
dilationsInternal = dilations,
activationInternal = activation,
kernelInitializerInternal = kernelInitializer,
biasInitializerInternal = biasInitializer,
kernelRegularizerInternal = kernelRegularizer,
biasRegularizerInternal = biasRegularizer,
activityRegularizerInternal = activityRegularizer,
paddingInternal = padding,
useBiasInternal = useBias,
name = name
) {
) : AbstractConv(name = name) {

init {
requireArraySize(strides, 3, "strides")
requireArraySize(dilations, 3, "dilations")
}

override val kernelSize: IntArray = intArrayOf(kernelLength)

/** Axis of height for which the extra dimension is added (unsqueezed) before actual
* convolution operation and the output from actual implementation are squeezed. */
private val squeezeAxis = Squeeze.axis(listOf(EXTRA_DIM))
Expand All @@ -102,13 +91,13 @@ public class Conv1D(
tf: Ops,
input: Operand<Float>
): Operand<Float> {
val reshapedInput = tf.expandDims(input, tf.constant(EXTRA_DIM))
val expandedInput = tf.expandDims(input, tf.constant(EXTRA_DIM))
val expandedKernel = tf.expandDims(kernel.variable, tf.constant(EXTRA_DIM - 1))
val expandedStrides = intArrayOf(stridesInternal[0], 1, stridesInternal[1], stridesInternal[2])
val expandedDilations = intArrayOf(dilationsInternal[0], 1, dilationsInternal[1], dilationsInternal[2])
val expandedStrides = intArrayOf(strides[0], 1, strides[1], strides[2])
val expandedDilations = intArrayOf(dilations[0], 1, dilations[1], dilations[2])
val options = Conv2d.dilations(expandedDilations.toLongList()).dataFormat("NHWC")
val result = tf.nn.conv2d(
reshapedInput, expandedKernel, expandedStrides.toLongList(), paddingInternal.paddingName, options
expandedInput, expandedKernel, expandedStrides.toLongList(), padding.paddingName, options
)
return tf.squeeze(result, squeezeAxis)
}
Expand All @@ -119,13 +108,13 @@ public class Conv1D(

val cols = convOutputLength(
colsCount,
kernelSize,
paddingInternal,
kernelLength,
padding,
strides[1],
dilations[1]
)

return Shape.make(batchSize, cols, filtersInternal.toLong())
return Shape.make(batchSize, cols, filters.toLong())
}

override fun toString(): String =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,34 +52,21 @@ import org.tensorflow.op.nn.Conv2d.dilations
* @constructor Creates [Conv2D] object.
*/
public class Conv2D(
public val filters: Int = 32,
public val kernelSize: IntArray = intArrayOf(3, 3),
public val strides: IntArray = intArrayOf(1, 1, 1, 1),
public val dilations: IntArray = intArrayOf(1, 1, 1, 1),
public val activation: Activations = Activations.Relu,
public val kernelInitializer: Initializer = HeNormal(),
public val biasInitializer: Initializer = HeUniform(),
public val kernelRegularizer: Regularizer? = null,
public val biasRegularizer: Regularizer? = null,
public val activityRegularizer: Regularizer? = null,
public val padding: ConvPadding = ConvPadding.SAME,
public val useBias: Boolean = true,
public override val filters: Int = 32,
public override val kernelSize: IntArray = intArrayOf(3, 3),
public override val strides: IntArray = intArrayOf(1, 1, 1, 1),
public override val dilations: IntArray = intArrayOf(1, 1, 1, 1),
public override val activation: Activations = Activations.Relu,
public override val kernelInitializer: Initializer = HeNormal(),
public override val biasInitializer: Initializer = HeUniform(),
public override val kernelRegularizer: Regularizer? = null,
public override val biasRegularizer: Regularizer? = null,
public override val activityRegularizer: Regularizer? = null,
public override val padding: ConvPadding = ConvPadding.SAME,
public override val useBias: Boolean = true,
name: String = ""
) : AbstractConv(
filtersInternal = filters,
kernelSizeInternal = kernelSize,
stridesInternal = strides,
dilationsInternal = dilations,
activationInternal = activation,
kernelInitializerInternal = kernelInitializer,
biasInitializerInternal = biasInitializer,
kernelRegularizerInternal = kernelRegularizer,
biasRegularizerInternal = biasRegularizer,
activityRegularizerInternal = activityRegularizer,
paddingInternal = padding,
useBiasInternal = useBias,
name = name
) {
) : AbstractConv(name = name) {

init {
requireArraySize(kernelSize, 2, "kernelSize")
requireArraySize(strides, 4, "strides")
Expand All @@ -90,12 +77,12 @@ public class Conv2D(
tf: Ops,
input: Operand<Float>
): Operand<Float> {
val options = dilations(dilationsInternal.toLongList()).dataFormat("NHWC")
val options = dilations(dilations.toLongList()).dataFormat("NHWC")
return tf.nn.conv2d(
input,
kernel.variable,
stridesInternal.toLongList(),
paddingInternal.paddingName,
strides.toLongList(),
padding.paddingName,
options
)
}
Expand All @@ -107,20 +94,20 @@ public class Conv2D(

val rows = convOutputLength(
rowsCount,
kernelSizeInternal[0],
paddingInternal,
stridesInternal[1],
dilationsInternal[1]
kernelSize[0],
padding,
strides[1],
dilations[1]
)
val cols = convOutputLength(
colsCount,
kernelSizeInternal[1],
paddingInternal,
stridesInternal[2],
dilationsInternal[2]
kernelSize[1],
padding,
strides[2],
dilations[2]
)

return Shape.make(batchSize, rows, cols, filtersInternal.toLong())
return Shape.make(batchSize, rows, cols, filters.toLong())
}

override fun toString(): String =
Expand Down
Loading

0 comments on commit 6b1c592

Please sign in to comment.