REQUIRE_TRUE(input->rankOf()==4,0," SCONV2D OP: rank of input array must be equal to 4, but got %i instead !",input->rankOf());
REQUIRE_TRUE(weightsDepth->rankOf()==4,0," SCONV2D OP: rank of weightsDepth array must be equal to 4, but got %i instead !",weightsDepth->rankOf());
if(weightsPoint)
REQUIRE_TRUE(weightsPoint->rankOf()==4,0," SCONV2D OP: rank of weightsPoint array must be equal to 4, but got %i instead !",weightsPoint->rankOf());
if(bias)
REQUIRE_TRUE(bias->rankOf()==1||bias->rankOf()==2,0," SCONV2D OP: rank of biases array must be equal to 1 or 2, but got %i instead !",bias->rankOf());;
Nd4jLong*biasShapeInfo=nullptr;// [oC], oC = iC*mC if weightsPoint=nullptr
if(block.width()==3)
if(inputShape->at(2)[0]==4)
weightsPShapeInfo=inputShape->at(2);
else
biasShapeInfo=inputShape->at(2);
elseif(block.width()==4){
weightsPShapeInfo=inputShape->at(2);
biasShapeInfo=inputShape->at(3);
}
constintrank=4;
REQUIRE_TRUE(inputShapeInfo[0]==rank,0,"SCONV2D OP: rank of input array must be equal to %i, but got %i instead !",rank,inputShapeInfo[0]);
REQUIRE_TRUE(weightsDShapeInfo[0]==rank,0,"SCONV2D OP: rank of weightsDepth array must be equal to %i, but got %i instead !",rank,weightsDShapeInfo[0]);
if(weightsPShapeInfo)
REQUIRE_TRUE(weightsPShapeInfo[0]==rank,0,"SCONV2D OP: rank of weightsPoint array must be equal to %i, but got %i instead !",rank,weightsPShapeInfo[0]);
if(biasShapeInfo)
REQUIRE_TRUE(biasShapeInfo[0]<=2,0,"SCONV2D OP: rank of biases array must be <= 2, but got %i instead !",biasShapeInfo[0]);;
REQUIRE_TRUE(expectedWeightsPShape==ShapeUtils::shapeAsString(weightsPShapeInfo),0,"SCONV2D OP: wrong shape of point array, expected is %s, but got %s instead !",expectedWeightsPShape.c_str(),ShapeUtils::shapeAsString(weightsPShapeInfo).c_str());
}
if(biasShapeInfo)
REQUIRE_TRUE(biasShapeInfo[0]<=2&&oC==shape::length(biasShapeInfo),0,"SCONV2D OP: wrong shape of array with biases, expected rank, length: <=2, %i, but got %i, %i instead !",oC,biasShapeInfo[0],shape::length(biasShapeInfo));
REQUIRE_TRUE(input->rankOf()==4,0," SCONV2D_BP OP: rank of input array must be equal to 4, but got %i instead !",input->rankOf());
REQUIRE_TRUE(gradO->rankOf()==4,0," SCONV2D_BP OP: rank of output gradients (next epsilon) array must be equal to 4, but got %i instead !",gradO->rankOf());
REQUIRE_TRUE(weightsDepth->rankOf()==4,0," SCONV2D_BP OP: rank of weightsDepth array must be equal to 4 !, but got %i instead !",weightsDepth->rankOf());
if(weightsPoint){
REQUIRE_TRUE(weightsPoint->rankOf()==4,0," SCONV2D_BP OP: rank of weightsPoint array must be equal to 4, but got %i instead !",weightsPoint->rankOf());
REQUIRE_TRUE(gradWP->rankOf()==4,0," SCONV2D_BP OP: rank of weightsPoint gradients array must be equal to 4, but got %i instead !",gradWP->rankOf());
}
if(bias){
REQUIRE_TRUE(bias->rankOf()==1||bias->rankOf()==2,0," SCONV2D_BP OP: rank of biases array must be equal to 1 or 2, but got %i instead !",bias->rankOf());
REQUIRE_TRUE(gradB->rankOf()==1||gradB->rankOf()==2,0," SCONV2D_BP OP: rank of biases gradientsarray must be equal to 1 or 2, but got %i instead !",gradB->rankOf());
REQUIRE_TRUE(expectedWeightsPShape==ShapeUtils::shapeAsString(weightsPoint),0," SCONV2D_BP OP: wrong shape of weightsPoint array, expected is %s, but got %s instead !",expectedWeightsPShape.c_str(),ShapeUtils::shapeAsString(weightsPoint).c_str());
REQUIRE_TRUE(expectedWeightsPShape==ShapeUtils::shapeAsString(gradWP),0," SCONV2D_BP OP: wrong shape of gradWP array, expected is %s, but got %s instead !",expectedWeightsPShape.c_str(),ShapeUtils::shapeAsString(gradWP).c_str());
}
if(bias){
REQUIRE_TRUE(oC==bias->lengthOf(),0," SCONV2D_BP OP: length of bias array must be equal to outChannels, but got %i instead",bias->lengthOf());
REQUIRE_TRUE(oC==gradB->lengthOf(),0," SCONV2D_BP OP: length of biases gradients array must be equal to outChannels, but got %i instead",gradB->lengthOf());
}
// if (iC == 1) {
// nd4j_debug(" SCONV2D_BP OP: for input_channels=1 this op is equivalent to standard conv2d_bp \n","");
// nd4j::ops::conv2d_bp op;
// return op.execute(&block);
// }
// ----- if weightsPoint is present, perform pointwise backprop first and calculate gradWP at this step ----- //
ConvolutionUtils::conv2dBP(block,resultFF,weightsPoint,bias,gradO,gradIDepth,gradWP,gradB,1,1,1,1,0,0,1,1,isSameMode,isNCHW);// in this case oH=iH and oW=iW
Nd4jLong*biasShapeInfo=nullptr;// [oC], oC = iC*mC if weightsPoint=nullptr
if(block.width()==4){
if(inputShape->at(3)[0]==4)
weightsPShapeInfo=inputShape->at(3);
else
biasShapeInfo=inputShape->at(3);
}
elseif(block.width()==5){
weightsPShapeInfo=inputShape->at(3);
biasShapeInfo=inputShape->at(4);
}
constintrank=4;
REQUIRE_TRUE(inputShapeInfo[0]==rank,0," SCONV2D_BP OP: rank of input array must be equal to %i, but got %i instead !",rank,inputShapeInfo[0]);
REQUIRE_TRUE(gradOShapeInfo[0]==rank,0," SCONV2D_BP OP: rank of output gradients (next epsilon) array must be equal to %i, but got %i instead !",rank,gradOShapeInfo[0]);
REQUIRE_TRUE(weightsDShapeInfo[0]==rank,0," SCONV2D_BP OP: rank of weightsDepth array must be equal to %i, but got %i instead !",rank,weightsDShapeInfo[0]);
if(weightsPShapeInfo)
REQUIRE_TRUE(weightsPShapeInfo[0]==rank,0," SCONV2D_BP OP: rank of weightsPoint array must be equal to %i, but got %i instead !",rank,weightsPShapeInfo[0]);
if(biasShapeInfo)
REQUIRE_TRUE(biasShapeInfo[0]==1||biasShapeInfo[0]==2,0," SCONV2D_BP OP: rank of biases array must be 1 or 2, but got %i instead !",biasShapeInfo[0]);;
REQUIRE_TRUE(expectedWeightsPShape==ShapeUtils::shapeAsString(weightsPShapeInfo),0,"SCONV2D_BP OP: wrong shape of point array, expected is %s, but got %s instead !",expectedWeightsPShape.c_str(),ShapeUtils::shapeAsString(weightsPShapeInfo).c_str());
}
if(biasShapeInfo)
REQUIRE_TRUE((biasShapeInfo[0]==1||biasShapeInfo[0]==2)&&oC==shape::length(biasShapeInfo),0,"SCONV2D_BP OP: wrong shape of array with biases, expected rank, length: <=2, %i, but got %i, %i instead !",oC,biasShapeInfo[0],shape::length(biasShapeInfo));