void NDMask::MarkSectionAs(const std::vector<size_t>& sectionOffset, const NDShape& sectionShape, MaskKind maskKind) { // TODO: Implement batching of masking operation for masks residing on GPUs to avoid making // GPU invocations for each MaskSection call. if (sectionOffset.size() > m_maskShape.Rank()) LogicError("NDMask::MaskSection: The sectionOffset cannot have dimensionality higher than the rank of 'this' mask"); if (sectionShape.Rank() > m_maskShape.Rank()) LogicError("NDMask::MaskSection: The section shape cannot have an axes count higher than the rank of 'this' mask"); std::vector<size_t> offset(m_maskShape.Rank(), 0); for (size_t i = 0; i < sectionOffset.size(); ++i) offset[i] = sectionOffset[i]; NDShape shape = sectionShape.AppendShape(NDShape(m_maskShape.Rank() - sectionShape.Rank(), NDShape::InferredDimension)); auto maskMatrix = GetMatrix(); size_t rowOffset = offset[0]; size_t colOffset = offset[1]; size_t sliceRowLength = (shape[0] != NDShape::InferredDimension) ? shape[0] : (maskMatrix->GetNumRows() - rowOffset); size_t sliceColLength = (shape[1] != NDShape::InferredDimension) ? shape[1] : (maskMatrix->GetNumCols() - colOffset); if ((rowOffset == 0) && (sliceRowLength == maskMatrix->GetNumRows())) maskMatrix->ColumnSlice(colOffset, sliceColLength).SetValue((char)maskKind); else { // Since Matrix does not support strides in the row dimension, we will need to create separate slices for each column for (size_t i = colOffset; i < (colOffset + sliceColLength); ++i) { auto column = maskMatrix->ColumnSlice(i, 1); column.Reshape(1, maskMatrix->GetNumRows()); column.ColumnSlice(rowOffset, sliceRowLength).SetValue((char)maskKind); } } }
void CheckValue(const ValuePtr testValue, const size_t dimension, const vector<vector<size_t>>& expectedData, const vector<size_t>& seqLenList, const vector<bool>& seqStartFlags = {}) { // Check parameters BOOST_TEST(expectedData.size() == seqLenList.size(), "Parameter error: the sequence number in the exepected data and sequence list does not match."); for (size_t i = 0; i < expectedData.size(); i++) { if (expectedData[i].size() != seqLenList[i]) { ReportFailure("Parameter erroe: the number of data for sequence %" PRIu64 " in the expected data does not match. Expected: %" PRIu64 ", actual: %" PRIu64 ".", i, seqLenList[i], expectedData[i].size()); } } // Check shape NDShape shape = testValue->Shape(); size_t valueRank = shape.Rank(); if (valueRank < 2 || valueRank > 3 || shape[0] != dimension) { ReportFailure("The shape of the value does not match\n"); } size_t numOfSequences = valueRank == 2 ? 1 : shape[2]; if (numOfSequences != expectedData.size()) { ReportFailure("The sequence number in the Value does not match. Expected: %" PRIu64 ", actual: %" PRIu64 ".", expectedData.size(), numOfSequences); } CheckMask(testValue, seqLenList, seqStartFlags); // Get data from Value vector<ElementType> outputData(shape.TotalSize()); NDArrayViewPtr arrayOutput = MakeSharedObject<NDArrayView>(shape, outputData, false); arrayOutput->CopyFrom(*testValue->Data()); size_t maxSeqLen = *max_element(seqLenList.begin(), seqLenList.end()); size_t oIndex = 0; for (size_t seq = 0; seq < seqLenList.size(); seq++) { size_t seqLen = seqLenList[seq]; for (size_t sample = 0; sample < seqLen; sample++) { for (size_t c = 0; c < dimension; c++, oIndex++) { if (outputData[oIndex] != 0) { if (outputData[oIndex] != 1) { ReportFailure("OneHot vector contains value other than 0 and 1 at seqNo=%" PRIu64 " sampleNo=%" PRIu64 " position=%" PRIu64 "\n", seq, sample, c); } if (c != expectedData[seq][sample]) { ReportFailure("OneHot Index does match at seqNo=%" PRIu64 ", sampleNo=%" PRIu64 ", expected: %" PRIu64 ", actual: %" PRIu64 "\n", seq, sample, expectedData[seq][sample], c); } } } } // Skip mask data oIndex += (maxSeqLen - seqLen) * dimension; } }
NDMask::NDMask(const NDShape& shape, const DeviceDescriptor& device) : NDMask(shape, AllocateMatrix(shape, device)) { if (shape.Rank() > 2) LogicError("NDMask instances with more than 2 axes are currently unsupported"); Clear(); }
/*static*/ NDArrayViewPtr Variable::CreateValueFromParameterInitializer(const NDShape& shape, const ParameterInitializer& initConfig, const DeviceDescriptor& device) { auto dataType = AsDataType<ElementType>(); auto value = MakeSharedObject<NDArrayView>(dataType, shape, device); auto valueMatrix = value->template GetWritableMatrix<ElementType>(); auto initializerType = initConfig[InitializerTypeAttributeName].Value<std::wstring>(); if (initializerType == Microsoft::MSR::CNTK::ConstantInitializerTypeName) { auto constantInitValue = initConfig[ValueAttributeName].Value<double>(); valueMatrix->SetValue((ElementType)constantInitValue); } else if (initializerType == Microsoft::MSR::CNTK::BilinearInitializerTypeName) { auto kernelWidth = initConfig[KernelWidthAttributeName].Value<size_t>(); auto kernelHeight = initConfig[KernelHeightAttributeName].Value<size_t>(); Microsoft::MSR::CNTK::LearnableParameter<ElementType>::InitBilinear(*valueMatrix, AsTensorShape(shape), kernelWidth, kernelHeight, AsCNTKImplDeviceId(device)); } else { auto randomSeed = (unsigned long)initConfig[RandomSeedAttributeName].Value<size_t>(); if (randomSeed == SentinelValueForAutoSelectRandomSeed) randomSeed = s_currentRandomSeed++; auto scale = initConfig[ScaleAttributeName].Value<double>(); int outputRank = DefaultParamInitOutputRank, filterRank = DefaultParamInitFilterRank; if (initializerType != Microsoft::MSR::CNTK::UniformInitializerTypeName) { outputRank = initConfig[OutputRankAttributeName].Value<int>(); filterRank = initConfig[FilterRankAttributeName].Value<int>(); if (outputRank == SentinelValueForInferParamInitRank) outputRank = DefaultParamInitOutputRank; if (filterRank == SentinelValueForInferParamInitRank) filterRank = DefaultParamInitFilterRank; if ((filterRank + outputRank) > shape.Rank()) InvalidArgument("Sum of filter rank (%d) and output rank (%d) of the parameter initializer cannot exceed the Parameter's rank(%d)", filterRank, outputRank, (int)shape.Rank()); } Microsoft::MSR::CNTK::LearnableParameter<ElementType>::InitRandom(*valueMatrix, AsTensorShape(shape), initializerType, randomSeed, (ElementType)scale, filterRank, outputRank, /*initOnCPUOnly=*/true, AsCNTKImplDeviceId(device)); } return value; }
void CheckValue(const ValuePtr testValue, const NDShape& sampleShape, const vector<vector<ElementType>>& expectedData, const vector<size_t>& seqLenList, const vector<bool>& seqStartFlags = {}) { size_t sampleSize = sampleShape.TotalSize(); // Check parameters BOOST_TEST(expectedData.size() == seqLenList.size(), "Parameter error: the sequence number in the exepected data and sequence list does not match."); for (size_t i = 0; i < expectedData.size(); i++) { if (expectedData[i].size() != seqLenList[i] * sampleSize) { ReportFailure("Parameter erroe: the number of data for sequence %" PRIu64 " in the expected data does not match. Expected: %" PRIu64 ", actual: %" PRIu64 ".", i, seqLenList[i] * sampleSize, expectedData[i].size()); } } // Check shape auto valueRank = testValue->Shape().Rank(); auto sampleRank = sampleShape.Rank(); auto shapeIsCorrect = !((valueRank < sampleRank + 1) || (valueRank > sampleRank + 2) || (sampleShape != testValue->Shape().SubShape(0, sampleRank))); BOOST_TEST(shapeIsCorrect, "The Value does not have the expected shape."); size_t numOfSequences; if (valueRank == sampleShape.Rank() + 1) { // no batch axis, only sequence axis numOfSequences = 1; } else { assert(valueRank == sampleShape.Rank() + 2); numOfSequences = testValue->Shape()[valueRank - 1]; } if (numOfSequences != expectedData.size()) { ReportFailure("The sequence number in the Value does not match. Expected: %" PRIu64 ", actual: %" PRIu64 ".", expectedData.size(), numOfSequences); } CheckMask(testValue, seqLenList, seqStartFlags); // Get data from Value vector<ElementType> outputData(testValue->Shape().TotalSize()); NDArrayViewPtr arrayOutput = MakeSharedObject<NDArrayView>(testValue->Shape(), outputData, false); arrayOutput->CopyFrom(*testValue->Data()); size_t maxSeqLen = *max_element(seqLenList.begin(), seqLenList.end()); size_t oIndex = 0; for (size_t seq = 0; seq < seqLenList.size(); seq++) { size_t seqLen = seqLenList[seq]; for (size_t sIndex = 0; sIndex < seqLen * sampleSize; sIndex++, oIndex++) { if (expectedData[seq][sIndex] != outputData[oIndex]) { ReportFailure("Data does match at position %" PRIu64 ", expected: %f, actual: %f\n", oIndex, expectedData[seq][sIndex], outputData[oIndex]); } } // Skip mask data oIndex += (maxSeqLen - seqLen) * sampleSize; } }