Add SameDiff exec debugging listener + few fixes (#104)
* First pass on SameDiff op exec debug listener Signed-off-by: Alex Black <blacka101@gmail.com> * #7555 DL4J helpers - don't fall back on builtin for op profiler exceptions Signed-off-by: Alex Black <blacka101@gmail.com> * Exec debugging listener + fixes Signed-off-by: Alex Black <blacka101@gmail.com> * Fix import counts for TF ops in OpValidationSuite Signed-off-by: Alex Black <blacka101@gmail.com> * Fix bad DL4J test configuration Signed-off-by: Alex Black <blacka101@gmail.com> * Exec debugging listener polish Signed-off-by: Alex Black <blacka101@gmail.com> * Small fix Signed-off-by: Alex Black <blacka101@gmail.com> * Another fix Signed-off-by: Alex Black <blacka101@gmail.com>master
parent
ba1d1b160b
commit
edb71bf46f
|
@ -165,35 +165,13 @@ public class FrozenLayerWithBackpropTest extends BaseDL4JTest {
|
||||||
.weightInit(WeightInit.XAVIER)
|
.weightInit(WeightInit.XAVIER)
|
||||||
.updater(new Sgd(2))
|
.updater(new Sgd(2))
|
||||||
.list()
|
.list()
|
||||||
.layer(0,
|
.layer(new DenseLayer.Builder().nIn(4).nOut(3).build())
|
||||||
new DenseLayer.Builder()
|
.layer(new org.deeplearning4j.nn.conf.layers.misc.FrozenLayerWithBackprop(
|
||||||
.nIn(4)
|
new DenseLayer.Builder().nIn(3).nOut(4).build()))
|
||||||
.nOut(3)
|
.layer(new org.deeplearning4j.nn.conf.layers.misc.FrozenLayerWithBackprop(
|
||||||
.build()
|
new DenseLayer.Builder().nIn(4).nOut(2).build()))
|
||||||
)
|
.layer(new org.deeplearning4j.nn.conf.layers.misc.FrozenLayerWithBackprop(
|
||||||
.layer(1,
|
new OutputLayer.Builder(LossFunctions.LossFunction.MSE).activation(Activation.TANH).nIn(2).nOut(1).build()))
|
||||||
new org.deeplearning4j.nn.conf.layers.misc.FrozenLayerWithBackprop(
|
|
||||||
new DenseLayer.Builder()
|
|
||||||
.nIn(3)
|
|
||||||
.nOut(4)
|
|
||||||
.build()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.layer(2,
|
|
||||||
new org.deeplearning4j.nn.conf.layers.misc.FrozenLayerWithBackprop(
|
|
||||||
new DenseLayer.Builder()
|
|
||||||
.nIn(4)
|
|
||||||
.nOut(2)
|
|
||||||
.build()
|
|
||||||
)
|
|
||||||
).layer(3,
|
|
||||||
new org.deeplearning4j.nn.conf.layers.misc.FrozenLayerWithBackprop(
|
|
||||||
new OutputLayer.Builder(LossFunctions.LossFunction.MSE)
|
|
||||||
.nIn(2)
|
|
||||||
.nOut(1)
|
|
||||||
.build()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
MultiLayerNetwork network = new MultiLayerNetwork(conf1);
|
MultiLayerNetwork network = new MultiLayerNetwork(conf1);
|
||||||
|
@ -238,70 +216,18 @@ public class FrozenLayerWithBackpropTest extends BaseDL4JTest {
|
||||||
.seed(12345)
|
.seed(12345)
|
||||||
.graphBuilder()
|
.graphBuilder()
|
||||||
.addInputs("input")
|
.addInputs("input")
|
||||||
.addLayer(initialLayer,
|
.addLayer(initialLayer, new DenseLayer.Builder().nIn(4).nOut(4).build(),"input")
|
||||||
new DenseLayer.Builder()
|
.addLayer(frozenBranchUnfrozenLayer0, new DenseLayer.Builder().nIn(4).nOut(3).build(),initialLayer)
|
||||||
.nIn(4)
|
.addLayer(frozenBranchFrozenLayer1, new org.deeplearning4j.nn.conf.layers.misc.FrozenLayerWithBackprop(
|
||||||
.nOut(4)
|
new DenseLayer.Builder().nIn(3).nOut(4).build()),frozenBranchUnfrozenLayer0)
|
||||||
.build(),
|
.addLayer(frozenBranchFrozenLayer2, new org.deeplearning4j.nn.conf.layers.misc.FrozenLayerWithBackprop(
|
||||||
"input"
|
new DenseLayer.Builder().nIn(4).nOut(2).build()),frozenBranchFrozenLayer1)
|
||||||
)
|
.addLayer(unfrozenLayer0, new DenseLayer.Builder().nIn(4).nOut(4).build(),initialLayer)
|
||||||
.addLayer(frozenBranchUnfrozenLayer0,
|
.addLayer(unfrozenLayer1, new DenseLayer.Builder().nIn(4).nOut(2).build(),unfrozenLayer0)
|
||||||
new DenseLayer.Builder()
|
.addLayer(unfrozenBranch2, new DenseLayer.Builder().nIn(2).nOut(1).build(),unfrozenLayer1)
|
||||||
.nIn(4)
|
.addVertex("merge", new MergeVertex(), frozenBranchFrozenLayer2, unfrozenBranch2)
|
||||||
.nOut(3)
|
.addLayer(frozenBranchOutput,new org.deeplearning4j.nn.conf.layers.misc.FrozenLayerWithBackprop(
|
||||||
.build(),
|
new OutputLayer.Builder(LossFunctions.LossFunction.MSE).activation(Activation.TANH).nIn(3).nOut(1).build()),"merge")
|
||||||
initialLayer
|
|
||||||
)
|
|
||||||
.addLayer(frozenBranchFrozenLayer1,
|
|
||||||
new org.deeplearning4j.nn.conf.layers.misc.FrozenLayerWithBackprop(
|
|
||||||
new DenseLayer.Builder()
|
|
||||||
.nIn(3)
|
|
||||||
.nOut(4)
|
|
||||||
.build()
|
|
||||||
),
|
|
||||||
frozenBranchUnfrozenLayer0
|
|
||||||
)
|
|
||||||
.addLayer(frozenBranchFrozenLayer2,
|
|
||||||
new org.deeplearning4j.nn.conf.layers.misc.FrozenLayerWithBackprop(
|
|
||||||
new DenseLayer.Builder()
|
|
||||||
.nIn(4)
|
|
||||||
.nOut(2)
|
|
||||||
.build()
|
|
||||||
),
|
|
||||||
frozenBranchFrozenLayer1
|
|
||||||
)
|
|
||||||
.addLayer(unfrozenLayer0,
|
|
||||||
new DenseLayer.Builder()
|
|
||||||
.nIn(4)
|
|
||||||
.nOut(4)
|
|
||||||
.build(),
|
|
||||||
initialLayer
|
|
||||||
)
|
|
||||||
.addLayer(unfrozenLayer1,
|
|
||||||
new DenseLayer.Builder()
|
|
||||||
.nIn(4)
|
|
||||||
.nOut(2)
|
|
||||||
.build(),
|
|
||||||
unfrozenLayer0
|
|
||||||
)
|
|
||||||
.addLayer(unfrozenBranch2,
|
|
||||||
new DenseLayer.Builder()
|
|
||||||
.nIn(2)
|
|
||||||
.nOut(1)
|
|
||||||
.build(),
|
|
||||||
unfrozenLayer1
|
|
||||||
)
|
|
||||||
.addVertex("merge",
|
|
||||||
new MergeVertex(), frozenBranchFrozenLayer2, unfrozenBranch2)
|
|
||||||
.addLayer(frozenBranchOutput,
|
|
||||||
new org.deeplearning4j.nn.conf.layers.misc.FrozenLayerWithBackprop(
|
|
||||||
new OutputLayer.Builder(LossFunctions.LossFunction.MSE)
|
|
||||||
.nIn(3)
|
|
||||||
.nOut(1)
|
|
||||||
.build()
|
|
||||||
),
|
|
||||||
"merge"
|
|
||||||
)
|
|
||||||
.setOutputs(frozenBranchOutput)
|
.setOutputs(frozenBranchOutput)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ import org.nd4j.linalg.api.memory.MemoryWorkspace;
|
||||||
import org.nd4j.linalg.api.ndarray.INDArray;
|
import org.nd4j.linalg.api.ndarray.INDArray;
|
||||||
import org.nd4j.linalg.api.shape.Shape;
|
import org.nd4j.linalg.api.shape.Shape;
|
||||||
import org.nd4j.linalg.convolution.Convolution;
|
import org.nd4j.linalg.convolution.Convolution;
|
||||||
|
import org.nd4j.linalg.exception.ND4JOpProfilerException;
|
||||||
import org.nd4j.linalg.factory.Nd4j;
|
import org.nd4j.linalg.factory.Nd4j;
|
||||||
import org.nd4j.linalg.primitives.Pair;
|
import org.nd4j.linalg.primitives.Pair;
|
||||||
import org.deeplearning4j.nn.workspace.LayerWorkspaceMgr;
|
import org.deeplearning4j.nn.workspace.LayerWorkspaceMgr;
|
||||||
|
@ -170,6 +171,8 @@ public class ConvolutionLayer extends BaseLayer<org.deeplearning4j.nn.conf.layer
|
||||||
pad, biasGradView, weightGradView, afn,
|
pad, biasGradView, weightGradView, afn,
|
||||||
layerConf().getCudnnAlgoMode(), layerConf().getCudnnBwdFilterAlgo(), layerConf().getCudnnBwdDataAlgo(),
|
layerConf().getCudnnAlgoMode(), layerConf().getCudnnBwdFilterAlgo(), layerConf().getCudnnBwdDataAlgo(),
|
||||||
convolutionMode, dilation, workspaceMgr);
|
convolutionMode, dilation, workspaceMgr);
|
||||||
|
} catch (ND4JOpProfilerException e){
|
||||||
|
throw e; //NaN panic etc for debugging
|
||||||
} catch (Exception e){
|
} catch (Exception e){
|
||||||
if(e.getMessage().contains("Failed to allocate")){
|
if(e.getMessage().contains("Failed to allocate")){
|
||||||
//This is a memory exception - don't fallback to built-in implementation
|
//This is a memory exception - don't fallback to built-in implementation
|
||||||
|
@ -359,6 +362,8 @@ public class ConvolutionLayer extends BaseLayer<org.deeplearning4j.nn.conf.layer
|
||||||
try {
|
try {
|
||||||
ret = helper.preOutput(input, weights, bias, kernel, strides, pad, layerConf().getCudnnAlgoMode(),
|
ret = helper.preOutput(input, weights, bias, kernel, strides, pad, layerConf().getCudnnAlgoMode(),
|
||||||
layerConf().getCudnnFwdAlgo(), convolutionMode, dilation, workspaceMgr);
|
layerConf().getCudnnFwdAlgo(), convolutionMode, dilation, workspaceMgr);
|
||||||
|
} catch (ND4JOpProfilerException e){
|
||||||
|
throw e; //NaN panic etc for debugging
|
||||||
} catch (Exception e){
|
} catch (Exception e){
|
||||||
if(e.getMessage() != null && e.getMessage().contains("Failed to allocate")){
|
if(e.getMessage() != null && e.getMessage().contains("Failed to allocate")){
|
||||||
//This is a memory exception - don't fallback to built-in implementation
|
//This is a memory exception - don't fallback to built-in implementation
|
||||||
|
|
|
@ -32,6 +32,7 @@ import org.deeplearning4j.util.ConvolutionUtils;
|
||||||
import org.nd4j.linalg.api.buffer.DataType;
|
import org.nd4j.linalg.api.buffer.DataType;
|
||||||
import org.nd4j.linalg.api.ndarray.INDArray;
|
import org.nd4j.linalg.api.ndarray.INDArray;
|
||||||
import org.nd4j.linalg.api.ops.DynamicCustomOp;
|
import org.nd4j.linalg.api.ops.DynamicCustomOp;
|
||||||
|
import org.nd4j.linalg.exception.ND4JOpProfilerException;
|
||||||
import org.nd4j.linalg.factory.Nd4j;
|
import org.nd4j.linalg.factory.Nd4j;
|
||||||
import org.nd4j.linalg.primitives.Pair;
|
import org.nd4j.linalg.primitives.Pair;
|
||||||
import org.nd4j.util.OneTimeLogger;
|
import org.nd4j.util.OneTimeLogger;
|
||||||
|
@ -131,6 +132,8 @@ public class SubsamplingLayer extends AbstractLayer<org.deeplearning4j.nn.conf.l
|
||||||
try{
|
try{
|
||||||
ret = helper.backpropGradient(input, epsilon, kernel, strides, pad,
|
ret = helper.backpropGradient(input, epsilon, kernel, strides, pad,
|
||||||
layerConf().getPoolingType(), convolutionMode, dilation, workspaceMgr);
|
layerConf().getPoolingType(), convolutionMode, dilation, workspaceMgr);
|
||||||
|
} catch (ND4JOpProfilerException e){
|
||||||
|
throw e; //NaN panic etc for debugging
|
||||||
} catch (Exception e){
|
} catch (Exception e){
|
||||||
if(e.getMessage() != null && e.getMessage().contains("Failed to allocate")){
|
if(e.getMessage() != null && e.getMessage().contains("Failed to allocate")){
|
||||||
//This is a memory exception - don't fallback to built-in implementation
|
//This is a memory exception - don't fallback to built-in implementation
|
||||||
|
@ -256,6 +259,8 @@ public class SubsamplingLayer extends AbstractLayer<org.deeplearning4j.nn.conf.l
|
||||||
try {
|
try {
|
||||||
ret = helper.activate(input, training, kernel, strides, pad, layerConf().getPoolingType(),
|
ret = helper.activate(input, training, kernel, strides, pad, layerConf().getPoolingType(),
|
||||||
convolutionMode, dilation, workspaceMgr);
|
convolutionMode, dilation, workspaceMgr);
|
||||||
|
} catch (ND4JOpProfilerException e){
|
||||||
|
throw e; //NaN panic etc for debugging
|
||||||
} catch (Exception e){
|
} catch (Exception e){
|
||||||
if(layerConf().isCudnnAllowFallback()){
|
if(layerConf().isCudnnAllowFallback()){
|
||||||
helperCountFail++;
|
helperCountFail++;
|
||||||
|
|
|
@ -37,6 +37,7 @@ import org.nd4j.linalg.api.ops.impl.broadcast.BroadcastSubOp;
|
||||||
import org.nd4j.linalg.api.ops.impl.transforms.pairwise.arithmetic.OldDivOp;
|
import org.nd4j.linalg.api.ops.impl.transforms.pairwise.arithmetic.OldDivOp;
|
||||||
import org.nd4j.linalg.api.ops.impl.transforms.pairwise.arithmetic.OldSubOp;
|
import org.nd4j.linalg.api.ops.impl.transforms.pairwise.arithmetic.OldSubOp;
|
||||||
import org.nd4j.linalg.api.shape.Shape;
|
import org.nd4j.linalg.api.shape.Shape;
|
||||||
|
import org.nd4j.linalg.exception.ND4JOpProfilerException;
|
||||||
import org.nd4j.linalg.factory.Nd4j;
|
import org.nd4j.linalg.factory.Nd4j;
|
||||||
import org.nd4j.linalg.ops.transforms.Transforms;
|
import org.nd4j.linalg.ops.transforms.Transforms;
|
||||||
import org.nd4j.linalg.primitives.Pair;
|
import org.nd4j.linalg.primitives.Pair;
|
||||||
|
@ -156,6 +157,8 @@ public class BatchNormalization extends BaseLayer<org.deeplearning4j.nn.conf.lay
|
||||||
try {
|
try {
|
||||||
ret = helper.backpropGradient(in, eps, ArrayUtil.toInts(shape), gamma, dGammaView, dBetaView,
|
ret = helper.backpropGradient(in, eps, ArrayUtil.toInts(shape), gamma, dGammaView, dBetaView,
|
||||||
layerConf.getEps(), workspaceMgr);
|
layerConf.getEps(), workspaceMgr);
|
||||||
|
} catch (ND4JOpProfilerException e){
|
||||||
|
throw e; //NaN panic etc for debugging
|
||||||
} catch (Throwable t){
|
} catch (Throwable t){
|
||||||
if(t.getMessage().contains("Failed to allocate")){
|
if(t.getMessage().contains("Failed to allocate")){
|
||||||
//This is a memory exception - don't fallback to built-in implementation
|
//This is a memory exception - don't fallback to built-in implementation
|
||||||
|
@ -447,6 +450,8 @@ public class BatchNormalization extends BaseLayer<org.deeplearning4j.nn.conf.lay
|
||||||
|
|
||||||
ret = helper.preOutput(in, training == TrainingMode.TRAIN, ArrayUtil.toInts(shape), gamma, beta, globalMeanView,
|
ret = helper.preOutput(in, training == TrainingMode.TRAIN, ArrayUtil.toInts(shape), gamma, beta, globalMeanView,
|
||||||
globalVarView, decay, layerConf.getEps(), workspaceMgr);
|
globalVarView, decay, layerConf.getEps(), workspaceMgr);
|
||||||
|
} catch (ND4JOpProfilerException e){
|
||||||
|
throw e; //NaN panic etc for debugging
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
if(t.getMessage().contains("Failed to allocate")){
|
if(t.getMessage().contains("Failed to allocate")){
|
||||||
//This is a memory exception - don't fallback to built-in implementation
|
//This is a memory exception - don't fallback to built-in implementation
|
||||||
|
|
|
@ -27,6 +27,7 @@ import org.deeplearning4j.nn.layers.mkldnn.MKLDNNLocalResponseNormalizationHelpe
|
||||||
import org.nd4j.linalg.api.buffer.DataType;
|
import org.nd4j.linalg.api.buffer.DataType;
|
||||||
import org.nd4j.linalg.api.ndarray.INDArray;
|
import org.nd4j.linalg.api.ndarray.INDArray;
|
||||||
import org.nd4j.linalg.api.ops.impl.transforms.pairwise.arithmetic.OldMulOp;
|
import org.nd4j.linalg.api.ops.impl.transforms.pairwise.arithmetic.OldMulOp;
|
||||||
|
import org.nd4j.linalg.exception.ND4JOpProfilerException;
|
||||||
import org.nd4j.linalg.factory.Nd4j;
|
import org.nd4j.linalg.factory.Nd4j;
|
||||||
import org.nd4j.linalg.indexing.INDArrayIndex;
|
import org.nd4j.linalg.indexing.INDArrayIndex;
|
||||||
import org.nd4j.linalg.indexing.NDArrayIndex;
|
import org.nd4j.linalg.indexing.NDArrayIndex;
|
||||||
|
@ -141,6 +142,8 @@ public class LocalResponseNormalization
|
||||||
Pair<Gradient, INDArray> ret = null;
|
Pair<Gradient, INDArray> ret = null;
|
||||||
try {
|
try {
|
||||||
ret = helper.backpropGradient(input, epsilon, k, n, alpha, beta, workspaceMgr);
|
ret = helper.backpropGradient(input, epsilon, k, n, alpha, beta, workspaceMgr);
|
||||||
|
} catch (ND4JOpProfilerException e){
|
||||||
|
throw e; //NaN panic etc for debugging
|
||||||
} catch (Throwable t){
|
} catch (Throwable t){
|
||||||
if(t.getMessage().contains("Failed to allocate")){
|
if(t.getMessage().contains("Failed to allocate")){
|
||||||
//This is a memory exception - don't fallback to built-in implementation
|
//This is a memory exception - don't fallback to built-in implementation
|
||||||
|
@ -206,6 +209,8 @@ public class LocalResponseNormalization
|
||||||
INDArray activations = null;
|
INDArray activations = null;
|
||||||
try {
|
try {
|
||||||
activations = helper.activate(input, training, k, n, alpha, beta, workspaceMgr);
|
activations = helper.activate(input, training, k, n, alpha, beta, workspaceMgr);
|
||||||
|
} catch (ND4JOpProfilerException e){
|
||||||
|
throw e; //NaN panic etc for debugging
|
||||||
} catch (Throwable t){
|
} catch (Throwable t){
|
||||||
if(t.getMessage().contains("Failed to allocate")){
|
if(t.getMessage().contains("Failed to allocate")){
|
||||||
//This is a memory exception - don't fallback to built-in implementation
|
//This is a memory exception - don't fallback to built-in implementation
|
||||||
|
|
|
@ -0,0 +1,257 @@
|
||||||
|
package org.nd4j.autodiff.listeners.debugging;
|
||||||
|
|
||||||
|
import org.nd4j.autodiff.functions.DifferentialFunction;
|
||||||
|
import org.nd4j.autodiff.listeners.At;
|
||||||
|
import org.nd4j.autodiff.listeners.BaseListener;
|
||||||
|
import org.nd4j.autodiff.samediff.SameDiff;
|
||||||
|
import org.nd4j.autodiff.samediff.internal.SameDiffOp;
|
||||||
|
import org.nd4j.linalg.api.buffer.DataType;
|
||||||
|
import org.nd4j.linalg.api.ndarray.INDArray;
|
||||||
|
import org.nd4j.linalg.api.ops.CustomOp;
|
||||||
|
import org.nd4j.linalg.api.ops.Op;
|
||||||
|
import org.nd4j.linalg.api.ops.ScalarOp;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A listener that logs operation execution for debugging purposes.
|
||||||
|
* 3 modes are supported:<br><br>
|
||||||
|
* <b>OPS_ONLY</b>: Only the operations names are printed. For example:<br>
|
||||||
|
* {@code (iter=0,epoch=0,op=1) org.nd4j.linalg.api.ops.impl.transforms.pairwise.arithmetic.AddOp}<br>
|
||||||
|
* <b>SHAPES_ONLY</b>: Print the operation class, shape info (for inputs/output arrays) as well as any arguments - iArgs, bArgs, tArgs. For example:<br>
|
||||||
|
* <pre>{@code
|
||||||
|
* (iter=1,epoch=0,op=3) org.nd4j.linalg.api.ops.impl.loss.LogLoss
|
||||||
|
* iArgs=[3]
|
||||||
|
* tArgs=[1.0E-7]
|
||||||
|
* Input[0]=Rank: 2, DataType: FLOAT, Offset: 0, Order: c, Shape: [1,2], Stride: [1,1]
|
||||||
|
* Input[1]=Rank: 0, DataType: FLOAT, Offset: 0, Order: c, Shape: [], Stride: []
|
||||||
|
* Input[2]=Rank: 2, DataType: FLOAT, Offset: 0, Order: c, Shape: [1,2], Stride: [1,1]
|
||||||
|
* Outputs[0]=Rank: 0, DataType: FLOAT, Offset: 0, Order: c, Shape: [], Stride: []
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
* <b>REPRODUCE</b>: Print runnable Java code that should reproduce that op execution (other than perhaps exact input/output strides). For example:<br>
|
||||||
|
* <pre>{@code
|
||||||
|
* (iter=2,epoch=0,op=1) org.nd4j.linalg.api.ops.impl.transforms.pairwise.arithmetic.AddOp
|
||||||
|
* DynamicCustomOp op = new org.nd4j.linalg.api.ops.impl.transforms.pairwise.arithmetic.AddOp();
|
||||||
|
* INDArray[] inputs = new INDArray[2];
|
||||||
|
* inputs[0] = Nd4j.createFromArray(1.5253239f, 0.8733858f).reshape(1, 2);
|
||||||
|
* inputs[1] = Nd4j.createFromArray(0.483428f, 0.86025196f).reshape(1, 2);
|
||||||
|
* op.addInputArgument(inputs);
|
||||||
|
* INDArray[] outputs = new INDArray[1];
|
||||||
|
* outputs[0] = Nd4j.createFromArray(2.012087f, 1.7303026f).reshape(1, 2);
|
||||||
|
* op.addOutputArgument(outputs);
|
||||||
|
* Nd4j.exec(op);
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author Alex Black
|
||||||
|
*/
|
||||||
|
public class ExecDebuggingListener extends BaseListener {
|
||||||
|
|
||||||
|
public enum PrintMode {OPS_ONLY, SHAPES_ONLY, REPRODUCE}
|
||||||
|
|
||||||
|
private final PrintMode printMode;
|
||||||
|
private final int maxIterations;
|
||||||
|
private final boolean logIter;
|
||||||
|
|
||||||
|
private long printIterations = 0;
|
||||||
|
private int lastIter = -1;
|
||||||
|
private int stepThisIter = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param printMode Print mode, see {@link PrintMode}
|
||||||
|
* @param maxIterations Maximum number of iterations to print. <= 0 for "all iterations"
|
||||||
|
* @param logIter If true: prefix iteration/epoch, such as "(iter=1,epoch=0,op=3)" to the output
|
||||||
|
*/
|
||||||
|
public ExecDebuggingListener(PrintMode printMode, int maxIterations, boolean logIter){
|
||||||
|
this.printMode = printMode;
|
||||||
|
this.maxIterations = maxIterations;
|
||||||
|
this.logIter = logIter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void preOpExecution(SameDiff sd, At at, boolean training, SameDiffOp op) {
|
||||||
|
if(lastIter != at.iteration()){
|
||||||
|
lastIter = at.iteration();
|
||||||
|
stepThisIter = 0;
|
||||||
|
printIterations++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(maxIterations > 0 && printIterations > maxIterations){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
if(logIter){
|
||||||
|
sb.append("(iter=").append(at.iteration())
|
||||||
|
.append(",epoch=").append(at.epoch())
|
||||||
|
.append(",");
|
||||||
|
}
|
||||||
|
sb.append("op=").append(stepThisIter++)
|
||||||
|
.append(logIter ? ") " : " - ");
|
||||||
|
|
||||||
|
DifferentialFunction df = op.getOp();
|
||||||
|
sb.append(op.getOp().getClass().getName());
|
||||||
|
CustomOp co = df instanceof CustomOp ? (CustomOp) df : null;
|
||||||
|
Op lOp = df instanceof Op ? (Op) df : null;
|
||||||
|
if(printMode == PrintMode.OPS_ONLY){
|
||||||
|
sb.append("\n");
|
||||||
|
} else if(printMode == PrintMode.SHAPES_ONLY){
|
||||||
|
if(co != null){
|
||||||
|
if(co.iArgs() != null && co.iArgs().length > 0) {
|
||||||
|
sb.append("\n\tiArgs=").append(Arrays.toString(co.iArgs()));
|
||||||
|
}
|
||||||
|
if(co.bArgs() != null && co.bArgs().length > 0) {
|
||||||
|
sb.append("\n\tbArgs=").append(Arrays.toString(co.bArgs()));
|
||||||
|
}
|
||||||
|
if(co.tArgs() != null && co.tArgs().length > 0) {
|
||||||
|
sb.append("\n\ttArgs=").append(Arrays.toString(co.tArgs()));
|
||||||
|
}
|
||||||
|
INDArray[] inputs = co.inputArguments();
|
||||||
|
INDArray[] outputs = co.outputArguments();
|
||||||
|
if(inputs != null ) {
|
||||||
|
for (int i = 0; i < inputs.length; i++) {
|
||||||
|
sb.append("\n\tInput[").append(i).append("]=").append(inputs[i].shapeInfoToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(outputs != null ) {
|
||||||
|
for (int i = 0; i < outputs.length; i++) {
|
||||||
|
sb.append("\n\tOutputs[").append(i).append("]=").append(outputs[i].shapeInfoToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(lOp.x() != null) {
|
||||||
|
sb.append("\n\tx: ").append(lOp.x().shapeInfoToString());
|
||||||
|
}
|
||||||
|
if(lOp.y() != null) {
|
||||||
|
sb.append("\n\ty: ").append(lOp.y().shapeInfoToString());
|
||||||
|
}
|
||||||
|
if(lOp.z() != null) {
|
||||||
|
sb.append("\n\tz: ").append(lOp.z().shapeInfoToString());
|
||||||
|
}
|
||||||
|
if(lOp instanceof ScalarOp){
|
||||||
|
INDArray scalar = ((ScalarOp)lOp).scalar();
|
||||||
|
if(scalar != null){
|
||||||
|
sb.append("\n\tscalar: ").append(scalar.shapeInfoToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sb.append("\n");
|
||||||
|
} else if(printMode == PrintMode.REPRODUCE){
|
||||||
|
sb.append("\n");
|
||||||
|
if(co != null){
|
||||||
|
sb.append("DynamicCustomOp op = new ").append(co.getClass().getName()).append("();\n");
|
||||||
|
if(co.iArgs() != null && co.iArgs().length > 0 ){
|
||||||
|
sb.append("op.addIArgument(").append(Arrays.toString(co.iArgs()).replaceAll("[\\[\\]]", "")).append(");\n");
|
||||||
|
}
|
||||||
|
if(co.bArgs() != null && co.bArgs().length > 0 ){
|
||||||
|
sb.append("op.addBArgument(").append(Arrays.toString(co.bArgs()).replaceAll("[\\[\\]]", "")).append(");\n");
|
||||||
|
}
|
||||||
|
if(co.tArgs() != null && co.tArgs().length > 0 ){
|
||||||
|
sb.append("op.addTArgument(").append(Arrays.toString(co.tArgs()).replaceAll("[\\[\\]]", "")).append(");\n");
|
||||||
|
}
|
||||||
|
INDArray[] inputs = co.inputArguments();
|
||||||
|
INDArray[] outputs = co.outputArguments();
|
||||||
|
if(inputs != null ) {
|
||||||
|
sb.append("INDArray[] inputs = new INDArray[").append(inputs.length).append("];\n");
|
||||||
|
for (int i = 0; i < inputs.length; i++) {
|
||||||
|
sb.append("inputs[").append(i).append("] = ");
|
||||||
|
sb.append(createString(inputs[i]))
|
||||||
|
.append(";\n");
|
||||||
|
}
|
||||||
|
sb.append("op.addInputArgument(inputs);\n");
|
||||||
|
}
|
||||||
|
if(outputs != null ) {
|
||||||
|
sb.append("INDArray[] outputs = new INDArray[").append(outputs.length).append("];\n");
|
||||||
|
for (int i = 0; i < outputs.length; i++) {
|
||||||
|
sb.append("outputs[").append(i).append("] = ");
|
||||||
|
sb.append(createString(outputs[i]))
|
||||||
|
.append(";\n");
|
||||||
|
}
|
||||||
|
sb.append("op.addOutputArgument(outputs);\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sb.append("Op op = new ").append(op.getClass().getName()).append("();\n");
|
||||||
|
if(lOp.x() != null) {
|
||||||
|
sb.append("op.setX(").append(createString(lOp.x())).append(");\n");
|
||||||
|
}
|
||||||
|
if(lOp.y() != null) {
|
||||||
|
sb.append("op.setY(").append(createString(lOp.y())).append(");\n");
|
||||||
|
}
|
||||||
|
if(lOp.z() != null) {
|
||||||
|
sb.append("op.setZ").append(createString(lOp.z())).append(");\n");
|
||||||
|
}
|
||||||
|
if(lOp instanceof ScalarOp){
|
||||||
|
INDArray scalar = ((ScalarOp)lOp).scalar();
|
||||||
|
if(scalar != null){
|
||||||
|
sb.append("((ScalarOp)op).setScalar(").append(createString(scalar)).append(");\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sb.append("Nd4j.exec(op);\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.print(sb.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String createString(INDArray arr){
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
if(arr.isEmpty()){
|
||||||
|
sb.append("Nd4j.empty(DataType.").append(arr.dataType()).append(");");
|
||||||
|
} else {
|
||||||
|
sb.append("Nd4j.createFromArray(");
|
||||||
|
|
||||||
|
DataType dt = arr.dataType();
|
||||||
|
switch (dt){
|
||||||
|
case DOUBLE:
|
||||||
|
double[] dArr = arr.dup().data().asDouble();
|
||||||
|
sb.append(Arrays.toString(dArr).replaceAll("[\\[\\]]", ""));
|
||||||
|
break;
|
||||||
|
case FLOAT:
|
||||||
|
case HALF:
|
||||||
|
case BFLOAT16:
|
||||||
|
float[] fArr = arr.dup().data().asFloat();
|
||||||
|
sb.append(Arrays.toString(fArr)
|
||||||
|
.replaceAll(",", "f,")
|
||||||
|
.replaceAll("]", "f")
|
||||||
|
.replaceAll("[\\[\\]]", ""));
|
||||||
|
break;
|
||||||
|
case LONG:
|
||||||
|
case UINT32:
|
||||||
|
case UINT64:
|
||||||
|
long[] lArr = arr.dup().data().asLong();
|
||||||
|
sb.append(Arrays.toString(lArr)
|
||||||
|
.replaceAll(",", "L,")
|
||||||
|
.replaceAll("]", "L")
|
||||||
|
.replaceAll("[\\[\\]]", ""));
|
||||||
|
break;
|
||||||
|
case INT:
|
||||||
|
case SHORT:
|
||||||
|
case UBYTE:
|
||||||
|
case BYTE:
|
||||||
|
case UINT16:
|
||||||
|
case BOOL:
|
||||||
|
int[] iArr = arr.dup().data().asInt();
|
||||||
|
sb.append(Arrays.toString(iArr).replaceAll("[\\[\\]]", ""));
|
||||||
|
break;
|
||||||
|
case UTF8:
|
||||||
|
break;
|
||||||
|
case COMPRESSED:
|
||||||
|
case UNKNOWN:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.append(").reshape(").append(Arrays.toString(arr.shape()).replaceAll("[\\[\\]]", ""))
|
||||||
|
.append(")");
|
||||||
|
|
||||||
|
if(dt == DataType.HALF || dt == DataType.BFLOAT16 || dt == DataType.UINT32 || dt == DataType.UINT64 ||
|
||||||
|
dt == DataType.SHORT || dt == DataType.UBYTE || dt == DataType.BYTE || dt == DataType.UINT16 || dt == DataType.BOOL){
|
||||||
|
sb.append(".cast(DataType.").append(arr.dataType()).append(")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -235,7 +235,18 @@ public class DifferentialFunctionClassHolder {
|
||||||
//log.debug("Missing " + set.size() + " ops!");
|
//log.debug("Missing " + set.size() + " ops!");
|
||||||
|
|
||||||
countTotalTfOps = tensorflowOpDescriptors.size();
|
countTotalTfOps = tensorflowOpDescriptors.size();
|
||||||
countTotalMappedOps = nodeConverters.size();
|
|
||||||
|
//Work out total number of TF ops mapped
|
||||||
|
Set<String> tfMappedOps = new HashSet<>();
|
||||||
|
for(DifferentialFunction df : nodeConverters.values()){
|
||||||
|
try{
|
||||||
|
String[] tfNames = df.tensorflowNames();
|
||||||
|
Collections.addAll(tfMappedOps, tfNames);
|
||||||
|
} catch (NoOpNameFoundException e){
|
||||||
|
//Ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
countTotalMappedOps = tfMappedOps.size();
|
||||||
|
|
||||||
//Get custom ops - map from hash to class
|
//Get custom ops - map from hash to class
|
||||||
Map<String,CustomOpDescriptor> descriptorMap = Nd4j.getExecutioner().getCustomOperations();
|
Map<String,CustomOpDescriptor> descriptorMap = Nd4j.getExecutioner().getCustomOperations();
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
package org.nd4j.autodiff.samediff.listeners;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.nd4j.autodiff.listeners.debugging.ExecDebuggingListener;
|
||||||
|
import org.nd4j.autodiff.samediff.SDVariable;
|
||||||
|
import org.nd4j.autodiff.samediff.SameDiff;
|
||||||
|
import org.nd4j.autodiff.samediff.TrainingConfig;
|
||||||
|
import org.nd4j.linalg.BaseNd4jTest;
|
||||||
|
import org.nd4j.linalg.api.buffer.DataType;
|
||||||
|
import org.nd4j.linalg.api.ndarray.INDArray;
|
||||||
|
import org.nd4j.linalg.dataset.DataSet;
|
||||||
|
import org.nd4j.linalg.factory.Nd4j;
|
||||||
|
import org.nd4j.linalg.factory.Nd4jBackend;
|
||||||
|
import org.nd4j.linalg.learning.config.Adam;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class ExecDebuggingListenerTest extends BaseNd4jTest {
|
||||||
|
|
||||||
|
public ExecDebuggingListenerTest(Nd4jBackend backend) {
|
||||||
|
super(backend);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExecDebugListener(){
|
||||||
|
|
||||||
|
SameDiff sd = SameDiff.create();
|
||||||
|
SDVariable in = sd.placeHolder("in", DataType.FLOAT, -1, 3);
|
||||||
|
SDVariable label = sd.placeHolder("label", DataType.FLOAT, 1, 2);
|
||||||
|
SDVariable w = sd.var("w", Nd4j.rand(DataType.FLOAT, 3, 2));
|
||||||
|
SDVariable b = sd.var("b", Nd4j.rand(DataType.FLOAT, 1, 2));
|
||||||
|
SDVariable sm = sd.nn.softmax("softmax", in.mmul(w).add(b));
|
||||||
|
SDVariable loss = sd.loss.logLoss("loss", label, sm);
|
||||||
|
|
||||||
|
INDArray i = Nd4j.rand(DataType.FLOAT, 1, 3);
|
||||||
|
INDArray l = Nd4j.rand(DataType.FLOAT, 1, 2);
|
||||||
|
|
||||||
|
sd.setTrainingConfig(TrainingConfig.builder()
|
||||||
|
.dataSetFeatureMapping("in")
|
||||||
|
.dataSetLabelMapping("label")
|
||||||
|
.updater(new Adam(0.001))
|
||||||
|
.build());
|
||||||
|
|
||||||
|
for(ExecDebuggingListener.PrintMode pm : ExecDebuggingListener.PrintMode.values()){
|
||||||
|
sd.setListeners(new ExecDebuggingListener(pm, -1, true));
|
||||||
|
// sd.output(m, "softmax");
|
||||||
|
sd.fit(new DataSet(i, l));
|
||||||
|
|
||||||
|
System.out.println("\n\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public char ordering() {
|
||||||
|
return 'c';
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue