Address review comments
This commit is contained in:
Родитель
d96f491dad
Коммит
ca4afe5c67
1
Makefile
1
Makefile
|
@ -586,7 +586,6 @@ CNTK_SRC =\
|
|||
$(SOURCEDIR)/CNTK/BrainScript/BrainScriptEvaluator.cpp \
|
||||
$(SOURCEDIR)/CNTK/BrainScript/BrainScriptParser.cpp \
|
||||
$(SOURCEDIR)/CNTK/BrainScript/BrainScriptTest.cpp \
|
||||
$(SOURCEDIR)/CNTK/BrainScript/ExperimentalNetworkBuilder.cpp \
|
||||
$(SOURCEDIR)/Common/BestGpu.cpp \
|
||||
$(SOURCEDIR)/Common/MPIWrapper.cpp \
|
||||
|
||||
|
|
|
@ -73,7 +73,7 @@ void NDLNodeEvaluatorImpl<ElemType>::Evaluate(NDLNode<ElemType>* node, const wst
|
|||
size_t i = 0;
|
||||
auto tensorShape = ProcessTensorShapeParameters(node, params, i, /*isImage=*/false, cnNodeType);
|
||||
|
||||
wstring dynamicAxis = node->GetOptionalParameter("dynamic", "");
|
||||
wstring dynamicAxis = node->GetOptionalParameter("dynamicAxis", "");
|
||||
// first look for this node already existing in the network
|
||||
// BUGBUG: How does this set the dimensions then?
|
||||
if (m_net->NodeNameExists(name))
|
||||
|
@ -98,7 +98,7 @@ void NDLNodeEvaluatorImpl<ElemType>::Evaluate(NDLNode<ElemType>* node, const wst
|
|||
size_t imageHeight = ((NDLNode<ElemType>*) params[1])->GetScalar();
|
||||
size_t imageChannels = ((NDLNode<ElemType>*) params[2])->GetScalar();
|
||||
ImageLayoutKind imageLayoutKind = ImageLayoutKindFrom(node->GetOptionalParameter("imageLayout", "HWC"));
|
||||
wstring dynamicAxis = node->GetOptionalParameter("dynamic", "");
|
||||
wstring dynamicAxis = node->GetOptionalParameter("dynamicAxis", "");
|
||||
|
||||
if (isSparse)
|
||||
nodePtr = builder.CreateSparseInputNode(name, ImageDimensions::AsTensorShape(imageWidth, imageHeight, imageChannels, imageLayoutKind), dynamicAxis);
|
||||
|
|
|
@ -34,11 +34,11 @@ Parameter = LearnableParameter // deprecated
|
|||
# TODO: make Parameter take tensor dims?
|
||||
ParameterTensor(dims, learningRateMultiplier = 1.0, init = 'uniform'/*|fixedValue|gaussian|fromFile*/, initValueScale = 1, value = 0, initFromFilePath = '', initFromLiteral = '', initOnCPUOnly=true, randomSeed=-1, tag='') = new ComputationNode [ operation = 'LearnableParameter' ; shape = new TensorShape [ /*dims*/ ] /*plus the function args*/ ]
|
||||
ConstantFromString(literal, tag='') = ParameterTensor((0)/*dim, will be inferred*/, init = 'fromLiteral', initFromLiteral = literal, learningRateMultiplier = 0.0)
|
||||
DynamicAxis(Name='', tag='') = new ComputationNode [ operation = 'DynamicAxis' ; name = Name ]
|
||||
Input(dims, dynamicAxis='', tag='feature') = new ComputationNode [ operation = 'InputValue' ; shape = new TensorShape [ /*dims*/ ] ; dynamicAxes = dynamicAxis ; isImage = false /*plus the function args*/ ]
|
||||
SparseInput(dims, dynamicAxis='', tag='feature') = new ComputationNode [ operation = 'SparseInputValue' ; shape = new TensorShape [ /*dims*/ ] ; dynamicAxes = dynamicAxis ; isImage = false /*plus the function args*/ ]
|
||||
ImageInput(imageWidth, imageHeight, imageChannels, imageLayout='CHW', dynamicAxis='', tag='feature') = new ComputationNode [ operation = 'InputValue' ; dynamicAxes = dynamicAxis ; isImage = true /*plus the function args*/ ]
|
||||
SparseImageInput(imageWidth, imageHeight, imageChannels, imageLayout='CHW', dynamicAxis='', tag='feature') = new ComputationNode [ operation = 'SparseInputValue' ; dynamicAxes = dynamicAxis ; isImage = true /*plus the function args*/ ]
|
||||
DynamicAxis(name='', tag='') = new ComputationNode [ operation = 'DynamicAxis' ; /*plus the function args*/ ]
|
||||
Input(dims, dynamicAxis='', tag='feature') = new ComputationNode [ operation = 'InputValue' ; shape = new TensorShape [ /*dims*/ ] ; isImage = false /*plus the function args*/ ]
|
||||
SparseInput(dims, dynamicAxis='', tag='feature') = new ComputationNode [ operation = 'SparseInputValue' ; shape = new TensorShape [ /*dims*/ ] ; isImage = false /*plus the function args*/ ]
|
||||
ImageInput(imageWidth, imageHeight, imageChannels, imageLayout='CHW', dynamicAxis='', tag='feature') = new ComputationNode [ operation = 'InputValue' ; isImage = true /*plus the function args*/ ]
|
||||
SparseImageInput(imageWidth, imageHeight, imageChannels, imageLayout='CHW', dynamicAxis='', tag='feature') = new ComputationNode [ operation = 'SparseInputValue' ; isImage = true /*plus the function args*/ ]
|
||||
EnvironmentInput(propertyName, tag='') = new ComputationNode [ operation = 'EnvironmentInput' /*plus the function args*/ ]
|
||||
ConstantTensor(val, dims, tag='') = ParameterTensor(dims, learningRateMultiplier = 0, init = 'fixedValue', value = val)
|
||||
Constant(val, rows = 1, cols = 1, tag='') = Parameter(rows, cols, learningRateMultiplier = 0, init = 'fixedValue', value = val)
|
||||
|
|
|
@ -1,134 +0,0 @@
|
|||
#if 0 // this entire file can be removed once CNTK.core.bs works
|
||||
// ExperimentalNetworkBuilder.cpp -- interface to new version of NDL (and config) parser --fseide
|
||||
|
||||
#define _CRT_NONSTDC_NO_DEPRECATE // make VS accept POSIX functions without _
|
||||
#define _CRT_SECURE_NO_WARNINGS // "secure" CRT not available on all platforms --add this at the top of all CPP files that give "function or variable may be unsafe" warnings
|
||||
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
// TODO: move to actual text files to be included
|
||||
|
||||
wstring standardFunctions =
|
||||
L"Print(value, format='') = new PrintAction [ what = value /*; how = format*/ ] \n"
|
||||
L"Debug(value, say = '', enabled = true) = new Debug [ /*macro arg values*/ ] \n"
|
||||
L"Format(value, format) = new StringFunction [ what = 'Format' ; arg = value ; how = format ] \n"
|
||||
L"Replace(s, from, to) = new StringFunction [ what = 'Replace' ; arg = s ; replacewhat = from ; withwhat = to ] \n"
|
||||
L"Substr(s, begin, num) = new StringFunction [ what = 'Substr' ; arg = s ; pos = begin ; chars = num ] \n"
|
||||
L"Chr(c) = new StringFunction [ what = 'Chr' ; arg = c ] \n"
|
||||
L"Floor(x) = new NumericFunction [ what = 'Floor' ; arg = x ] \n"
|
||||
L"Length(x) = new NumericFunction [ what = 'Length' ; arg = x ] \n"
|
||||
L"Ceil(x) = -Floor(-x) \n"
|
||||
L"Round(x) = Floor(x+0.5) \n"
|
||||
L"Sign(x) = if x > 0 then 1 else if x < 0 then -1 else 0 \n"
|
||||
L"Min(a,b) = if a < b then a else b \n"
|
||||
L"Max(a,b) = if a > b then a else b \n"
|
||||
L"Fac(n) = if n > 1 then Fac(n-1) * n else 1 \n";
|
||||
|
||||
wstring commonMacros =
|
||||
L"BFF(in, rows, cols) = [ B = Parameter(rows, 1, init = 'fixedValue', value = 0) ; W = Parameter(rows, cols) ; z = W*in+B ] \n"
|
||||
L"SBFF(in, rows, cols) = [ Eh = Sigmoid(BFF(in, rows, cols).z) ] \n "
|
||||
L"MeanVarNorm(feat) = PerDimMeanVarNormalization(feat, Mean(feat), InvStdDev(feat)) \n"
|
||||
L"LogPrior(labels) = Log(Mean(labels)) \n";
|
||||
|
||||
wstring computationNodes = // TODO: use actual TypeName() here? would first need to make it a wide string; we should also extract those two methods into the base macro
|
||||
L"LearnableParameter(rows, cols, learningRateMultiplier = 1.0, init = 'uniform'/*|fixedValue|gaussian|fromFile*/, initValueScale = 1, value = 0, initFromFilePath = '', initOnCPUOnly=true, randomSeed=-1, tag='') = new ComputationNode [ operation = 'LearnableParameter' ; shape = new TensorShape [ dims = (rows : cols) ] /*plus the function args*/ ]\n"
|
||||
L"Parameter = LearnableParameter // deprecated \n"
|
||||
L"ParameterTensor(dims, learningRateMultiplier = 1.0, init = 'uniform'/*|fixedValue|gaussian|fromFile*/, initValueScale = 1, value = 0, initFromFilePath = '', initOnCPUOnly=true, randomSeed=-1, tag='') = new ComputationNode [ operation = 'LearnableParameter' ; shape = new TensorShape [ /*dims*/ ] /*plus the function args*/ ]\n"
|
||||
// TODO: ImageParameter?
|
||||
// ^^ already works; vv untested
|
||||
L"Input(dims, tag='feature') = new ComputationNode [ operation = 'InputValue' ; shape = new TensorShape [ /*dims*/ ] ; isImage = false /*plus the function args*/ ]\n" // note: naming a little inconsistent // TODO: re-test after flag change
|
||||
L"SparseInput(dims, tag='feature') = new ComputationNode [ operation = 'SparseInputValue' ; shape = new TensorShape [ /*dims*/ ] ; isImage = false /*plus the function args*/ ]\n"
|
||||
L"ImageInput(imageWidth, imageHeight, imageChannels, imageLayout='CHW', tag='feature') = new ComputationNode [ operation = 'InputValue' ; isImage = true /*plus the function args*/ ]\n"
|
||||
L"SparseImageInput(imageWidth, imageHeight, imageChannels, imageLayout='CHW', tag='feature') = new ComputationNode [ operation = 'SparseInputValue' ; isImage = true /*plus the function args*/ ]\n"
|
||||
L"Constant(val, rows = 1, cols = 1, tag='') = Parameter(rows, cols, learningRateMultiplier = 0, init = 'fixedValue', value = val) \n"
|
||||
L"PastValue(dims, input, timeStep = 1, defaultHiddenActivation = 0.1, tag='') = new ComputationNode [ operation = 'PastValue' ; inputs = input ; shape = new TensorShape [ /*dims*/ ] /*plus the function args*/ ]\n"
|
||||
L"FutureValue(dims, input, timeStep = 1, defaultHiddenActivation = 0.1, tag='') = new ComputationNode [ operation = 'FutureValue' ; inputs = input ; shape = new TensorShape [ /*dims*/ ] /*plus the function args*/ ]\n"
|
||||
// TODO: ^^ DelayedValues no longer need to know their dimension. That is inferred in Validation.
|
||||
L"Shift(input, fromOffset, boundaryValue, boundaryMode=-1/*context*/, dim=-1, tag='') = new ComputationNode [ operation = 'Shift' ; inputs = (input : boundaryValue) /*plus the function args*/ ]\n"
|
||||
L"RowSlice(startIndex, numRows, input, tag='') = new ComputationNode [ operation = 'RowSlice' ; inputs = input /*plus the function args*/ ]\n"
|
||||
L"RowRepeat(input, numRepeats, tag='') = new ComputationNode [ operation = 'RowRepeat' ; inputs = input /*plus the function args*/ ]\n"
|
||||
L"RowStack(inputs, tag='') = new ComputationNode [ operation = 'RowStack' /*plus the function args*/ ]\n"
|
||||
L"Reshape(input, numRows, imageWidth = 0, imageHeight = 0, imageChannels = 0, tag='') = new ComputationNode [ operation = 'LegacyReshape' ; inputs = input /*plus the function args*/ ]\n"
|
||||
L"NewReshape(input, dims, beginDim=0, endDim=0, tag='') = new ComputationNode [ operation = 'Reshape' ; inputs = input ; shape = new TensorShape [ /*dims*/ ] /*plus the function args*/ ]\n"
|
||||
L"ReshapeDimension(x, dim, tensorShape) = NewReshape(x, tensorShape, beginDim=dim, endDim=dim + 1) \n"
|
||||
L"FlattenDimensions(x, dim, num) = NewReshape(x, 0, beginDim=dim, endDim=dim + num) \n"
|
||||
L"SplitDimension(x, dim, N) = ReshapeDimension(x, dim, 0:N) \n"
|
||||
L"TransposeDimensions(input, dim1, dim2, tag='') = new ComputationNode [ operation = 'TransposeDimensions' ; inputs = input /*plus the function args*/ ]\n"
|
||||
L"Transpose(x) = TransposeDimensions(x, 1, 2)\n"
|
||||
L"Times(A, B, outputRank=1, tag='') = new ComputationNode [ operation = 'Times' ; inputs = ( A : B ) /*plus the function args*/ ]\n"
|
||||
// TODO: Logistic should be generated with with BinaryStandardNode macro below.
|
||||
L"Logistic(label, probability, tag='') = new ComputationNode [ operation = 'Logistic' ; inputs = (label : probability) /*plus the function args*/ ]\n"
|
||||
L"WeightedLogistic(label, probability, instanceWeight, tag='') = new ComputationNode [ operation = 'Logistic' ; inputs = (label : probability : instanceWeight) /*plus the function args*/ ]\n"
|
||||
L"ReconcileDynamicAxis(dataInput, layoutInput, tag='') = new ComputationNode [ operation = 'ReconcileDynamicAxis' ; inputs = (dataInput : layoutInput) /*plus the function args*/ ]\n"
|
||||
L"Convolution(weightNode, inputValueNode, kernelWidth, kernelHeight, outputChannels, horizontalSubsample, verticalSubsample, zeroPadding = false, maxTempMemSizeInSamples = 0, imageLayout='CHW', tag='') = new ComputationNode [ operation = 'Convolution' ; inputs = (weightNode : inputValueNode) /*plus the function args*/ ]\n"
|
||||
L"MaxPooling(input, windowWidth, windowHeight, horizontalSubsample, verticalSubsample, imageLayout='CHW', tag='') = new ComputationNode [ operation = 'MaxPooling' ; inputs = input /*plus the function args*/ ]\n"
|
||||
L"AveragePooling(input, windowWidth, windowHeight, horizontalSubsample, verticalSubsample, imageLayout='CHW', tag='') = new ComputationNode [ operation = 'AveragePooling' ; inputs = input /*plus the function args*/ ]\n"
|
||||
// TODO: define DelayedValue, with negative delay for future; cannot do this yet, need to be able to say something like delay = -(^.delay)
|
||||
// aliases
|
||||
L"ColumnwiseCrossProduct = KhatriRaoProduct // deprecated \n" // TODO: should it be deprecated? It is described as easier to understand in the CNTKBook.
|
||||
L"ClassificationError = ErrorPrediction \n"
|
||||
L"Delay = PastValue \n" // TODO: should it allow negative offsets and an if test here?
|
||||
L"BatchNormalization(input, scale, bias, runMean, runInvStdDev, eval, spatial, normalizationTimeConstant = 0, epsilon = 0.00001, useCntkEngine = true, imageLayout='CHW', tag='') = new ComputationNode [ operation = 'BatchNormalization' ; inputs = (input : scale : bias : runMean : runInvStdDev) /*plus the function args*/ ]\n"
|
||||
// standard nodes. We use macros to define these strings.
|
||||
#define UnaryStandardNode(Op, a) L## #Op L"(" L## #a L", tag='') = new ComputationNode [ operation = '" L## #Op L"' ; inputs = " L## #a L" /*plus the function args*/ ]\n"
|
||||
#define BinaryStandardNode(Op, a, b) L## #Op L"(" L## #a L", " L## #b L", tag='') = new ComputationNode [ operation = '" L## #Op L"' ; inputs = (" L## #a L" : " L## #b L") /*plus the function args*/ ]\n"
|
||||
#define TernaryStandardNode(Op, a, b, c) L## #Op L"(" L## #a L", " L## #b L", " L## #c L", tag='') = new ComputationNode [ operation = '" L## #Op L"' ; inputs = (" L## #a L" : " L## #b L" : " L## #c L") /*plus the function args*/ ]\n"
|
||||
#define QuaternaryStandardNode(Op, a, b, c, d) L## #Op L"(" L## #a L", " L## #b L", " L## #c L", " L## #d L", tag='') = new ComputationNode [ operation = '" L## #Op L"' ; inputs = (" L## #a L" : " L## #b L" : " L## #c L" : " L## #d L") /*plus the function args*/ ]\n"
|
||||
#ifdef COMING_SOON
|
||||
TernaryStandardNode(CRF, labelVectorSequence, positionDependenScoreVectorSequence, transitionScores) // TODO: better names
|
||||
#endif
|
||||
UnaryStandardNode(Abs, x)
|
||||
QuaternaryStandardNode(ClassBasedCrossEntropyWithSoftmax, labelClassDescriptorVectorSequence, mainInputInfo, mainWeight, classLogProbsBeforeSoftmax)
|
||||
// BUGBUG: the commented-out ones are not mentioned in the CNTK book, nor are their parameters documented in the source code
|
||||
BinaryStandardNode(ColumnElementTimes, aVectorSequence, anotherVectorSequence)
|
||||
BinaryStandardNode(CosDistance, aVectorSequence, anotherVectorSequence)
|
||||
QuaternaryStandardNode(CosDistanceWithNegativeSamples, aVectorSequence, anotherVectorSequence, numShifts, numNegSamples)
|
||||
//BinaryStandardNode(CosDistanceWithNegativeSamplesNode)
|
||||
UnaryStandardNode(Cosine, x)
|
||||
BinaryStandardNode(CrossEntropy, refProbVectorSequence, outProbVectorSequence)
|
||||
BinaryStandardNode(CrossEntropyWithSoftmax, labelVectorSequence, outProbVectorSequence)
|
||||
BinaryStandardNode(DiagTimes, diagonalMatrixAsColumnVector, matrix)
|
||||
UnaryStandardNode(Dropout, activationVectorSequence)
|
||||
//BinaryStandardNode(DummyCriterionNode)
|
||||
BinaryStandardNode(ElementTimes, aMatrix, anotherMatrix)
|
||||
BinaryStandardNode(ErrorPrediction, labelVectorSequence, outVectorSequence) // CNTKBook: ClassificationError?
|
||||
UnaryStandardNode(Exp, x)
|
||||
QuaternaryStandardNode(GMMLogLikelihood, unnormalizedPriorVector, meansAsRows, logStdDevAsRows, dataVectorSequence)
|
||||
UnaryStandardNode(InvStdDev, dataVectorSequence)
|
||||
BinaryStandardNode(KhatriRaoProduct, leftMatrix, rightMatrix)
|
||||
//BinaryStandardNode(LSTMNode)
|
||||
UnaryStandardNode(Log, x)
|
||||
UnaryStandardNode(LogSoftmax, z)
|
||||
//BinaryStandardNode(LookupTableNode)
|
||||
UnaryStandardNode(MatrixL1Reg, matrix)
|
||||
UnaryStandardNode(MatrixL2Reg, matrix)
|
||||
// BUGBUG: CNTKBook also mentions L1Norm and L2Norm
|
||||
UnaryStandardNode(Mean, dataVectorSequence)
|
||||
BinaryStandardNode(Minus, leftMatrix, rightMatrix)
|
||||
UnaryStandardNode(Negate, input)
|
||||
TernaryStandardNode(PerDimMeanVarDeNormalization, dataVectorSequence, meanVector, invStdDevVector) // TODO: correct?
|
||||
TernaryStandardNode(PerDimMeanVarNormalization, dataVectorSequence, meanVector, invStdDevVector)
|
||||
BinaryStandardNode(Plus, leftMatrix, rightMatrix)
|
||||
UnaryStandardNode(RectifiedLinear, z)
|
||||
//BinaryStandardNode(RowElementTimesNode)
|
||||
BinaryStandardNode(Scale, scalarScalingFactor, matrix)
|
||||
#ifdef COMING_SOON
|
||||
//BinaryStandardNode(SequenceDecoderNode)
|
||||
#endif
|
||||
UnaryStandardNode(Sigmoid, z)
|
||||
UnaryStandardNode(Softmax, z)
|
||||
UnaryStandardNode(Hardmax, z)
|
||||
BinaryStandardNode(SquareError, aMatrix, anotherMatrix)
|
||||
UnaryStandardNode(SumColumnElements, z)
|
||||
UnaryStandardNode(SumElements, matrix)
|
||||
UnaryStandardNode(Tanh, z)
|
||||
UnaryStandardNode(TimeReverse, vectorSequence)
|
||||
BinaryStandardNode(TransposeTimes, leftMatrix, rightMatrix)
|
||||
// those nodes are deprecated, we won't implement them in BS:
|
||||
//BinaryStandardNode(NoiseContrastiveEstimationNode)
|
||||
//BinaryStandardNode(ParallelNode)
|
||||
//BinaryStandardNode(StrideTimesNode)
|
||||
;
|
||||
#endif
|
|
@ -203,7 +203,6 @@
|
|||
<ClCompile Include="BrainScript\BrainScriptEvaluator.cpp" />
|
||||
<ClCompile Include="BrainScript\BrainScriptParser.cpp" />
|
||||
<ClCompile Include="BrainScript\BrainScriptTest.cpp" />
|
||||
<ClCompile Include="BrainScript\ExperimentalNetworkBuilder.cpp" />
|
||||
<ClCompile Include="CNTK.cpp" />
|
||||
<ClCompile Include="ModelEditLanguage.cpp" />
|
||||
<ClCompile Include="stdafx.cpp" />
|
||||
|
@ -226,4 +225,4 @@
|
|||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets" />
|
||||
</Project>
|
||||
</Project>
|
|
@ -44,9 +44,6 @@
|
|||
<ClCompile Include="BrainScript\BrainScriptTest.cpp">
|
||||
<Filter>BrainScript</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="BrainScript\ExperimentalNetworkBuilder.cpp">
|
||||
<Filter>BrainScript</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Common\ExceptionWithCallStack.cpp">
|
||||
<Filter>Common</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
@ -120,6 +120,8 @@ struct MBLayout
|
|||
|
||||
// copy the content of another MBLayoutPtr over
|
||||
// Use this instead of actual assignment to make it super-obvious that this is not copying the pointer but actual content. The pointer is kept fixed.
|
||||
// Use "keepName" if the "identity" of the target is to be preserved, e.g.
|
||||
// while copying from reader space to network space.
|
||||
void CopyFrom(const MBLayoutPtr& other, bool keepName=false)
|
||||
{
|
||||
m_numTimeSteps = other->m_numTimeSteps;
|
||||
|
@ -521,7 +523,7 @@ private:
|
|||
size_t m_numFramesDeclared;
|
||||
size_t m_numGapFrames;
|
||||
|
||||
// Lookup tables for determining whether any sequence at time t is a identical layouts, do noboundary or gap.
|
||||
// Lookup tables for determining whether any sequence at time t is a boundary or gap.
|
||||
// An optional time delay can be given, then the test is whether going from t to (t + time delay) crosses a boundary.
|
||||
// The purpose is for knowing when to reset state of a recurrent node.
|
||||
//
|
||||
|
|
|
@ -76,7 +76,7 @@ static shared_ptr<ComputationNode<ElemType>> CreateStandardNode(const std::wstri
|
|||
else if (nodeType == OperationNameOf(PerDimMeanVarDeNormalizationNode)) return New<PerDimMeanVarDeNormalizationNode<ElemType>>(forward<_Types>(_Args)...);
|
||||
else if (nodeType == OperationNameOf(PassNode)) return New<PassNode<ElemType>>(forward<_Types>(_Args)...);
|
||||
else if (nodeType == OperationNameOf(PlusNode)) return New<PlusNode<ElemType>>(forward<_Types>(_Args)...);
|
||||
else if (nodeType == OperationNameOf(ReconcileDynamicAxisNode)) return New<ReconcileDynamicAxisNode<ElemType>>(forward<_Types>(_Args)...);
|
||||
else if (nodeType == OperationNameOf(ReconcileDynamicAxisNode)) return New<ReconcileDynamicAxisNode<ElemType>>(forward<_Types>(_Args)...);
|
||||
else if (nodeType == OperationNameOf(ReciprocalNode)) return New<ReciprocalNode<ElemType>>(forward<_Types>(_Args)...);
|
||||
else if (nodeType == OperationNameOf(RectifiedLinearNode)) return New<RectifiedLinearNode<ElemType>>(forward<_Types>(_Args)...);
|
||||
else if (nodeType == OperationNameOf(ReshapeNode)) return New<ReshapeNode<ElemType>>(forward<_Types>(_Args)...);
|
||||
|
|
|
@ -525,13 +525,19 @@ void ComputationNetwork::ResetMBLayouts()
|
|||
for (const auto& node : GetAllNodesForRoot(nullptr))
|
||||
node->LinkToMBLayout(nullptr);
|
||||
|
||||
// DynamicAxis nodes are (apart from the network-wide MBLayout) the only holders of MBLayouts. Initialize them.
|
||||
// DynamicAxis nodes are (apart from the network-wide MBLayout) the main holders of MBLayouts. Initialize them.
|
||||
// The only other instances are nodes that change the MBLayout, like WhereNode.
|
||||
for (auto node : GetNodesWithType(L"DynamicAxis"))
|
||||
node->LinkToMBLayout(make_shared<MBLayout>(1, 0, node->GetName()));
|
||||
|
||||
// This is now initialized inside of the Input nodes, with the proper connections.
|
||||
for (auto node : InputNodes(nullptr))
|
||||
node->AttachDynamicAxis([&](std::wstring name) { return GetNodeFromName(name); }, /* default */ m_pMBLayoutOfNetwork);
|
||||
{
|
||||
auto n = dynamic_pointer_cast<IDynamic>(node);
|
||||
if (!n)
|
||||
LogicError("Expected %ls to implement IDynamic, but it doesn't.", node->NodeDescription().c_str());
|
||||
n->AttachDynamicAxis([&](std::wstring name) { return GetNodeFromName(name); }, /* default */ m_pMBLayoutOfNetwork);
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
|
|
@ -332,28 +332,25 @@ TensorShape ComputationNodeBase::GetOneSampleTensorSliceFor(size_t rank, const F
|
|||
prototype += "NULL";
|
||||
continue;
|
||||
}
|
||||
|
||||
const char* mbSizeMark = child->m_pMBLayout ? " x " : "";
|
||||
#if 0
|
||||
if (child->m_sampleLayout.GetRank() == 3 && (child->m_sampleLayout[1] != 1 || child->m_sampleLayout[0] != 1)) // looks like an image: use WHC notation
|
||||
prototype += msra::strfun::strprintf("%ls[%s%s {W=%lu, H=%lu, C=%lu}]", child->NodeName().c_str(), string(child->m_sampleLayout).c_str(), mbSizeMark,
|
||||
child->m_sampleLayout[1], child->m_sampleLayout[2], child->m_sampleLayout[0]);
|
||||
// BUGBUG: This ^^ will print based on the old legacy layout, and we have no way of knowing here whether that is correct.
|
||||
else
|
||||
#endif
|
||||
prototype += msra::strfun::strprintf("[%s%s%ls]", string(child->m_sampleLayout).c_str(), mbSizeMark,
|
||||
child->HasMBLayout() ? child->GetMBLayout()->GetAxisName().c_str() : L"");
|
||||
prototype += child->ShapeDescription().c_str();
|
||||
}
|
||||
prototype += extraArgs;
|
||||
//prototype += ")";
|
||||
}
|
||||
|
||||
prototype += msra::strfun::strprintf(" -> [%s%s%ls]", string(GetSampleLayout()).c_str(), HasMBLayout() ? " x " : "",
|
||||
HasMBLayout() ? GetMBLayout()->GetAxisName().c_str() : L"");
|
||||
prototype += msra::strfun::strprintf(" -> %s", ShapeDescription().c_str());
|
||||
|
||||
return prototype;
|
||||
}
|
||||
|
||||
const std::string ComputationNodeBase::ShapeDescription() const
|
||||
{
|
||||
return msra::strfun::strprintf("[%s%s%ls]",
|
||||
string(m_sampleLayout).c_str(),
|
||||
HasMBLayout() ? " x " : "",
|
||||
HasMBLayout() ? GetMBLayout()->GetAxisName().c_str() : L"");
|
||||
}
|
||||
|
||||
template <class ElemType>
|
||||
/*virtual*/ void ComputationNode<ElemType>::DumpNodeInfo(const bool /*printValues*/, const bool printMetadata, File& fstream) const
|
||||
{
|
||||
|
|
|
@ -473,12 +473,6 @@ public:
|
|||
VerifyDims(node->GetSampleLayout(), node->HasMBLayout());
|
||||
}
|
||||
|
||||
virtual void AttachDynamicAxis(std::function<ComputationNodeBasePtr(const std::wstring)> nodeLookup, MBLayoutPtr defaultLayout)
|
||||
{
|
||||
// Applies only to input nodes.
|
||||
NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
// MBLayout (minibatch structure)
|
||||
void LinkToMBLayout(MBLayoutPtr pMBLayout)
|
||||
{
|
||||
|
@ -551,7 +545,7 @@ public:
|
|||
return GetInputsFromConfig(configp, L"inputs");
|
||||
}
|
||||
|
||||
static vector<ComputationNodeBasePtr> GetInputsFromConfig(const ScriptableObjects::IConfigRecordPtr configp, const std::wstring property)
|
||||
static vector<ComputationNodeBasePtr> GetInputsFromConfig(const ScriptableObjects::IConfigRecordPtr configp, const std::wstring& property)
|
||||
{
|
||||
vector<ComputationNodeBasePtr> inputs;
|
||||
const auto* inputsArg = configp->Find(property);
|
||||
|
@ -810,6 +804,9 @@ public:
|
|||
return std::wstring(L"Node '") + NodeName().c_str() + L"' (" + OperationName().c_str() + L" operation)";
|
||||
};
|
||||
|
||||
// Helper that returns [a x b x c], including dynamic axes.
|
||||
const std::string ShapeDescription() const;
|
||||
|
||||
protected:
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
@ -844,7 +841,8 @@ protected:
|
|||
typedef ComputationNodeBase::ComputationNodeBasePtr ComputationNodeBasePtr;
|
||||
|
||||
// =======================================================================
|
||||
// NumInputs -- little helper interface to allow derived Node classes to specify how many inputs they expect
|
||||
// NumInputs -- little helper interface to allow derived Node classes to
|
||||
// specify how many inputs they expect
|
||||
// =======================================================================
|
||||
|
||||
struct INumInputs { virtual size_t GetExpectedNumInputs() const = 0; };
|
||||
|
@ -857,6 +855,14 @@ struct NumInputs : public INumInputs // e.g. derive from NumInputs<2>
|
|||
}
|
||||
};
|
||||
|
||||
// =======================================================================
|
||||
//
|
||||
// =======================================================================
|
||||
struct IDynamic
|
||||
{
|
||||
virtual void AttachDynamicAxis(std::function<ComputationNodeBasePtr(const std::wstring)> nodeLookup, MBLayoutPtr defaultLayout) = 0;
|
||||
};
|
||||
|
||||
// =======================================================================
|
||||
// ComputationNode -- abstract base class for computation nodes, deriving
|
||||
// from CompuationNodeBase, parameterized by float vs. double
|
||||
|
@ -1921,7 +1927,6 @@ protected:
|
|||
public: \
|
||||
using Base::AttachInputs; \
|
||||
using Base::AttachInputsFromConfig; \
|
||||
using Base::AttachDynamicAxis; \
|
||||
using Base::CreateGradientMatrixIfNull; \
|
||||
using Base::NodeName; \
|
||||
using Base::RequiresPreCompute; \
|
||||
|
|
|
@ -129,7 +129,7 @@ public:
|
|||
m_displayName = name;
|
||||
}
|
||||
DynamicAxisNode(const ScriptableObjects::IConfigRecordPtr configp)
|
||||
: DynamicAxisNode(configp->Get(L"deviceId"), (const std::wstring&)configp->Get(L"name"))
|
||||
: DynamicAxisNode(configp->Get(L"deviceId"), (const std::wstring&)configp->Get(L"axisName"))
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -168,7 +168,7 @@ template class DynamicAxisNode<double>;
|
|||
// -----------------------------------------------------------------------
|
||||
|
||||
template <class ElemType>
|
||||
class InputValueBase : public ComputationNode<ElemType>, public NumInputs<0>
|
||||
class InputValueBase : public ComputationNode<ElemType>, public NumInputs<0>, public IDynamic
|
||||
{
|
||||
typedef ComputationNode<ElemType> Base;
|
||||
UsingComputationNodeMembers;
|
||||
|
@ -205,11 +205,11 @@ protected:
|
|||
{
|
||||
AttachInputsFromConfig(configp, this->GetExpectedNumInputs());
|
||||
wstring axisName = L"";
|
||||
if (configp->Exists(L"dynamicAxes"))
|
||||
if (configp->Exists(L"dynamicAxis"))
|
||||
{
|
||||
if (configp->Find(L"dynamicAxes")->Is<ComputationNodeBase>())
|
||||
if (configp->Find(L"dynamicAxis")->Is<ComputationNodeBase>())
|
||||
{
|
||||
ComputationNodeBasePtr axis = configp->Get(L"dynamicAxes");
|
||||
ComputationNodeBasePtr axis = configp->Get(L"dynamicAxis");
|
||||
axisName = axis->GetName();
|
||||
}
|
||||
// Else: Use default axis.
|
||||
|
@ -245,7 +245,7 @@ protected:
|
|||
// more dependencies on the order in which things are evaluated, though.
|
||||
if (!node->Is<DynamicAxisNode<ElemType>>())
|
||||
RuntimeError("%ls: dynamicAxis argument must be of type DynamicAxis(), but got %ls.",
|
||||
NodeDescription().c_str(), node->NodeDescription().c_str());
|
||||
NodeDescription().c_str(), node->NodeDescription().c_str());
|
||||
m_dynamicAxisNode = node->As<DynamicAxisNode<ElemType>>();
|
||||
if (!m_dynamicAxisNode->HasMBLayout())
|
||||
LogicError("%ls: Expected %ls to have MBLayout, but it doesn't.", NodeDescription().c_str(), node->NodeDescription().c_str());
|
||||
|
|
|
@ -122,7 +122,6 @@
|
|||
<ClCompile Include="..\..\..\Source\CNTK\BrainScript\BrainScriptEvaluator.cpp" />
|
||||
<ClCompile Include="..\..\..\Source\CNTK\BrainScript\BrainScriptParser.cpp" />
|
||||
<ClCompile Include="..\..\..\Source\CNTK\BrainScript\BrainScriptTest.cpp" />
|
||||
<ClCompile Include="..\..\..\Source\CNTK\BrainScript\ExperimentalNetworkBuilder.cpp" />
|
||||
<ClCompile Include="..\..\..\Source\Common\Config.cpp" />
|
||||
<ClCompile Include="..\..\..\Source\Common\DataReader.cpp" />
|
||||
<ClCompile Include="..\..\..\Source\Common\DataWriter.cpp" />
|
||||
|
|
|
@ -34,9 +34,6 @@
|
|||
<ClCompile Include="..\..\..\Source\CNTK\BrainScript\BrainScriptTest.cpp">
|
||||
<Filter>From BrainScript</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\Source\CNTK\BrainScript\ExperimentalNetworkBuilder.cpp">
|
||||
<Filter>From BrainScript</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="Config">
|
||||
|
|
Загрузка…
Ссылка в новой задаче