Skip to content

Commit

Permalink
(some reordering of methods in ReshapingNodes.h--CopyTo, Load, Save, …
Browse files Browse the repository at this point in the history
…forward, backward, Validate, no code change)
  • Loading branch information
frankseide committed Jan 27, 2016
1 parent 4fe5fd7 commit 37fb8df
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 136 deletions.
2 changes: 1 addition & 1 deletion Source/ComputationNetworkLib/ComputationNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ struct /*interface*/ IComputationNode
virtual void BackpropTo(const size_t inputIndex, const FrameRange&) = 0; // backprop gradient into one of the inputs
virtual void EndBackprop() = 0; // called after last iteration step of ComputeGradient()

// --- these are meant to be overridden by ControlFlowNodes
// --- this is meant to be overridden by ControlFlowNodes

virtual void Backprop(const FrameRange& fr, bool childrenInThisLoop, bool childrenInOuterLoop) = 0;

Expand Down
228 changes: 93 additions & 135 deletions Source/ComputationNetworkLib/ReshapingNodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,21 +209,6 @@ class ReconcileMBLayoutNode : public ComputationNode<ElemType>, public NumInputs
{
}

virtual void /*ComputationNode::*/ BackpropTo(const size_t /*inputIndex*/, const FrameRange& fr) override
{
Input(0)->GradientFor(fr.WithLayout(Input(0)->GetMBLayout())) += GradientFor(fr);
// TODO: Once we do in-place, the above must include a copy-to-self check (pay special attention to adding vs. copying).
}

virtual bool OutputUsedInComputingInputNodesGradients() const override
{
return false;
}
virtual bool InputUsedInComputingInputNodesGradients(size_t /*childIndex*/) const override
{
return false;
}

virtual void /*ComputationNode::*/ ForwardProp(const FrameRange& fr) override
{
// enforce compatibility of 'dataInput' with 'layoutInput'
Expand All @@ -239,6 +224,15 @@ class ReconcileMBLayoutNode : public ComputationNode<ElemType>, public NumInputs
// TODO: Once we do in-place, the above must include a copy-to-self check (either here or inside the matrix lib).
}

virtual void /*ComputationNode::*/ BackpropTo(const size_t /*inputIndex*/, const FrameRange& fr) override
{
Input(0)->GradientFor(fr.WithLayout(Input(0)->GetMBLayout())) += GradientFor(fr);
// TODO: Once we do in-place, the above must include a copy-to-self check (pay special attention to adding vs. copying).
}

virtual bool OutputUsedInComputingInputNodesGradients() const override { return false; }
virtual bool InputUsedInComputingInputNodesGradients(size_t /*childIndex*/) const override { return false; }

virtual void /*ComputationNodeBase::*/ Validate(bool isFinalValidationPass) override
{
Base::Validate(isFinalValidationPass);
Expand All @@ -256,8 +250,7 @@ template class ReconcileMBLayoutNode<double>;

// -----------------------------------------------------------------------
// RowSliceNode (input)
// this node extracts part of the input by rows as the output
// it has to be continuous segments of rows since each column is treated as one sample
// This node extracts a slice of the first tensor dimension (row).
// -----------------------------------------------------------------------

template <class ElemType>
Expand All @@ -277,6 +270,7 @@ class RowSliceNode : public ComputationNode<ElemType>, public NumInputs<1>
m_sliceHeight(numRows)
{
}

RowSliceNode(const ScriptableObjects::IConfigRecordPtr configp)
: RowSliceNode(configp->Get(L"deviceId"), L"<placeholder>", configp->Get(L"startIndex"), configp->Get(L"numRows"))
{
Expand All @@ -292,42 +286,30 @@ class RowSliceNode : public ComputationNode<ElemType>, public NumInputs<1>
node->m_sliceHeight = m_sliceHeight;
}

virtual void Save(File& fstream) const override
{
Base::Save(fstream);
fstream << m_startIndex << m_sliceHeight;
}

virtual void Load(File& fstream, size_t modelVersion) override
{
Base::Load(fstream, modelVersion);
fstream >> m_startIndex >> m_sliceHeight;
}

virtual void /*ComputationNode::*/ BackpropTo(const size_t /*inputIndex*/, const FrameRange& fr) override
virtual void Save(File& fstream) const override
{
Input(0)->GradientFor(fr).AddToRowSliceValuesOf(GradientFor(fr), m_startIndex, m_sliceHeight);
Base::Save(fstream);
fstream << m_startIndex << m_sliceHeight;
}

virtual bool OutputUsedInComputingInputNodesGradients() const override
virtual void /*ComputationNode::*/ ForwardProp(const FrameRange& fr) override
{
// The RowSliceNode does not require its output value for computing
// the gradients of its input nodes
return false;
ValueFor(fr).AssignRowSliceValuesOf(Input(0)->ValueFor(fr), m_startIndex, m_sliceHeight);
}

virtual bool InputUsedInComputingInputNodesGradients(size_t childIndex) const override
virtual void /*ComputationNode::*/ BackpropTo(const size_t /*inputIndex*/, const FrameRange& fr) override
{
// The RowSliceNode does not require any of it's input's values for computing
// the gradients of its input nodes
UNREFERENCED_PARAMETER(childIndex);
return false;
Input(0)->GradientFor(fr).AddToRowSliceValuesOf(GradientFor(fr), m_startIndex, m_sliceHeight);
}

virtual void /*ComputationNode::*/ ForwardProp(const FrameRange& fr) override
{
ValueFor(fr).AssignRowSliceValuesOf(Input(0)->ValueFor(fr), m_startIndex, m_sliceHeight);
}
virtual bool OutputUsedInComputingInputNodesGradients() const override { return false; }
virtual bool InputUsedInComputingInputNodesGradients(size_t /*childIndex*/) const override { return false; }

virtual void /*ComputationNodeBase::*/ Validate(bool isFinalValidationPass) override
{
Expand Down Expand Up @@ -604,24 +586,6 @@ class DiagonalNode : public ComputationNodeNonLooping<ElemType>, public NumInput
{
}

virtual void Validate(bool isFinalValidationPass) override
{
Base::Validate(isFinalValidationPass);
m_pMBLayout = nullptr;

if (isFinalValidationPass && Input(0)->HasMBLayout())
InvalidArgument("%ls %ls operation cannot operate on minibatch data (which have a layout)", NodeName().c_str(), OperationName().c_str());

size_t dim = Input(0)->GetAsMatrixNumCols();
if (isFinalValidationPass && dim != Input(0)->GetAsMatrixNumRows())
InvalidArgument("%ls %ls operation requires a square matrix as its input.", NodeName().c_str(), OperationName().c_str());

if (Input(0)->HasSampleLayout())
fprintf(stderr, "WARNING: Diagonal operation cannot inherit image size information from its child. Image size info is lost.\n");

SetDims(TensorShape(1, dim), false);
}

virtual void /*ComputationNodeNonLooping::*/ ForwardPropNonLooping() override
{
Input(0)->ValueAsMatrix().AssignDiagonalValuesTo(ValueAsMatrix()); // TODO: use tensor lib; this is a stride operation
Expand All @@ -646,19 +610,25 @@ class DiagonalNode : public ComputationNodeNonLooping<ElemType>, public NumInput
inputGradientValues.SetDiagonalValue(diag);
}

virtual bool OutputUsedInComputingInputNodesGradients() const override
{
// The DiagonalNode does not require its output value for computing
// the gradients of its input nodes
return false;
}
virtual bool OutputUsedInComputingInputNodesGradients() const override { return false; }
virtual bool InputUsedInComputingInputNodesGradients(size_t /*childIndex*/) const override { return false; }

virtual bool InputUsedInComputingInputNodesGradients(size_t childIndex) const override
virtual void Validate(bool isFinalValidationPass) override
{
// The DiagonalNode does not require any of it's input's values for computing
// the gradients of its input nodes
UNREFERENCED_PARAMETER(childIndex);
return false;
Base::Validate(isFinalValidationPass);
m_pMBLayout = nullptr;

if (isFinalValidationPass && Input(0)->HasMBLayout())
InvalidArgument("%ls %ls operation cannot operate on minibatch data (which have a layout)", NodeName().c_str(), OperationName().c_str());

size_t dim = Input(0)->GetAsMatrixNumCols();
if (isFinalValidationPass && dim != Input(0)->GetAsMatrixNumRows())
InvalidArgument("%ls %ls operation requires a square matrix as its input.", NodeName().c_str(), OperationName().c_str());

if (Input(0)->HasSampleLayout())
fprintf(stderr, "WARNING: Diagonal operation cannot inherit image size information from its child. Image size info is lost.\n");

SetDims(TensorShape(1, dim), false);
}
};

Expand Down Expand Up @@ -839,20 +809,20 @@ class LegacyReshapeNode : public ReinterpretNodeBase<ElemType>
}
}

virtual void Save(File& fstream) const override
{
Base::Save(fstream);
fstream << m_numTargetRows;
m_targetImageLayout.Save(fstream);
}

virtual void Load(File& fstream, size_t modelVersion) override
{
Base::Load(fstream, modelVersion);
fstream >> m_numTargetRows;
m_targetImageLayout.Load(fstream, /*acceptLegacyFormat=*/true);
}

virtual void Save(File& fstream) const override
{
Base::Save(fstream);
fstream << m_numTargetRows;
m_targetImageLayout.Save(fstream);
}

virtual void /*IComputationNode::*/ PrintSelfBeforeValidation() const override
{
fprintf(stderr, "\nValidating --> %ls = %ls", NodeName().c_str(), OperationName().c_str());
Expand All @@ -871,56 +841,6 @@ class LegacyReshapeNode : public ReinterpretNodeBase<ElemType>
// BUGBUG: This interpretaion as image dims is only correct for the 'legacy format, not for cudnn.
}

virtual void /*ComputationNodeBase::*/ Validate(bool isFinalValidationPass) override
{
Base::Validate(isFinalValidationPass);
if (factor() == 1) // canonical case: keeps the MBLayout(e.g. only changing the TensorShape)
m_pMBLayout = Input(0)->GetMBLayout();
else if (Input(0)->HasMBLayout())
{
if (!m_pMBLayout)
m_pMBLayout = make_shared<MBLayout>(); // mini-batch data: this generates a new layout
}
else
assert(!m_pMBLayout); // reshaping non-mini-batch data

size_t newCols = 1; // dummy
if (!m_pMBLayout)
{
size_t rows = Input(0)->GetAsMatrixNumRows(), cols = Input(0)->GetAsMatrixNumCols();
newCols = cols * rows / m_numTargetRows;
if (isFinalValidationPass)
{
if ((m_numTargetRows > rows && m_numTargetRows % rows != 0) || // grouping columns
(m_numTargetRows < rows && rows % m_numTargetRows != 0)) // splitting columns
InvalidArgument("%ls %ls operation: output row dimension %d is not an integer multiple or divisor of input dimension %d", NodeName().c_str(), OperationName().c_str(), (int) m_numTargetRows, (int) rows);
if (rows * cols != m_numTargetRows * newCols)
LogicError("%ls %ls operation: unexpected dimension mismatch", NodeName().c_str(), OperationName().c_str());
}
}

// patch up m_targetImageLayout, which was originally a construction parameter
InferTargetSampleLayout();

// setting any dimension to 0 means lose the tensor, flatten to vector
if (m_targetImageLayout.GetNumElements() == 0)
{
if (Input(0)->HasSampleLayout())
fprintf(stderr, "WARNING: Reshape operation cannot inherit image size information from its child. Image size info is lost.\n");
// TODO: We need to decide what reshaping means in presence of a tensor.
if (HasMBLayout())
SetDims(TensorShape(m_numTargetRows), true);
else
SetDims(TensorShape(m_numTargetRows, newCols), false);
}
else
{
if (m_numTargetRows != m_targetImageLayout.GetNumElements())
LogicError("LegacyReshapeNode: InferTargetSampleLayout() computed a sample layout [%s] that mismatches m_numTargetRows %d.", string(m_targetImageLayout).c_str(), (int) m_numTargetRows);
SetDims(m_targetImageLayout, HasMBLayout());
}
}

// TODO: Clarify/resolve the semantic overlap between BeginForwardProp() and UpdateFunctionMBSize().
virtual void /*IComputationNode::*/ BeginForwardProp() override
{
Expand Down Expand Up @@ -1002,19 +922,57 @@ class LegacyReshapeNode : public ReinterpretNodeBase<ElemType>
}
}

virtual bool OutputUsedInComputingInputNodesGradients() const override
{
// The LegacyReshapeNode does not require its output value for computing
// the gradients of its input nodes
return false;
}
virtual bool OutputUsedInComputingInputNodesGradients() const override { return false; }
virtual bool InputUsedInComputingInputNodesGradients(size_t /*childIndex*/) const override { return false; }

virtual bool InputUsedInComputingInputNodesGradients(size_t childIndex) const override
virtual void /*ComputationNodeBase::*/ Validate(bool isFinalValidationPass) override
{
// The LegacyReshapeNode does not require any of it's input's values for computing
// the gradients of its input nodes
UNREFERENCED_PARAMETER(childIndex);
return false;
Base::Validate(isFinalValidationPass);
if (factor() == 1) // canonical case: keeps the MBLayout(e.g. only changing the TensorShape)
m_pMBLayout = Input(0)->GetMBLayout();
else if (Input(0)->HasMBLayout())
{
if (!m_pMBLayout)
m_pMBLayout = make_shared<MBLayout>(); // mini-batch data: this generates a new layout
}
else
assert(!m_pMBLayout); // reshaping non-mini-batch data

size_t newCols = 1; // dummy
if (!m_pMBLayout)
{
size_t rows = Input(0)->GetAsMatrixNumRows(), cols = Input(0)->GetAsMatrixNumCols();
newCols = cols * rows / m_numTargetRows;
if (isFinalValidationPass)
{
if ((m_numTargetRows > rows && m_numTargetRows % rows != 0) || // grouping columns
(m_numTargetRows < rows && rows % m_numTargetRows != 0)) // splitting columns
InvalidArgument("%ls %ls operation: output row dimension %d is not an integer multiple or divisor of input dimension %d", NodeName().c_str(), OperationName().c_str(), (int) m_numTargetRows, (int) rows);
if (rows * cols != m_numTargetRows * newCols)
LogicError("%ls %ls operation: unexpected dimension mismatch", NodeName().c_str(), OperationName().c_str());
}
}

// patch up m_targetImageLayout, which was originally a construction parameter
InferTargetSampleLayout();

// setting any dimension to 0 means lose the tensor, flatten to vector
if (m_targetImageLayout.GetNumElements() == 0)
{
if (Input(0)->HasSampleLayout())
fprintf(stderr, "WARNING: Reshape operation cannot inherit image size information from its child. Image size info is lost.\n");
// TODO: We need to decide what reshaping means in presence of a tensor.
if (HasMBLayout())
SetDims(TensorShape(m_numTargetRows), true);
else
SetDims(TensorShape(m_numTargetRows, newCols), false);
}
else
{
if (m_numTargetRows != m_targetImageLayout.GetNumElements())
LogicError("LegacyReshapeNode: InferTargetSampleLayout() computed a sample layout [%s] that mismatches m_numTargetRows %d.", string(m_targetImageLayout).c_str(), (int) m_numTargetRows);
SetDims(m_targetImageLayout, HasMBLayout());
}
}

private:
Expand Down

0 comments on commit 37fb8df

Please sign in to comment.