void Variable::SetValue(const NDArrayViewPtr& value) { if (!IsParameter()) LogicError("Variable::SetValue can be only invoked on a Parameter variable!"); else if (GetDataType() != value->GetDataType()) LogicError("Variable::SetValue: 'source' and 'destination' have different data types!"); else if (Shape() != value->Shape() && (AsTensorShape(Shape()) != AsTensorShape(value->Shape()))) LogicError("Variable::SetValue: 'source' and 'destination' have different shapes!"); bool alreadySet = false; if (m_dataFields->m_initValueFlag) { // In the case of lazy initialization, try to avoid the redundant call to the initializer. std::call_once(*m_dataFields->m_initValueFlag, [=, &value, &alreadySet] { // If the variable hasn't been initialized yet, clone the content of the supplied value and delete the initializer. m_dataFields->m_value = value->DeepClone(*m_dataFields->m_valueInitializationDevice, false); m_dataFields->m_valueInitializer = nullptr; m_dataFields->m_valueInitializationDevice = nullptr; alreadySet = true; }); } assert(m_dataFields->m_value != nullptr); if (!alreadySet) { // alreadySet is false, the lambda above wasn't called and the variable has been initialized before, // get a pointer to its value and simply copy the content of the supplied value. m_dataFields->m_value->CopyFrom(*value); } }
NDArrayViewPtr NDArrayView::RandomUniform(const NDShape& shape, double rangeStart, double rangeEnd, unsigned long seed, const DeviceDescriptor& device/* = DeviceDescriptor::DefaultDevice()*/) { auto matrixDims = GetMatrixDimensions(shape); auto randomUniformMatrix = std::make_shared<Matrix<ElementType>>(Matrix<ElementType>::RandomUniform(matrixDims.first, matrixDims.second, AsCNTKImplDeviceId(device), (ElementType)rangeStart, (ElementType)rangeEnd, seed)); auto tensorView = new TensorView<ElementType>(randomUniformMatrix, AsTensorShape(shape)); auto view = new NDArrayView(AsDataType<ElementType>(), device, StorageFormat::Dense, shape, false, tensorView); return NDArrayViewPtr(view, [](_ReferenceCounter* ptr) { delete ptr; }); }
static TensorView<ElementType>* AllocateTensorView(const NDShape& viewShape, CNTK::StorageFormat storageType, const DeviceDescriptor& device) { auto matrixDims = GetMatrixDimensions(viewShape); std::shared_ptr<Matrix<ElementType>> matrix = std::make_shared<Matrix<ElementType>>(matrixDims.first, matrixDims.second, AsCNTKImplDeviceId(device), IsSparseStorageFormat(storageType) ? MatrixType::SPARSE : MatrixType::DENSE, AsCNTKMatrixFormat(storageType)); return new TensorView<ElementType>(matrix, AsTensorShape(viewShape)); }
static TensorView<ElementType>* AllocateTensorView(const NDShape& viewShape, const DeviceDescriptor& device, void* dataBuffer, size_t bufferSizeInBytes) { if (dataBuffer == nullptr) InvalidArgument("Cannot create a NDArrayView over a null data buffer"); if (bufferSizeInBytes < (viewShape.TotalSize() * sizeof(ElementType))) InvalidArgument("Size of the specified buffer for creating the NDArrayView is smaller than the specified view shape"); auto matrixDims = GetMatrixDimensions(viewShape); std::shared_ptr<Matrix<ElementType>> matrix = std::make_shared<Matrix<ElementType>>(matrixDims.first, matrixDims.second, (ElementType*)dataBuffer, AsCNTKImplDeviceId(device), matrixFlagDontOwnBuffer); return new TensorView<ElementType>(matrix, AsTensorShape(viewShape)); }
/*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>(); auto scale = initConfig[ScaleAttributeName].Value<double>(); int outputRank = DefaultParamInitOutputRank, filterRank = DefaultParamInitFilterRank; if (initializerType != Microsoft::MSR::CNTK::UniformInitializerTypeName) { outputRank = (int)initConfig[OutputRankAttributeName].Value<size_t>(); filterRank = (int)initConfig[FilterRankAttributeName].Value<size_t>(); } Microsoft::MSR::CNTK::LearnableParameter<ElementType>::InitRandom(*valueMatrix, AsTensorShape(shape), initializerType, randomSeed, (ElementType)scale, filterRank, outputRank, false, AsCNTKImplDeviceId(device)); } return value; }
/*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; }