added imageLayout parameter to Convolution, MaxPooling, and AveragePooling (only Convolution had it, and BrainScrip only);
bug fix: LearnableParameter must also serialize m_sampleLayout
This commit is contained in:
Родитель
50218cd031
Коммит
5ff5d685db
|
@ -55,8 +55,8 @@ using namespace std;
|
|||
L"WeightedLogistic(label, probability, instanceWeight, tag='') = new ComputationNode [ operation = 'Logistic' ; inputs = (label : probability : instanceWeight) /*plus the function args*/ ]\n"
|
||||
L"ReconcileMBLayout(dataInput, layoutInput, tag='') = new ComputationNode [ operation = 'ReconcileMBLayout' ; 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, tag='') = new ComputationNode [ operation = 'MaxPooling' ; inputs = input /*plus the function args*/ ]\n"
|
||||
L"AveragePooling(input, windowWidth, windowHeight, horizontalSubsample, verticalSubsample, tag='') = new ComputationNode [ operation = 'AveragePooling' ; inputs = input /*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.
|
||||
|
|
|
@ -385,16 +385,15 @@ namespace Microsoft { namespace MSR { namespace CNTK {
|
|||
size_t outputChannels = ((NDLNode<ElemType>*)params[id++])->GetScalar();
|
||||
size_t horizontalSubsample = ((NDLNode<ElemType>*)params[id++])->GetScalar();
|
||||
size_t verticalSubsample = ((NDLNode<ElemType>*)params[id++])->GetScalar();
|
||||
|
||||
assert (id == 5);
|
||||
|
||||
//optional
|
||||
// optional
|
||||
ImageLayoutKind imageLayoutKind = ImageLayoutKindFrom(node->GetOptionalParameter("imageLayout", "HWC"));
|
||||
bool zeroPadding = node->GetOptionalParameter("zeroPadding", "false");
|
||||
size_t maxTempMemSizeInSamples = node->GetOptionalParameter("maxTempMemSizeInSamples", "0");
|
||||
|
||||
|
||||
nodePtr = builder.Convolution(NULL, NULL, kernelWidth, kernelHeight, outputChannels,
|
||||
horizontalSubsample, verticalSubsample, zeroPadding, name, maxTempMemSizeInSamples);
|
||||
horizontalSubsample, verticalSubsample, imageLayoutKind, zeroPadding, maxTempMemSizeInSamples, name);
|
||||
}
|
||||
}
|
||||
else if (cnNodeType == OperationNameOf(MaxPoolingNode))
|
||||
|
@ -417,11 +416,12 @@ namespace Microsoft { namespace MSR { namespace CNTK {
|
|||
size_t windowHeight = ((NDLNode<ElemType>*)params[id++])->GetScalar();
|
||||
size_t horizontalSubsample = ((NDLNode<ElemType>*)params[id++])->GetScalar();
|
||||
size_t verticalSubsample = ((NDLNode<ElemType>*)params[id++])->GetScalar();
|
||||
|
||||
assert (id == 4);
|
||||
|
||||
ImageLayoutKind imageLayoutKind = ImageLayoutKindFrom(node->GetOptionalParameter("imageLayout", "HWC"));
|
||||
|
||||
nodePtr = builder.MaxPooling(NULL, /*inputWidth,inputHeight, channels,*/windowWidth, windowHeight,
|
||||
horizontalSubsample, verticalSubsample, name);
|
||||
horizontalSubsample, verticalSubsample, imageLayoutKind, name);
|
||||
}
|
||||
}
|
||||
else if (cnNodeType == OperationNameOf(AveragePoolingNode))
|
||||
|
@ -444,11 +444,12 @@ namespace Microsoft { namespace MSR { namespace CNTK {
|
|||
size_t windowHeight = ((NDLNode<ElemType>*)params[id++])->GetScalar();
|
||||
size_t horizontalSubsample = ((NDLNode<ElemType>*)params[id++])->GetScalar();
|
||||
size_t verticalSubsample = ((NDLNode<ElemType>*)params[id++])->GetScalar();
|
||||
assert(id == 4);
|
||||
|
||||
assert (id == 4);
|
||||
ImageLayoutKind imageLayoutKind = ImageLayoutKindFrom(node->GetOptionalParameter("imageLayout", "HWC"));
|
||||
|
||||
nodePtr = builder.AveragePooling(NULL, /*inputWidth,inputHeight, channels,*/windowWidth, windowHeight,
|
||||
horizontalSubsample, verticalSubsample, name);
|
||||
horizontalSubsample, verticalSubsample, imageLayoutKind, name);
|
||||
}
|
||||
}
|
||||
else if (cnNodeType == OperationNameOf(BatchNormalizationNode))
|
||||
|
|
|
@ -251,7 +251,8 @@ namespace Microsoft { namespace MSR { namespace CNTK {
|
|||
Base::Load(fstream, modelVersion);
|
||||
fstream >> m_hasComputed;
|
||||
LoadValue(fstream);
|
||||
}
|
||||
// Note: This loses the sample layout, but that is recovered by Validate().
|
||||
}
|
||||
|
||||
virtual void DumpNodeInfo(const bool printValues, File& fstream) const override
|
||||
{
|
||||
|
|
|
@ -215,37 +215,26 @@ namespace Microsoft { namespace MSR { namespace CNTK {
|
|||
template<class ElemType> shared_ptr<ComputationNode<ElemType>> ComputationNetworkBuilder<ElemType>::CreateConvolutionNode(const std::wstring & nodeName,
|
||||
const size_t kernelWidth, const size_t kernelHeight, const size_t outputChannels,
|
||||
const size_t horizontalSubsample, const size_t verticalSubsample,
|
||||
const bool zeroPadding,
|
||||
ImageLayoutKind imageLayoutKind, const bool zeroPadding,
|
||||
const size_t maxTempMemSizeInSamples)
|
||||
{
|
||||
return net.AddNodeToNetWithElemType(New<ConvolutionNode<ElemType>>(net.GetDeviceId(), nodeName,
|
||||
kernelWidth, kernelHeight,
|
||||
outputChannels,
|
||||
horizontalSubsample,
|
||||
verticalSubsample, zeroPadding,
|
||||
maxTempMemSizeInSamples));
|
||||
kernelWidth, kernelHeight, outputChannels,
|
||||
horizontalSubsample, verticalSubsample, imageLayoutKind,
|
||||
zeroPadding,
|
||||
maxTempMemSizeInSamples));
|
||||
}
|
||||
|
||||
template<class ElemType> shared_ptr<ComputationNode<ElemType>> ComputationNetworkBuilder<ElemType>::CreateMaxPoolingNode(const std::wstring & nodeName,
|
||||
const size_t windowWidth,
|
||||
const size_t windowHeight,
|
||||
const size_t horizontalSubsample,
|
||||
const size_t verticalSubsample)
|
||||
const size_t windowWidth, const size_t windowHeight, const size_t horizontalSubsample, const size_t verticalSubsample, ImageLayoutKind imageLayoutKind)
|
||||
{
|
||||
return net.AddNodeToNetWithElemType(New<MaxPoolingNode<ElemType>>(net.GetDeviceId(), nodeName,
|
||||
windowWidth, windowHeight,
|
||||
horizontalSubsample,
|
||||
verticalSubsample));
|
||||
return net.AddNodeToNetWithElemType(New<MaxPoolingNode<ElemType>>(net.GetDeviceId(), nodeName, windowWidth, windowHeight, horizontalSubsample, verticalSubsample, imageLayoutKind));
|
||||
}
|
||||
|
||||
template<class ElemType> shared_ptr<ComputationNode<ElemType>> ComputationNetworkBuilder<ElemType>::CreateAveragePoolingNode(const std::wstring & nodeName, const size_t windowWidth,
|
||||
const size_t windowHeight, const size_t horizontalSubsample,
|
||||
const size_t verticalSubsample)
|
||||
template<class ElemType> shared_ptr<ComputationNode<ElemType>> ComputationNetworkBuilder<ElemType>::CreateAveragePoolingNode(const std::wstring & nodeName,
|
||||
const size_t windowWidth, const size_t windowHeight, const size_t horizontalSubsample, const size_t verticalSubsample, ImageLayoutKind imageLayoutKind)
|
||||
{
|
||||
return net.AddNodeToNetWithElemType(New<AveragePoolingNode<ElemType>>(net.GetDeviceId(), nodeName,
|
||||
windowWidth, windowHeight,
|
||||
horizontalSubsample,
|
||||
verticalSubsample));
|
||||
return net.AddNodeToNetWithElemType(New<AveragePoolingNode<ElemType>>(net.GetDeviceId(), nodeName, windowWidth, windowHeight, horizontalSubsample, verticalSubsample, imageLayoutKind));
|
||||
}
|
||||
|
||||
// this is the catch-all for all cases not covered as special cases above
|
||||
|
@ -274,49 +263,30 @@ namespace Microsoft { namespace MSR { namespace CNTK {
|
|||
|
||||
template<class ElemType> shared_ptr<ComputationNode<ElemType>> ComputationNetworkBuilder<ElemType>::Convolution(const ComputationNodePtr weight,
|
||||
const ComputationNodePtr inputValues,
|
||||
const size_t kernelWidth,
|
||||
const size_t kernelHeight,
|
||||
const size_t outputChannels,
|
||||
const size_t horizontalSubsample,
|
||||
const size_t verticalSubsample,
|
||||
const bool zeroPadding,
|
||||
const std::wstring nodeName,
|
||||
const size_t maxTempMemSizeInSamples)
|
||||
const size_t kernelWidth, const size_t kernelHeight, const size_t outputChannels, const size_t horizontalSubsample, const size_t verticalSubsample, ImageLayoutKind imageLayoutKind, const bool zeroPadding, const size_t maxTempMemSizeInSamples,
|
||||
const std::wstring nodeName)
|
||||
{
|
||||
return net.AddNodeToNetAndAttachInputs(New<ConvolutionNode<ElemType>>(net.GetDeviceId(), nodeName,
|
||||
kernelWidth, kernelHeight,
|
||||
outputChannels,
|
||||
horizontalSubsample,
|
||||
verticalSubsample, zeroPadding,
|
||||
kernelWidth, kernelHeight, outputChannels, horizontalSubsample, verticalSubsample, imageLayoutKind, zeroPadding,
|
||||
maxTempMemSizeInSamples),
|
||||
weight, inputValues);
|
||||
}
|
||||
|
||||
template<class ElemType> shared_ptr<ComputationNode<ElemType>> ComputationNetworkBuilder<ElemType>::MaxPooling(const ComputationNodePtr inputValues,
|
||||
const size_t windowWidth,
|
||||
const size_t windowHeight,
|
||||
const size_t horizontalSubsample,
|
||||
const size_t verticalSubsample,
|
||||
const size_t windowWidth, const size_t windowHeight, const size_t horizontalSubsample, const size_t verticalSubsample, ImageLayoutKind imageLayoutKind,
|
||||
const std::wstring nodeName)
|
||||
{
|
||||
return net.AddNodeToNetAndAttachInputs(New<MaxPoolingNode<ElemType>>(net.GetDeviceId(), nodeName,
|
||||
windowWidth, windowHeight,
|
||||
horizontalSubsample,
|
||||
verticalSubsample),
|
||||
windowWidth, windowHeight, horizontalSubsample, verticalSubsample, imageLayoutKind),
|
||||
inputValues);
|
||||
}
|
||||
|
||||
template<class ElemType> shared_ptr<ComputationNode<ElemType>> ComputationNetworkBuilder<ElemType>::AveragePooling(const ComputationNodePtr inputValues,
|
||||
const size_t windowWidth,
|
||||
const size_t windowHeight,
|
||||
const size_t horizontalSubsample,
|
||||
const size_t verticalSubsample,
|
||||
const size_t windowWidth, const size_t windowHeight, const size_t horizontalSubsample, const size_t verticalSubsample, ImageLayoutKind imageLayoutKind,
|
||||
const std::wstring nodeName)
|
||||
{
|
||||
return net.AddNodeToNetAndAttachInputs(New<AveragePoolingNode<ElemType>>(net.GetDeviceId(), nodeName,
|
||||
windowWidth, windowHeight,
|
||||
horizontalSubsample,
|
||||
verticalSubsample),
|
||||
windowWidth, windowHeight, horizontalSubsample, verticalSubsample, imageLayoutKind),
|
||||
inputValues);
|
||||
}
|
||||
|
||||
|
|
|
@ -46,9 +46,9 @@ namespace Microsoft { namespace MSR { namespace CNTK {
|
|||
ComputationNodePtr CreateInputNode(const std::wstring & inputName, const TensorShape & imageLayout, const size_t numImages);
|
||||
ComputationNodePtr CreateSparseInputNode(const std::wstring & inputName, const TensorShape & imageLayout, const size_t numImages);
|
||||
ComputationNodePtr CreatePairNetworkNode(const std::wstring & inputName, const size_t rows, const size_t cols);
|
||||
ComputationNodePtr CreateConvolutionNode(const std::wstring & nodeName, const size_t kernelWidth, const size_t kernelHeight, const size_t outputChannels, const size_t horizontalSubsample, const size_t verticalSubsample, const bool zeroPadding = false, const size_t maxTempMemSizeInSamples = 0);
|
||||
ComputationNodePtr CreateMaxPoolingNode(const std::wstring & nodeName, const size_t windowWidth, const size_t windowHeight, const size_t horizontalSubsample, const size_t verticalSubsample);
|
||||
ComputationNodePtr CreateAveragePoolingNode(const std::wstring & nodeName, const size_t windowWidth, const size_t windowHeight, const size_t horizontalSubsample, const size_t verticalSubsample);
|
||||
ComputationNodePtr CreateConvolutionNode(const std::wstring & nodeName, const size_t kernelWidth, const size_t kernelHeight, const size_t outputChannels, const size_t horizontalSubsample, const size_t verticalSubsample, ImageLayoutKind imageLayoutKind, const bool zeroPadding = false, const size_t maxTempMemSizeInSamples = 0);
|
||||
ComputationNodePtr CreateMaxPoolingNode(const std::wstring & nodeName, const size_t windowWidth, const size_t windowHeight, const size_t horizontalSubsample, const size_t verticalSubsample, ImageLayoutKind imageLayoutKind);
|
||||
ComputationNodePtr CreateAveragePoolingNode(const std::wstring & nodeName, const size_t windowWidth, const size_t windowHeight, const size_t horizontalSubsample, const size_t verticalSubsample, ImageLayoutKind imageLayoutKind);
|
||||
// this is the catch-all for all cases not covered as special cases above
|
||||
// Unlike the specialized ones above, this one creates nodes by type given as a string.
|
||||
ComputationNodePtr CreateComputationNode(const std::wstring & nodeType, const std::wstring & nodeName);
|
||||
|
@ -61,25 +61,15 @@ namespace Microsoft { namespace MSR { namespace CNTK {
|
|||
ComputationNodePtr PairNetwork(const ComputationNodePtr & a, const std::wstring nodeName = L"");
|
||||
ComputationNodePtr Convolution(const ComputationNodePtr weight,
|
||||
const ComputationNodePtr inputValues,
|
||||
const size_t kernelWidth,
|
||||
const size_t kernelHeight,
|
||||
const size_t outputChannels,
|
||||
const size_t horizontalSubsample,
|
||||
const size_t verticalSubsample,
|
||||
const bool zeroPadding = false,
|
||||
const std::wstring nodeName = L"",
|
||||
const size_t maxTempMemSizeInSamples = 0);
|
||||
const size_t kernelWidth, const size_t kernelHeight, const size_t outputChannels,
|
||||
const size_t horizontalSubsample, const size_t verticalSubsample, ImageLayoutKind imageLayoutKind,
|
||||
const bool zeroPadding = false, const size_t maxTempMemSizeInSamples = 0,
|
||||
const std::wstring nodeName = L"");
|
||||
ComputationNodePtr MaxPooling(const ComputationNodePtr inputValues,
|
||||
const size_t windowWidth,
|
||||
const size_t windowHeight,
|
||||
const size_t horizontalSubsample,
|
||||
const size_t verticalSubsample,
|
||||
const size_t windowWidth, const size_t windowHeight, const size_t horizontalSubsample, const size_t verticalSubsample, ImageLayoutKind imageLayoutKind,
|
||||
const std::wstring nodeName = L"");
|
||||
ComputationNodePtr AveragePooling(const ComputationNodePtr inputValues,
|
||||
const size_t windowWidth,
|
||||
const size_t windowHeight,
|
||||
const size_t horizontalSubsample,
|
||||
const size_t verticalSubsample,
|
||||
const size_t windowWidth, const size_t windowHeight, const size_t horizontalSubsample, const size_t verticalSubsample, ImageLayoutKind imageLayoutKind,
|
||||
const std::wstring nodeName = L"");
|
||||
ComputationNodePtr ErrorPrediction(const ComputationNodePtr a, const ComputationNodePtr b, const std::wstring nodeName = L"");
|
||||
ComputationNodePtr PerDimMeanVarNormalization(const ComputationNodePtr feature, const ComputationNodePtr mean, const ComputationNodePtr InvStdDev, const std::wstring nodeName = L"");
|
||||
|
|
|
@ -185,9 +185,6 @@ namespace Microsoft {
|
|||
if (m_sampleLayout.GetDim(k) == 0 || m_sampleLayout.GetDim(k) == SIZE_MAX)
|
||||
layoutPlausible = false;
|
||||
}
|
||||
// some code initializes it to (1,1,rowDim)
|
||||
if (m_sampleLayout.GetRank() == 3 && m_sampleLayout.GetDim(0) == 1 && m_sampleLayout.GetDim(1) == 1)
|
||||
layoutPlausible = false;
|
||||
// check dimension
|
||||
if (GetNumRows() != m_sampleLayout.GetNumElements())
|
||||
layoutPlausible = false;
|
||||
|
|
|
@ -504,7 +504,7 @@ namespace Microsoft { namespace MSR { namespace CNTK {
|
|||
|
||||
const char * mbSizeMark = child->m_pMBLayout ? "MBSize " : "";
|
||||
if (child->m_sampleLayout.GetRank() == 3 && (child->m_sampleLayout[1] != 1 || child->m_sampleLayout[0] != 1)) // looks like an image: use WHC notation
|
||||
fprintf(stderr, "%ls[%lu {W=%lu, H=%lu, C=%lu}, %s%lu]", child->NodeName().c_str(), child->GetNumRows(),
|
||||
fprintf(stderr, "%ls[%lu [%s] {W=%lu, H=%lu, C=%lu}, %s%lu]", child->NodeName().c_str(), child->GetNumRows(), string(child->m_sampleLayout).c_str(),
|
||||
child->m_sampleLayout[1], child->m_sampleLayout[2], child->m_sampleLayout[0], mbSizeMark, child->GetNumCols());
|
||||
//BUGBUG: This ^^ will print based on the old legacy layout, and we have no way of knowing here whether that is correct.
|
||||
else if (child->m_sampleLayout.GetRank() > 1) // tensor: output the tensor dimensions --TODO: there will be no numRows in the future, only the tensor
|
||||
|
@ -820,7 +820,7 @@ namespace Microsoft { namespace MSR { namespace CNTK {
|
|||
fstream >> Value();
|
||||
// above reads dimensions, so we must update our own m_numRows/m_numCols
|
||||
SetDims(TensorShape(Value().GetNumRows()), Value().GetNumCols());
|
||||
// BUGBUG: This looses the sample layout (tensor shape). It should be serialized as well.
|
||||
// BUGBUG: This looses the sample layout (tensor shape). The caller must know this and fix it up if needed (currently needed for LearnableParameterNode).
|
||||
}
|
||||
|
||||
// reader updated m_functionValue--update our internal state, i.e. m_numCols
|
||||
|
|
|
@ -72,8 +72,8 @@ namespace Microsoft { namespace MSR { namespace CNTK {
|
|||
{
|
||||
SetDims(ImageDimensions::AsTensorShape(1, 1, 0, m_imageLayoutKind), 0);
|
||||
}
|
||||
ConvolutionNode(DEVICEID_TYPE deviceId, const wstring & name, const size_t kernelWidth, const size_t kernelHeight, const size_t outputChannels, const size_t horizontalSubsample, const size_t verticalSubsample,
|
||||
const bool zeroPadding = false, const size_t maxTempMemSizeInSamples = 0, ImageLayoutKind imageLayoutKind = ImageLayoutKind::HWC) :
|
||||
ConvolutionNode(DEVICEID_TYPE deviceId, const wstring & name, const size_t kernelWidth, const size_t kernelHeight, const size_t outputChannels, const size_t horizontalSubsample, const size_t verticalSubsample, ImageLayoutKind imageLayoutKind,
|
||||
const bool zeroPadding = false, const size_t maxTempMemSizeInSamples = 0) :
|
||||
Base(deviceId, name),
|
||||
m_outputChannels(outputChannels),
|
||||
m_kernelWidth(kernelWidth), m_kernelHeight(kernelHeight),
|
||||
|
@ -86,8 +86,8 @@ namespace Microsoft { namespace MSR { namespace CNTK {
|
|||
}
|
||||
ConvolutionNode(const ScriptableObjects::IConfigRecordPtr configp) :
|
||||
ConvolutionNode(configp->Get(L"deviceId"), L"<placeholder>", configp->Get(L"kernelWidth"), configp->Get(L"kernelHeight"), configp->Get(L"outputChannels"),
|
||||
configp->Get(L"horizontalSubsample"), configp->Get(L"verticalSubsample"),
|
||||
configp->Get(L"zeroPadding"), configp->Get(L"maxTempMemSizeInSamples"), ImageLayoutKindFrom(configp->Get(L"imageLayout")))
|
||||
configp->Get(L"horizontalSubsample"), configp->Get(L"verticalSubsample"), ImageLayoutKindFrom(configp->Get(L"imageLayout")),
|
||||
configp->Get(L"zeroPadding"), configp->Get(L"maxTempMemSizeInSamples"))
|
||||
{
|
||||
// weightNodeName, inputValueNodeName, kernelWidth, kernelHeight, outputChannels, horizontalSubsample, verticalSubsample, zeroPadding = false, maxTempMemSizeInSamples = 0
|
||||
AttachInputs(configp, this->GetExpectedNumInputs());
|
||||
|
@ -338,17 +338,19 @@ namespace Microsoft { namespace MSR { namespace CNTK {
|
|||
PoolingNodeBase(DEVICEID_TYPE deviceId, const wstring & name) :
|
||||
Base(deviceId, name),
|
||||
m_windowWidth(SIZE_MAX), m_windowHeight(SIZE_MAX),
|
||||
m_horizontalSubsample(SIZE_MAX), m_verticalSubsample(SIZE_MAX)
|
||||
m_horizontalSubsample(SIZE_MAX), m_verticalSubsample(SIZE_MAX),
|
||||
m_imageLayoutKind(ImageLayoutKind::HWC)
|
||||
{ }
|
||||
PoolingNodeBase(DEVICEID_TYPE deviceId, const wstring & name, const size_t windowWidth, const size_t windowHeight, const size_t horizontalSubsample, const size_t verticalSubsample) :
|
||||
PoolingNodeBase(DEVICEID_TYPE deviceId, const wstring & name, const size_t windowWidth, const size_t windowHeight, const size_t horizontalSubsample, const size_t verticalSubsample, ImageLayoutKind imageLayoutKind) :
|
||||
Base(deviceId, name),
|
||||
m_windowWidth(windowWidth), m_windowHeight(windowHeight),
|
||||
m_horizontalSubsample(horizontalSubsample), m_verticalSubsample(verticalSubsample)
|
||||
m_horizontalSubsample(horizontalSubsample), m_verticalSubsample(verticalSubsample),
|
||||
m_imageLayoutKind(imageLayoutKind)
|
||||
{
|
||||
m_factory = ConvolutionEngineFactory<ElemType>::Create(deviceId, ConvolutionEngineFactory<ElemType>::EngineType::Auto, ImageLayoutKind::HWC/*m_imageLayoutKind*/);
|
||||
}
|
||||
PoolingNodeBase(const ScriptableObjects::IConfigRecordPtr configp) :
|
||||
PoolingNodeBase(configp->Get(L"deviceId"), L"<placeholder>", configp->Get(L"windowWidth"), configp->Get(L"windowHeight"), configp->Get(L"horizontalSubsample"), configp->Get(L"verticalSubsample"))
|
||||
PoolingNodeBase(configp->Get(L"deviceId"), L"<placeholder>", configp->Get(L"windowWidth"), configp->Get(L"windowHeight"), configp->Get(L"horizontalSubsample"), configp->Get(L"verticalSubsample"), ImageLayoutKindFrom(configp->Get(L"imageLayout")))
|
||||
{
|
||||
// input, windowWidth, windowHeight, horizontalSubsample, verticalSubsample
|
||||
AttachInputs(configp, this->GetExpectedNumInputs());
|
||||
|
@ -357,13 +359,18 @@ namespace Microsoft { namespace MSR { namespace CNTK {
|
|||
void Save(File& fstream) const override
|
||||
{
|
||||
Base::Save(fstream);
|
||||
fstream << m_windowWidth << m_windowHeight << m_horizontalSubsample << m_verticalSubsample;
|
||||
uint32_t imageLayoutKind = (uint32_t)m_imageLayoutKind;
|
||||
uint32_t windowWidth = (uint32_t)m_windowWidth;
|
||||
fstream << imageLayoutKind << windowWidth << m_windowHeight << m_horizontalSubsample << m_verticalSubsample;
|
||||
}
|
||||
|
||||
void Load(File& fstream, size_t modelVersion) override
|
||||
{
|
||||
Base::Load(fstream, modelVersion);
|
||||
fstream >> m_windowWidth >> m_windowHeight >> m_horizontalSubsample >> m_verticalSubsample;
|
||||
uint32_t imageLayoutKind, windowWidth;
|
||||
fstream >> imageLayoutKind >> windowWidth >> m_windowHeight >> m_horizontalSubsample >> m_verticalSubsample;
|
||||
m_windowWidth = windowWidth;
|
||||
m_imageLayoutKind = (ImageLayoutKind)imageLayoutKind;
|
||||
}
|
||||
|
||||
void CopyTo(ComputationNodeBasePtr nodeP, const std::wstring& newName, const CopyNodeFlags flags) const override
|
||||
|
@ -381,6 +388,8 @@ namespace Microsoft { namespace MSR { namespace CNTK {
|
|||
|
||||
node->m_inputSizePerSample = m_inputSizePerSample;
|
||||
node->m_outputSizePerSample = m_outputSizePerSample;
|
||||
|
||||
node->m_imageLayoutKind = m_imageLayoutKind;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -419,7 +428,6 @@ namespace Microsoft { namespace MSR { namespace CNTK {
|
|||
InferMBLayoutFromInputsForStandardCase();
|
||||
|
||||
// get input tensor shape and interpret as image dimensions
|
||||
const auto m_imageLayoutKind = ImageLayoutKind::HWC; // BUGBUG: Finish this. Must be serialized.
|
||||
auto inDims = ImageDimensions(GetInputSampleLayout(0), m_imageLayoutKind);
|
||||
|
||||
if (inDims.m_width < m_windowWidth || inDims.m_height < m_windowHeight)
|
||||
|
@ -450,7 +458,7 @@ namespace Microsoft { namespace MSR { namespace CNTK {
|
|||
if (m_inT == nullptr)
|
||||
m_inT = m_factory->CreateTensor(inDims.m_width, inDims.m_height, inDims.m_numChannels, 1);
|
||||
if (m_outT == nullptr)
|
||||
m_outT = m_factory->CreateTensor(m_sampleLayout[1], m_sampleLayout[2], m_sampleLayout[0], 1);
|
||||
m_outT = m_factory->CreateTensor(outDims.m_width, outDims.m_height, outDims.m_numChannels, 1);
|
||||
}
|
||||
|
||||
void DumpNodeInfo(const bool printValues, File& fstream) const override
|
||||
|
@ -471,16 +479,18 @@ namespace Microsoft { namespace MSR { namespace CNTK {
|
|||
}
|
||||
|
||||
protected:
|
||||
size_t m_windowWidth, m_windowHeight;
|
||||
size_t m_horizontalSubsample, m_verticalSubsample;
|
||||
size_t m_inputSizePerSample, m_outputSizePerSample;
|
||||
|
||||
ImageLayoutKind m_imageLayoutKind; // how to interpret the tensor (which dimensions are X/Y and C)
|
||||
|
||||
std::unique_ptr<ConvolutionEngineFactory<ElemType>> m_factory;
|
||||
std::unique_ptr<PoolingEngine<ElemType>> m_poolEng;
|
||||
|
||||
std::unique_ptr<ConvolutionTensor4D> m_inT;
|
||||
std::unique_ptr<ConvolutionTensor4D> m_outT;
|
||||
std::unique_ptr<PoolingDescriptor> m_poolDesc;
|
||||
|
||||
size_t m_windowWidth, m_windowHeight;
|
||||
size_t m_horizontalSubsample, m_verticalSubsample;
|
||||
size_t m_inputSizePerSample, m_outputSizePerSample;
|
||||
};
|
||||
|
||||
// add this at the start of each derived class, to get access to the members of ComputationNode
|
||||
|
@ -501,8 +511,8 @@ namespace Microsoft { namespace MSR { namespace CNTK {
|
|||
static const std::wstring TypeName() { return L"MaxPooling"; }
|
||||
public:
|
||||
MaxPoolingNode(DEVICEID_TYPE deviceId, const wstring & name) : Base(deviceId, name) { }
|
||||
MaxPoolingNode(DEVICEID_TYPE deviceId, const wstring & name, const size_t windowWidth, const size_t windowHeight, const size_t horizontalSubsample, const size_t verticalSubsample) :
|
||||
Base(deviceId, name, windowWidth, windowHeight, horizontalSubsample, verticalSubsample)
|
||||
MaxPoolingNode(DEVICEID_TYPE deviceId, const wstring & name, const size_t windowWidth, const size_t windowHeight, const size_t horizontalSubsample, const size_t verticalSubsample, ImageLayoutKind imageLayoutKind) :
|
||||
Base(deviceId, name, windowWidth, windowHeight, horizontalSubsample, verticalSubsample, imageLayoutKind)
|
||||
{ }
|
||||
MaxPoolingNode(const ScriptableObjects::IConfigRecordPtr configp) :
|
||||
Base(configp)
|
||||
|
@ -530,8 +540,8 @@ namespace Microsoft { namespace MSR { namespace CNTK {
|
|||
static const std::wstring TypeName() { return L"AveragePooling"; }
|
||||
public:
|
||||
AveragePoolingNode(DEVICEID_TYPE deviceId, const wstring & name) : Base(deviceId, name) { }
|
||||
AveragePoolingNode(DEVICEID_TYPE deviceId, const wstring & name, const size_t windowWidth, const size_t windowHeight, const size_t horizontalSubsample, const size_t verticalSubsample) :
|
||||
Base(deviceId, name, windowWidth, windowHeight, horizontalSubsample, verticalSubsample)
|
||||
AveragePoolingNode(DEVICEID_TYPE deviceId, const wstring & name, const size_t windowWidth, const size_t windowHeight, const size_t horizontalSubsample, const size_t verticalSubsample, ImageLayoutKind imageLayoutKind) :
|
||||
Base(deviceId, name, windowWidth, windowHeight, horizontalSubsample, verticalSubsample, imageLayoutKind)
|
||||
{ }
|
||||
AveragePoolingNode(const ScriptableObjects::IConfigRecordPtr configp) :
|
||||
Base(configp)
|
||||
|
|
|
@ -28,6 +28,7 @@ namespace Microsoft { namespace MSR { namespace CNTK {
|
|||
// -----------------------------------------------------------------------
|
||||
// LearnableParameter (/*no input*/)
|
||||
// represents weight matrices and biases
|
||||
// TODO: add -Node to the class name
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
template<class ElemType>
|
||||
|
@ -96,7 +97,8 @@ namespace Microsoft { namespace MSR { namespace CNTK {
|
|||
{
|
||||
Base::Save(fstream);
|
||||
fstream << m_parameterUpdateRequired;
|
||||
fstream << GetNumRows() << GetNumCols();
|
||||
fstream << (size_t)0/*#rows in a legacy file format*/ << GetNumCols();
|
||||
m_sampleLayout.Save(fstream);
|
||||
fstream << Value();
|
||||
}
|
||||
|
||||
|
@ -108,8 +110,13 @@ namespace Microsoft { namespace MSR { namespace CNTK {
|
|||
fstream >> m_parameterUpdateRequired;
|
||||
fstream >> rows >> cols;
|
||||
|
||||
SetDims(TensorShape(rows), cols);
|
||||
TensorShape sampleLayout;
|
||||
if (rows != 0) // legacy file format
|
||||
sampleLayout = TensorShape(rows);
|
||||
else
|
||||
sampleLayout.Load(fstream);
|
||||
LoadValue(fstream);
|
||||
SetDims(sampleLayout, cols); // note: call this after LoadValue() since LoadValue() overwrites m_sampleLayout
|
||||
}
|
||||
|
||||
// initialize with random numbers
|
||||
|
@ -235,6 +242,7 @@ namespace Microsoft { namespace MSR { namespace CNTK {
|
|||
// InputValueBase (/*no input*/)
|
||||
// Base class for InputValue and SparseInputValue (typically fed by a DataReader)
|
||||
// this covers four types: (regular vs. image) x (non-sparse vs. sparse)
|
||||
// TODO: add -Node to the class names
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
template<class ElemType>
|
||||
|
|
|
@ -70,7 +70,6 @@ train = [
|
|||
hStride1 = 1
|
||||
vStride1 = 1
|
||||
# weight[cMap1, kW1 * kH1 * inputChannels]
|
||||
# ConvReLULayer is defined in Macros.ndl
|
||||
conv1_act = ConvReLULayer(featScaled, cMap1, 25, kW1, kH1, hStride1, vStride1, 10, 1).out
|
||||
|
||||
# pool1
|
||||
|
@ -78,7 +77,7 @@ train = [
|
|||
pool1H = 2
|
||||
pool1hStride = 2
|
||||
pool1vStride = 2
|
||||
pool1 = MaxPooling(conv1_act, pool1W, pool1H, pool1hStride, pool1vStride)
|
||||
pool1 = MaxPooling(conv1_act, pool1W, pool1H, pool1hStride, pool1vStride, imageLayout=if useCuDnn then "cudnn" else "legacy")
|
||||
|
||||
# conv2
|
||||
kW2 = 5
|
||||
|
@ -95,7 +94,7 @@ train = [
|
|||
pool2H = 2
|
||||
pool2hStride = 2
|
||||
pool2vStride = 2
|
||||
pool2 = AveragePooling(conv2_act, pool2W, pool2H, pool2hStride, pool2vStride)
|
||||
pool2 = AveragePooling(conv2_act, pool2W, pool2H, pool2hStride, pool2vStride, imageLayout=if useCuDnn then "cudnn" else "legacy")
|
||||
|
||||
h1Dim = 128
|
||||
# DNNSigmoidLayer and DNNLayer are defined in Macros.ndl
|
||||
|
|
|
@ -60,7 +60,6 @@ fprintf(stderr, "ConvolutionEngineTests.cpp %d\n", __LINE__);
|
|||
for (int deviceId : { 0 })
|
||||
{
|
||||
// BUGBUG: These will fail depending on whether we built with cuDNN or not. Without cuDNN we should use HWC
|
||||
fprintf(stderr, "ConvolutionEngineTests.cpp %d\n", __LINE__);
|
||||
auto fact = ConvFact::Create(deviceId, ConvFact::EngineType::Auto, ImageLayoutKind::CHW);
|
||||
auto tt = typeid(fact).name();
|
||||
UNUSED(tt);
|
||||
|
@ -71,14 +70,12 @@ fprintf(stderr, "ConvolutionEngineTests.cpp %d\n", __LINE__);
|
|||
auto convT = fact->CreateConvDescriptor(*inT, *filtT, sW, sH, false);
|
||||
auto biasT = fact->CreateTensor(1, 1, cmapOut, 1);
|
||||
|
||||
fprintf(stderr, "ConvolutionEngineTests.cpp %d\n", __LINE__);
|
||||
vec buf(inW * inH * cmapIn * n);
|
||||
int seed = 0;
|
||||
// Create input, cmapIn feature maps, inW x inH each (NCHW format).
|
||||
std::generate(buf.begin(), buf.end(), [=, &seed]{ return seed++ % (inW * inH * cmapIn); });
|
||||
SingleMatrix in(inW * inH * cmapIn, n, buf.data(), matrixFlagNormal, deviceId);
|
||||
|
||||
fprintf(stderr, "ConvolutionEngineTests.cpp %d\n", __LINE__);
|
||||
seed = 0;
|
||||
buf.resize(kW * kH * cmapIn * cmapOut);
|
||||
// Create cmapOut filters, each kW x kH x cmapIn (NCHW format).
|
||||
|
@ -88,9 +85,7 @@ fprintf(stderr, "ConvolutionEngineTests.cpp %d\n", __LINE__);
|
|||
SingleMatrix out(outW * outH * cmapOut, n, deviceId);
|
||||
SingleMatrix temp(deviceId);
|
||||
|
||||
fprintf(stderr, "ConvolutionEngineTests.cpp %d\n", __LINE__);
|
||||
eng->Forward(*inT, in, *filtT, filt, *convT, *outT, out, temp);
|
||||
fprintf(stderr, "ConvolutionEngineTests.cpp %d\n", __LINE__);
|
||||
|
||||
// Output is in NCHW format.
|
||||
std::array<float, 4 * 2 * 2> expBuf = {
|
||||
|
@ -100,24 +95,19 @@ fprintf(stderr, "ConvolutionEngineTests.cpp %d\n", __LINE__);
|
|||
15219.0f, 15921.0f, 18729.0f, 19431.0f
|
||||
};
|
||||
SingleMatrix exp(outW * outH * cmapOut, n, expBuf.data(), matrixFlagNormal, deviceId);
|
||||
fprintf(stderr, "ConvolutionEngineTests.cpp %d\n", __LINE__);
|
||||
BOOST_CHECK_MESSAGE(out.IsEqualTo(exp), "Unexpected convolution output.");
|
||||
fprintf(stderr, "ConvolutionEngineTests.cpp %d\n", __LINE__);
|
||||
|
||||
float b[] = { 1.0f, 2.0f };
|
||||
SingleMatrix bias(cmapOut, 1, b, matrixFlagNormal, deviceId);
|
||||
|
||||
SingleMatrix plusB(outW * outH * cmapOut, n, expBuf.data(), matrixFlagNormal, deviceId);
|
||||
fprintf(stderr, "ConvolutionEngineTests.cpp %d\n", __LINE__);
|
||||
eng->AddBias(*outT, out, *biasT, bias, plusB);
|
||||
fprintf(stderr, "ConvolutionEngineTests.cpp %d\n", __LINE__);
|
||||
|
||||
// Bias is per-channel.
|
||||
seed = 0;
|
||||
std::transform(expBuf.begin(), expBuf.end(), expBuf.begin(),
|
||||
[=, &seed, &b](const float& a) { return a + b[(seed++ % (outW * outH * cmapOut)) / (outW * outH)]; });
|
||||
SingleMatrix expPlusB(outW * outH * cmapOut, n, expBuf.data(), matrixFlagNormal, deviceId);
|
||||
fprintf(stderr, "ConvolutionEngineTests.cpp %d\n", __LINE__);
|
||||
BOOST_CHECK_MESSAGE(plusB.IsEqualTo(expPlusB), "Unexpected (convolution + bias) output.");
|
||||
}
|
||||
}
|
||||
|
@ -144,13 +134,20 @@ fprintf(stderr, "ConvolutionEngineTests.cpp %d\n", __LINE__);
|
|||
for (int deviceId : { -1, 0 })
|
||||
{
|
||||
auto fact = ConvFact::Create(deviceId, ConvFact::EngineType::Auto, ImageLayoutKind::CHW);
|
||||
fprintf(stderr, "ConvolutionEngineTests.cpp %d\n", __LINE__);
|
||||
auto eng = fact->CreateConvEngine(deviceId, 0);
|
||||
fprintf(stderr, "ConvolutionEngineTests.cpp %d\n", __LINE__);
|
||||
auto inT = fact->CreateTensor(inW, inH, cmapIn, n);
|
||||
fprintf(stderr, "ConvolutionEngineTests.cpp %d\n", __LINE__);
|
||||
auto filtT = fact->CreateFilter(kW, kH, cmapIn, cmapOut);
|
||||
fprintf(stderr, "ConvolutionEngineTests.cpp %d\n", __LINE__);
|
||||
auto outT = fact->CreateTensor(outW, outH, cmapOut, n);
|
||||
fprintf(stderr, "ConvolutionEngineTests.cpp %d\n", __LINE__);
|
||||
auto convT = fact->CreateConvDescriptor(*inT, *filtT, sW, sH, pad);
|
||||
fprintf(stderr, "ConvolutionEngineTests.cpp %d\n", __LINE__);
|
||||
|
||||
// Input in NCHW format.
|
||||
fprintf(stderr, "ConvolutionEngineTests.cpp %d\n", __LINE__);
|
||||
SingleMatrix in(inW * inH * cmapIn, n, vec(inW * inH * cmapIn * n, 1.0f).data(), matrixFlagNormal, deviceId);
|
||||
// Create cmapOut filters, each kW x kH x cmapIn (NCHW format).
|
||||
SingleMatrix filt(cmapOut, kW * kH * cmapIn, vec(kW * kH * cmapIn * cmapOut, 1.0f).data(), matrixFlagNormal, deviceId);
|
||||
|
@ -158,7 +155,9 @@ fprintf(stderr, "ConvolutionEngineTests.cpp %d\n", __LINE__);
|
|||
SingleMatrix out(outW * outH * cmapOut, n, deviceId);
|
||||
SingleMatrix temp(deviceId);
|
||||
|
||||
fprintf(stderr, "ConvolutionEngineTests.cpp %d\n", __LINE__);
|
||||
eng->Forward(*inT, in, *filtT, filt, *convT, *outT, out, temp);
|
||||
fprintf(stderr, "ConvolutionEngineTests.cpp %d\n", __LINE__);
|
||||
|
||||
// Output is in NCHW format.
|
||||
float expBuf[] = {
|
||||
|
|
Загрузка…
Ссылка в новой задаче