Merge branch 'master' into ebarsoum/ImageHandsOn

For checkin....
This commit is contained in:
Emad Barsoum 2016-11-03 09:25:52 -07:00
Родитель de7de82ec9 327f6f9213
Коммит bc2b046cdd
19 изменённых файлов: 425 добавлений и 209 удалений

Просмотреть файл

@ -936,12 +936,12 @@ namespace CNTK
CNTK_API static UniqueDynamicAxesNames s_uniqueDynamicAxisNames; CNTK_API static UniqueDynamicAxesNames s_uniqueDynamicAxisNames;
public: public:
CNTK_API static const std::vector<Axis> DefaultInputVariableDynamicAxes; CNTK_API static const std::vector<Axis>& DefaultInputVariableDynamicAxes();
/// ///
/// Axis object representing unknown dynamic axes /// Axis object representing unknown dynamic axes
/// ///
CNTK_API static const std::vector<Axis> UnknownDynamicAxes; CNTK_API static const std::vector<Axis>& UnknownDynamicAxes();
public: public:
/// ///
@ -1548,8 +1548,8 @@ namespace CNTK
typedef Dictionary ParameterInitializer; typedef Dictionary ParameterInitializer;
// Forward declarations // Forward declarations
inline Variable PlaceholderVariable(const NDShape& shape, const std::wstring& name, const std::vector<Axis>& dynamicAxes = Axis::UnknownDynamicAxes); inline Variable PlaceholderVariable(const NDShape& shape, const std::wstring& name, const std::vector<Axis>& dynamicAxes = Axis::UnknownDynamicAxes());
inline Variable InputVariable(const NDShape& shape, bool isSparse, ::CNTK::DataType dataType, bool needsGradient, const std::wstring& name, const std::vector<Axis>& dynamicAxes = Axis::DefaultInputVariableDynamicAxes); inline Variable InputVariable(const NDShape& shape, bool isSparse, ::CNTK::DataType dataType, bool needsGradient, const std::wstring& name, const std::vector<Axis>& dynamicAxes = Axis::DefaultInputVariableDynamicAxes());
inline Variable OutputVariable(const NDShape& shape, ::CNTK::DataType dataType, Function* ownerFunction, const std::vector<Axis>& dynamicAxes, const std::wstring& name = L""); inline Variable OutputVariable(const NDShape& shape, ::CNTK::DataType dataType, Function* ownerFunction, const std::vector<Axis>& dynamicAxes, const std::wstring& name = L"");
/// ///
@ -1578,7 +1578,7 @@ namespace CNTK
#ifndef SWIG #ifndef SWIG
private: private:
friend inline Variable PlaceholderVariable(const NDShape& shape, const std::wstring& name, const std::vector<Axis>& dynamicAxes); friend inline Variable PlaceholderVariable(const NDShape& shape, const std::wstring& name, const std::vector<Axis>& dynamicAxes);
friend inline Variable InputVariable(const NDShape& shape, bool isSparse, ::CNTK::DataType dataType, bool needsGradient, const std::wstring& name, const std::vector<Axis>& dynamicAxes /*= Axis::DefaultInputVariableDynamicAxes*/); friend inline Variable InputVariable(const NDShape& shape, bool isSparse, ::CNTK::DataType dataType, bool needsGradient, const std::wstring& name, const std::vector<Axis>& dynamicAxes /*= Axis::DefaultInputVariableDynamicAxes()*/);
friend inline Variable OutputVariable(const NDShape& shape, ::CNTK::DataType dataType, Function* ownerFunction, const std::vector<Axis>& dynamicAxes, const std::wstring& name /*= L""*/); friend inline Variable OutputVariable(const NDShape& shape, ::CNTK::DataType dataType, Function* ownerFunction, const std::vector<Axis>& dynamicAxes, const std::wstring& name /*= L""*/);
#endif #endif
@ -1812,7 +1812,7 @@ private:
/// Create a Placeholder variable to be used as a temporary/placeholder input to a Function. /// Create a Placeholder variable to be used as a temporary/placeholder input to a Function.
/// All placeholder inputs of a Function must be replaced with non-placeholder Variables before Forward evaluation of the Function. /// All placeholder inputs of a Function must be replaced with non-placeholder Variables before Forward evaluation of the Function.
/// ///
inline Variable PlaceholderVariable(const NDShape& shape, const std::vector<Axis>& dynamicAxes = Axis::UnknownDynamicAxes) inline Variable PlaceholderVariable(const NDShape& shape, const std::vector<Axis>& dynamicAxes = Axis::UnknownDynamicAxes())
{ {
return PlaceholderVariable(shape, L"", dynamicAxes); return PlaceholderVariable(shape, L"", dynamicAxes);
} }
@ -1823,13 +1823,13 @@ private:
/// ///
inline Variable PlaceholderVariable(const std::wstring& name = L"") inline Variable PlaceholderVariable(const std::wstring& name = L"")
{ {
return PlaceholderVariable(NDShape::Unknown, name, Axis::UnknownDynamicAxes); return PlaceholderVariable(NDShape::Unknown, name, Axis::UnknownDynamicAxes());
} }
/// ///
/// Create an 'Input' Variable denoting sparse data and specify if gradients are to be computed for this input /// Create an 'Input' Variable denoting sparse data and specify if gradients are to be computed for this input
/// ///
inline Variable InputVariable(const NDShape& shape, bool isSparse, ::CNTK::DataType dataType, bool needsGradient, const std::wstring& name /*= L""*/, const std::vector<Axis>& dynamicAxes /*= Axis::DefaultInputVariableDynamicAxes*/) inline Variable InputVariable(const NDShape& shape, bool isSparse, ::CNTK::DataType dataType, bool needsGradient, const std::wstring& name /*= L""*/, const std::vector<Axis>& dynamicAxes /*= Axis::DefaultInputVariableDynamicAxes()*/)
{ {
return Variable(shape, isSparse, dataType, needsGradient, name, dynamicAxes, Internal::GenerateUid(VariableKind::Input)); return Variable(shape, isSparse, dataType, needsGradient, name, dynamicAxes, Internal::GenerateUid(VariableKind::Input));
} }
@ -1837,7 +1837,7 @@ private:
/// ///
/// Create an 'Input' Variable and specify if gradients are to be computed for this input /// Create an 'Input' Variable and specify if gradients are to be computed for this input
/// ///
inline Variable InputVariable(const NDShape& shape, ::CNTK::DataType dataType, bool needsGradient, const std::wstring& name = L"", const std::vector<Axis>& dynamicAxes = Axis::DefaultInputVariableDynamicAxes) inline Variable InputVariable(const NDShape& shape, ::CNTK::DataType dataType, bool needsGradient, const std::wstring& name = L"", const std::vector<Axis>& dynamicAxes = Axis::DefaultInputVariableDynamicAxes())
{ {
return InputVariable(shape, /*isSparse =*/ false, dataType, needsGradient, name, dynamicAxes); return InputVariable(shape, /*isSparse =*/ false, dataType, needsGradient, name, dynamicAxes);
} }
@ -1845,7 +1845,7 @@ private:
/// ///
/// Create an 'Input' Variable. /// Create an 'Input' Variable.
/// ///
inline Variable InputVariable(const NDShape& shape, DataType dataType, const std::wstring& name, const std::vector<Axis>& dynamicAxes = Axis::DefaultInputVariableDynamicAxes) inline Variable InputVariable(const NDShape& shape, DataType dataType, const std::wstring& name, const std::vector<Axis>& dynamicAxes = Axis::DefaultInputVariableDynamicAxes())
{ {
return InputVariable(shape, dataType, /*needsGradient =*/ false, name, dynamicAxes); return InputVariable(shape, dataType, /*needsGradient =*/ false, name, dynamicAxes);
} }
@ -1853,7 +1853,7 @@ private:
/// ///
/// Create an 'Input' Variable. /// Create an 'Input' Variable.
/// ///
inline Variable InputVariable(const NDShape& shape, DataType dataType, const wchar_t* name, const std::vector<Axis>& dynamicAxes = Axis::DefaultInputVariableDynamicAxes) inline Variable InputVariable(const NDShape& shape, DataType dataType, const wchar_t* name, const std::vector<Axis>& dynamicAxes = Axis::DefaultInputVariableDynamicAxes())
{ {
return InputVariable(shape, dataType, std::wstring(name), dynamicAxes); return InputVariable(shape, dataType, std::wstring(name), dynamicAxes);
} }
@ -1861,7 +1861,7 @@ private:
/// ///
/// Create an 'Input' Variable. /// Create an 'Input' Variable.
/// ///
inline Variable InputVariable(const NDShape& shape, DataType dataType, const std::vector<Axis>& dynamicAxes = Axis::DefaultInputVariableDynamicAxes) inline Variable InputVariable(const NDShape& shape, DataType dataType, const std::vector<Axis>& dynamicAxes = Axis::DefaultInputVariableDynamicAxes())
{ {
return InputVariable(shape, dataType, L"", dynamicAxes); return InputVariable(shape, dataType, L"", dynamicAxes);
} }
@ -1869,7 +1869,7 @@ private:
/// ///
/// Create an 'Input' Variable denoting sparse data. /// Create an 'Input' Variable denoting sparse data.
/// ///
inline Variable InputVariable(const NDShape& shape, bool isSparse, ::CNTK::DataType dataType, const std::wstring& name, const std::vector<Axis>& dynamicAxes = Axis::DefaultInputVariableDynamicAxes) inline Variable InputVariable(const NDShape& shape, bool isSparse, ::CNTK::DataType dataType, const std::wstring& name, const std::vector<Axis>& dynamicAxes = Axis::DefaultInputVariableDynamicAxes())
{ {
return InputVariable(shape, isSparse, dataType, /*needsGradient =*/ false, name, dynamicAxes); return InputVariable(shape, isSparse, dataType, /*needsGradient =*/ false, name, dynamicAxes);
} }
@ -1877,7 +1877,7 @@ private:
/// ///
/// Create an 'Input' Variable denoting sparse data. /// Create an 'Input' Variable denoting sparse data.
/// ///
inline Variable InputVariable(const NDShape& shape, bool isSparse, ::CNTK::DataType dataType, const wchar_t* name, const std::vector<Axis>& dynamicAxes = Axis::DefaultInputVariableDynamicAxes) inline Variable InputVariable(const NDShape& shape, bool isSparse, ::CNTK::DataType dataType, const wchar_t* name, const std::vector<Axis>& dynamicAxes = Axis::DefaultInputVariableDynamicAxes())
{ {
return InputVariable(shape, isSparse, dataType, std::wstring(name), dynamicAxes); return InputVariable(shape, isSparse, dataType, std::wstring(name), dynamicAxes);
} }
@ -1885,7 +1885,7 @@ private:
/// ///
/// Create an 'Input' Variable denoting sparse data. /// Create an 'Input' Variable denoting sparse data.
/// ///
inline Variable InputVariable(const NDShape& shape, bool isSparse, ::CNTK::DataType dataType, const std::vector<Axis>& dynamicAxes = Axis::DefaultInputVariableDynamicAxes) inline Variable InputVariable(const NDShape& shape, bool isSparse, ::CNTK::DataType dataType, const std::vector<Axis>& dynamicAxes = Axis::DefaultInputVariableDynamicAxes())
{ {
return InputVariable(shape, isSparse, dataType, L"", dynamicAxes); return InputVariable(shape, isSparse, dataType, L"", dynamicAxes);
} }

Просмотреть файл

@ -253,4 +253,4 @@ namespace CNTK
std::unordered_map<::CNTK::Variable, ::CNTK::Variable>& placeholderReplacements, std::unordered_map<::CNTK::Variable, ::CNTK::Variable>& placeholderReplacements,
std::unordered_set<::CNTK::FunctionPtr>& allPrimitiveFunctions); std::unordered_set<::CNTK::FunctionPtr>& allPrimitiveFunctions);
} }
} }

Просмотреть файл

@ -267,7 +267,8 @@ namespace CNTK
/*static*/ DeviceDescriptor DeviceDescriptor::DefaultDevice() /*static*/ DeviceDescriptor DeviceDescriptor::DefaultDevice()
{ {
std::call_once(s_initDefaultDeviceFlag, [=]{ std::call_once(s_initDefaultDeviceFlag, []
{
s_defaultDevice.reset(new DeviceDescriptor(DeviceDescriptor::BestDevice())); s_defaultDevice.reset(new DeviceDescriptor(DeviceDescriptor::BestDevice()));
}); });
return *s_defaultDevice; return *s_defaultDevice;
@ -293,7 +294,8 @@ namespace CNTK
if (!Internal::IsSettingDefaultDeviceAlwaysAllowed() && s_defaultDeviceFrozen.load()) if (!Internal::IsSettingDefaultDeviceAlwaysAllowed() && s_defaultDeviceFrozen.load())
RuntimeError("Process wide default device cannot be changed since it has been frozen by being implicitly used as the default device in a CNTK API call"); RuntimeError("Process wide default device cannot be changed since it has been frozen by being implicitly used as the default device in a CNTK API call");
std::call_once(s_initDefaultDeviceFlag, []{ std::call_once(s_initDefaultDeviceFlag, []
{
// do nothing. This will set the flag above, in case when DefaultDevice() was never called before. // do nothing. This will set the flag above, in case when DefaultDevice() was never called before.
}); });
@ -313,7 +315,8 @@ namespace CNTK
{ {
using namespace Microsoft::MSR::CNTK; using namespace Microsoft::MSR::CNTK;
std::call_once(s_initAllDevicesFlag, [=]{ std::call_once(s_initAllDevicesFlag, []
{
s_allDevices.reset(new std::vector<DeviceDescriptor>()); s_allDevices.reset(new std::vector<DeviceDescriptor>());
#ifndef CPUONLY #ifndef CPUONLY
auto allGpusData = GetAllGpusData(); auto allGpusData = GetAllGpusData();
@ -352,8 +355,26 @@ namespace CNTK
/*static*/ Axis::UniqueDynamicAxesNames Axis::s_uniqueDynamicAxisNames; /*static*/ Axis::UniqueDynamicAxesNames Axis::s_uniqueDynamicAxisNames;
/*static*/ const std::vector<Axis> Axis::DefaultInputVariableDynamicAxes = { Axis::DefaultDynamicAxis(), Axis::DefaultBatchAxis() }; static std::shared_ptr<std::vector<Axis>> s_defaultInputVariableDynamicAxes, s_unknownDynamicAxes;
/*static*/ const std::vector<Axis> Axis::UnknownDynamicAxes = { Axis(SentinelStaticAxisIndexValueForUnknownAxes) }; static std::once_flag s_initDefaultInputVariableDynamicAxesFlag, s_initUnknownDynamicAxesFlag;
/*static*/ const std::vector<Axis>& Axis::DefaultInputVariableDynamicAxes()
{
std::call_once(s_initDefaultInputVariableDynamicAxesFlag, []
{
s_defaultInputVariableDynamicAxes.reset(new std::vector<Axis>({ Axis::DefaultDynamicAxis(), Axis::DefaultBatchAxis() }));
});
return *s_defaultInputVariableDynamicAxes;
}
/*static*/ const std::vector<Axis>& Axis::UnknownDynamicAxes()
{
std::call_once(s_initUnknownDynamicAxesFlag, []
{
s_unknownDynamicAxes.reset(new std::vector<Axis>({ Axis(SentinelStaticAxisIndexValueForUnknownAxes) }));
});
return *s_unknownDynamicAxes;
}
/*static*/ const Axis& Axis::DefaultDynamicAxis() /*static*/ const Axis& Axis::DefaultDynamicAxis()
{ {

Просмотреть файл

@ -92,7 +92,7 @@ namespace CNTK
if (var.Shape().IsUnknown() && !placeholder.Shape().IsUnknown()) if (var.Shape().IsUnknown() && !placeholder.Shape().IsUnknown())
var.m_dataFields->m_shape = placeholder.Shape(); var.m_dataFields->m_shape = placeholder.Shape();
if ((var.DynamicAxes() == Axis::UnknownDynamicAxes) && (placeholder.DynamicAxes() != Axis::UnknownDynamicAxes)) if ((var.DynamicAxes() == Axis::UnknownDynamicAxes()) && (placeholder.DynamicAxes() != Axis::UnknownDynamicAxes()))
var.m_dataFields->m_dynamicAxes = placeholder.DynamicAxes(); var.m_dataFields->m_dynamicAxes = placeholder.DynamicAxes();
} }
} }
@ -164,7 +164,7 @@ namespace CNTK
currentOutputVar.m_dataFields->m_dataType = newOutputVar.GetDataType(); currentOutputVar.m_dataFields->m_dataType = newOutputVar.GetDataType();
} }
if ((currentOutputVar.DynamicAxes() == Axis::UnknownDynamicAxes) && (currentOutputVar.DynamicAxes() != newOutputVar.DynamicAxes())) if ((currentOutputVar.DynamicAxes() == Axis::UnknownDynamicAxes()) && (currentOutputVar.DynamicAxes() != newOutputVar.DynamicAxes()))
{ {
recurrentNodeOutputModified = true; recurrentNodeOutputModified = true;
currentOutputVar.m_dataFields->m_dynamicAxes = newOutputVar.DynamicAxes(); currentOutputVar.m_dataFields->m_dynamicAxes = newOutputVar.DynamicAxes();
@ -172,7 +172,7 @@ namespace CNTK
if ((!newOutputVar.Shape().IsUnknown() && (currentOutputVar.Shape() != newOutputVar.Shape())) || if ((!newOutputVar.Shape().IsUnknown() && (currentOutputVar.Shape() != newOutputVar.Shape())) ||
((newOutputVar.GetDataType() != DataType::Unknown) && (currentOutputVar.GetDataType() != newOutputVar.GetDataType())) || ((newOutputVar.GetDataType() != DataType::Unknown) && (currentOutputVar.GetDataType() != newOutputVar.GetDataType())) ||
((newOutputVar.DynamicAxes() != Axis::UnknownDynamicAxes) && (currentOutputVar.DynamicAxes() != newOutputVar.DynamicAxes()))) ((newOutputVar.DynamicAxes() != Axis::UnknownDynamicAxes()) && (currentOutputVar.DynamicAxes() != newOutputVar.DynamicAxes())))
{ {
InvalidArgument("Inconsistency in output variable shape, DataType or Dynamic axes computed after replaced placeholders vs. existing output properties, for the Recurrent Function"); InvalidArgument("Inconsistency in output variable shape, DataType or Dynamic axes computed after replaced placeholders vs. existing output properties, for the Recurrent Function");
} }
@ -642,13 +642,13 @@ namespace CNTK
auto allInputDynamicAxesEmpty = std::find_if(inputs.begin(), inputs.end(), [](const Variable& input) { return !input.DynamicAxes().empty(); }) == inputs.end(); auto allInputDynamicAxesEmpty = std::find_if(inputs.begin(), inputs.end(), [](const Variable& input) { return !input.DynamicAxes().empty(); }) == inputs.end();
if (!allInputDynamicAxesEmpty) if (!allInputDynamicAxesEmpty)
{ {
outputDynamicAxes = Axis::UnknownDynamicAxes; outputDynamicAxes = Axis::UnknownDynamicAxes();
for (auto inputVar : inputs) for (auto inputVar : inputs)
{ {
auto currentInputDynamicAxes = inputVar.DynamicAxes(); auto currentInputDynamicAxes = inputVar.DynamicAxes();
if (!currentInputDynamicAxes.empty() && (currentInputDynamicAxes != Axis::UnknownDynamicAxes)) if (!currentInputDynamicAxes.empty() && (currentInputDynamicAxes != Axis::UnknownDynamicAxes()))
{ {
if (outputDynamicAxes == Axis::UnknownDynamicAxes) if (outputDynamicAxes == Axis::UnknownDynamicAxes())
outputDynamicAxes = currentInputDynamicAxes; outputDynamicAxes = currentInputDynamicAxes;
else else
{ {
@ -808,7 +808,7 @@ namespace CNTK
Variable initialStateVar = inputs[1]; Variable initialStateVar = inputs[1];
// TODO: We currently only support input operand with 1 dynamic axis for PastValue/FutureValue // TODO: We currently only support input operand with 1 dynamic axis for PastValue/FutureValue
if ((inputOperandVar.DynamicAxes() != Axis::UnknownDynamicAxes) && (inputOperandVar.DynamicAxes().size() != 2)) if ((inputOperandVar.DynamicAxes() != Axis::UnknownDynamicAxes()) && (inputOperandVar.DynamicAxes().size() != 2))
LogicError("Currently PastValue/FutureValue Function only supports input operand with 2 dynamic axis (1 sequence-axis and 1 batch-axis)"); LogicError("Currently PastValue/FutureValue Function only supports input operand with 2 dynamic axis (1 sequence-axis and 1 batch-axis)");
if (!initialStateVar.DynamicAxes().empty()) if (!initialStateVar.DynamicAxes().empty())
@ -1322,7 +1322,7 @@ namespace CNTK
if (variable.Shape().HasInferredDimension()) if (variable.Shape().HasInferredDimension())
InvalidArgument("Variable%S with InferredDimension for at least one axis in its shape, detected when compiling the Function graph!", ParanthesizedName(variable.Name()).c_str()); InvalidArgument("Variable%S with InferredDimension for at least one axis in its shape, detected when compiling the Function graph!", ParanthesizedName(variable.Name()).c_str());
if (variable.DynamicAxes() == Axis::UnknownDynamicAxes) if (variable.DynamicAxes() == Axis::UnknownDynamicAxes())
InvalidArgument("Variable%S with unknown dynamic axes detected when compiling the Function graph!", ParanthesizedName(variable.Name()).c_str()); InvalidArgument("Variable%S with unknown dynamic axes detected when compiling the Function graph!", ParanthesizedName(variable.Name()).c_str());
// Lets add a null entry in the map for this variable, to break infinite recursion when processing recurrent graphs // Lets add a null entry in the map for this variable, to break infinite recursion when processing recurrent graphs

Просмотреть файл

@ -2,7 +2,7 @@
//%feature("autodoc", "1"); //%feature("autodoc", "1");
%include "stl.i" %include "stl.i"
%include "std_wstring.i" %include "std_wstring.i"
%include <std_vector.i> %include <std_vector.i>
%include <std_map.i> %include <std_map.i>
%include <std_set.i> %include <std_set.i>
@ -74,9 +74,210 @@
// //
%feature("shadow") CNTK::Variable::DynamicAxes %{ %feature("shadow") CNTK::Variable::DynamicAxes %{
def dynamic_axes(self): def dynamic_axes(self):
return tuple(reversed($action(self))) return ($action(self))[::-1]
%} %}
%fragment("NDShapeToTuple", "header")
{
PyObject *NDShapeToTuple(const CNTK::NDShape& shape)
{
size_t rank = shape.Rank();
auto result = PyTuple_New(rank);
for (size_t i=0; i<rank; i++)
{
size_t dim = (&shape)->operator[](i);
PyTuple_SetItem(result, i, PyInt_FromLong(dim));
}
return result;
}
}
%fragment("NDArrayViewToNumPy", "header")
{
PyObject* NDArrayViewToNumPy(const CNTK::NDArrayView* self) {
if ((*self).GetStorageFormat() != StorageFormat::Dense)
throw std::invalid_argument("only dense supported at the moment");
// FIXME use not yet existing NDShape function that returns the dimensions at once
std::vector<size_t> dimensions_cntk = (*self).Shape().Dimensions();
std::vector<size_t> dimensions;
// We have at least one element. In case the shape is empty (e.g.
// '()'), we have a scalar, which we need to copy (e.g. a constant).
size_t num_elements = 1;
// CNTK uses column major, thus we reverse the shape
for (int i=dimensions_cntk.size()-1; i>=0; i--)
{
dimensions.push_back(dimensions_cntk[i]);
num_elements *= dimensions_cntk[i];
}
npy_intp* shape = reinterpret_cast<npy_intp*>(&dimensions[0]);
CNTK::DataType cntk_type = (*self).GetDataType();
NDArrayView* cpuView;
if ((*self).Device() != DeviceDescriptor::CPUDevice())
{
cpuView = new NDArrayView(cntk_type, (*self).Shape(), DeviceDescriptor::CPUDevice());
cpuView->CopyFrom((*self));
}
else
{
cpuView = const_cast<NDArrayView*>(&(*self));
}
NPY_TYPES numpy_type;
void* buffer;
if (cntk_type == CNTK::DataType::Float)
{
numpy_type = NPY_FLOAT;
buffer = (void*)cpuView->DataBuffer<float>();
}
else if (cntk_type == CNTK::DataType::Double)
{
numpy_type = NPY_DOUBLE;
buffer = (void*)cpuView->DataBuffer<double>();
}
else
{
throw std::invalid_argument("unknown CNTK data type");
}
PyObject* ndarray = PyArray_SimpleNew(dimensions.size(), shape, numpy_type);
void *arr_data = PyArray_DATA((PyArrayObject*)ndarray);
memcpy(arr_data, buffer, PyArray_ITEMSIZE((PyArrayObject*) ndarray) * num_elements);
if ((*self).Device() != DeviceDescriptor::CPUDevice())
{
delete cpuView;
}
return ndarray;
}
}
%fragment("DictionaryValueToPy", "header", fragment="NDShapeToTuple", fragment="NDArrayViewToNumPy")
{
PyObject *DictionaryValueToPy(const CNTK::DictionaryValue& dictVal)
{
PyObject *val = nullptr;
switch (dictVal.ValueType())
{
case CNTK::DictionaryValue::Type::None:
Py_INCREF(Py_None);
val = Py_None;
break;
case CNTK::DictionaryValue::Type::Bool:
val = PyBool_FromLong(static_cast<long>(dictVal.Value<bool>()));
break;
case CNTK::DictionaryValue::Type::Int:
val = PyLong_FromLong(static_cast<long>(dictVal.Value<int>()));
break;
case CNTK::DictionaryValue::Type::SizeT:
val = PyLong_FromSize_t(dictVal.Value<size_t>());
break;
case CNTK::DictionaryValue::Type::Float:
val = PyFloat_FromDouble(static_cast<double>(dictVal.Value<float>()));
break;
case CNTK::DictionaryValue::Type::Double:
val = PyFloat_FromDouble(dictVal.Value<double>());
break;
case CNTK::DictionaryValue::Type::String:
val = PyUnicode_FromWideChar(dictVal.Value<std::wstring>().c_str(), dictVal.Value<std::wstring>().length());
break;
case CNTK::DictionaryValue::Type::NDShape:
val = NDShapeToTuple(dictVal.Value<CNTK::NDShape>());
break;
case CNTK::DictionaryValue::Type::Axis:
val = PyTuple_New(3);
if (val == NULL)
{
SWIG_exception(SWIG_RuntimeError, "error creating tuple for axis");
}
if (dictVal.Value<CNTK::Axis>().IsOrdered())
PyTuple_SetItem(val, 0, PyUnicode_FromWideChar(L"ordered", 7));
else
PyTuple_SetItem(val, 0, PyUnicode_FromWideChar(L"unordered", 9));
if (dictVal.Value<CNTK::Axis>().IsDynamicAxis())
{
PyTuple_SetItem(val, 1, PyUnicode_FromWideChar(L"dynamic", 7));
PyTuple_SetItem(val, 2, PyUnicode_FromWideChar(
dictVal.Value<CNTK::Axis>().Name().c_str(),
dictVal.Value<CNTK::Axis>().Name().length()));
}
else
{
PyTuple_SetItem(val, 1, PyUnicode_FromWideChar(L"static", 6));
PyTuple_SetItem(val, 2, PyLong_FromLong(
static_cast<long>(
dictVal.Value<CNTK::Axis>().StaticAxisIndex(true)
)));
}
break;
case CNTK::DictionaryValue::Type::Vector:
val = PyList_New(0);
if (val == NULL)
{
SWIG_exception(SWIG_RuntimeError, "error creating list");
}
for (auto it: dictVal.Value<std::vector<CNTK::DictionaryValue> >())
{
PyObject* tmp = DictionaryValueToPy(it);
PyList_Append(val, tmp);
Py_DECREF(tmp);
}
break;
case CNTK::DictionaryValue::Type::Dictionary:
val = PyDict_New();
if (val == NULL)
{
SWIG_exception(SWIG_RuntimeError, "error creating dict");
}
for (auto it = dictVal.Value<CNTK::Dictionary>().begin(); it != dictVal.Value<CNTK::Dictionary>().end(); ++it)
{
PyObject *key = PyUnicode_FromWideChar(it->first.c_str(), it->first.length());
PyObject *dvp = DictionaryValueToPy(it->second);
PyDict_SetItem(val, key, dvp);
Py_DECREF(key);
Py_DECREF(val);
}
break;
case CNTK::DictionaryValue::Type::NDArrayView:
val = NDArrayViewToNumPy(&(dictVal.Value<CNTK::NDArrayView>()));
break;
default:
SWIG_exception(SWIG_RuntimeError, "unknown type for DictionaryValue object");
break;
}
return val;
fail:
return NULL;
}
}
%typemap(out, fragment="DictionaryValueToPy") const CNTK::Dictionary& Attributes(){
PyObject* container = PyDict_New();
if (container == NULL)
{
SWIG_exception(SWIG_RuntimeError, "error passing dictionary to Python");
}
for (auto it = $1->begin(); it != $1->end(); ++it)
{
PyObject *key = PyUnicode_FromWideChar(it->first.c_str(), it->first.length());
PyObject *val = DictionaryValueToPy(it->second);
PyDict_SetItem(container, key, val);
Py_DECREF(key);
Py_DECREF(val);
}
$result = container;
}
%define %eq_for(DATA_TYPE, EQ) %define %eq_for(DATA_TYPE, EQ)
%rename(EQ) operator==(const DATA_TYPE&, const DATA_TYPE&); %rename(EQ) operator==(const DATA_TYPE&, const DATA_TYPE&);
%enddef %enddef
@ -98,6 +299,12 @@ def dynamic_axes(self):
} }
} }
%extend CNTK::Axis {
bool __eq__(const CNTK::Axis& other) const {
return *$self == other;
}
}
%{ %{
#include "CNTKLibrary.h" #include "CNTKLibrary.h"
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
@ -122,8 +329,8 @@ def dynamic_axes(self):
} }
// //
// NDShape // NDShape
// //
%typecheck(1000) CNTK::NDShape const &, CNTK::NDShape { %typecheck(1000) CNTK::NDShape const &, CNTK::NDShape {
// '1000' is the typecheck precedence code. It means: check after basic // '1000' is the typecheck precedence code. It means: check after basic
@ -152,14 +359,8 @@ def dynamic_axes(self):
%ignore CNTK::NDShape::AppendShape; %ignore CNTK::NDShape::AppendShape;
%ignore CNTK::NDShape::Dimensions; %ignore CNTK::NDShape::Dimensions;
%typemap(out) CNTK::NDShape { %typemap(out, fragment="NDShapeToTuple") CNTK::NDShape {
size_t rank = $1.Rank(); $result = NDShapeToTuple($1);
$result = PyTuple_New(rank);
for (size_t i=0; i<rank; i++)
{
size_t dim = (&$1)->operator[](i);
PyTuple_SET_ITEM($result, i, PyInt_FromLong(dim));
}
} }
%extend CNTK::NDShape { %extend CNTK::NDShape {
@ -173,7 +374,7 @@ def dynamic_axes(self):
return (*self)[rank-1-i]; return (*self)[rank-1-i];
} }
PyObject* dimensions() { PyObject* dimensions() {
std::vector<size_t> dims = (*self).Dimensions(); std::vector<size_t> dims = (*self).Dimensions();
size_t rank = (*self).Rank(); size_t rank = (*self).Rank();
PyObject* result = PyTuple_New(rank); PyObject* result = PyTuple_New(rank);
@ -181,7 +382,7 @@ def dynamic_axes(self):
for (size_t i=0; i<rank; i++) for (size_t i=0; i<rank; i++)
{ {
size_t dim = dims[i]; size_t dim = dims[i];
PyTuple_SET_ITEM(result, rank-1-i, PyInt_FromLong(dim)); PyTuple_SET_ITEM(result, rank-1-i, PyInt_FromLong(dim));
} }
return result; return result;
} }
@ -199,7 +400,7 @@ def dynamic_axes(self):
//%constant long CNTK::NDShape::InferredDimension = -1; //%constant long CNTK::NDShape::InferredDimension = -1;
%constant long InferredDimension = -1; %constant long InferredDimension = -1;
// end of NDShape // end of NDShape
// //
// Converting Python dictionary {Variable: ValuePtr} to std::unordered_map // Converting Python dictionary {Variable: ValuePtr} to std::unordered_map
@ -222,7 +423,7 @@ def dynamic_axes(self):
void *raw_var = 0 ; void *raw_var = 0 ;
int res1 = SWIG_ConvertPtr(key, &raw_var, SWIGTYPE_p_CNTK__Variable, 0); int res1 = SWIG_ConvertPtr(key, &raw_var, SWIGTYPE_p_CNTK__Variable, 0);
if (!SWIG_IsOK(res1)) { if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "cannot convert key of dictionary to CNTK::Variable"); SWIG_exception_fail(SWIG_ArgError(res1), "cannot convert key of dictionary to CNTK::Variable");
} }
if (!raw_var) { if (!raw_var) {
SWIG_exception_fail(SWIG_ValueError, "invalid null reference when converting key of dictionary to CNTK::Variable"); SWIG_exception_fail(SWIG_ValueError, "invalid null reference when converting key of dictionary to CNTK::Variable");
@ -233,7 +434,7 @@ def dynamic_axes(self):
void *raw_value = 0; void *raw_value = 0;
int res2 = SWIG_ConvertPtr(value, &raw_value, SWIGTYPE_p_std__shared_ptrT_CNTK__Value_t, 0); int res2 = SWIG_ConvertPtr(value, &raw_value, SWIGTYPE_p_std__shared_ptrT_CNTK__Value_t, 0);
if (!SWIG_IsOK(res2)) { if (!SWIG_IsOK(res2)) {
SWIG_exception_fail(SWIG_ArgError(res2), "cannot convert value of dictionary to CNTK::ValuePtr"); SWIG_exception_fail(SWIG_ArgError(res2), "cannot convert value of dictionary to CNTK::ValuePtr");
} }
CNTK::ValuePtr* value; CNTK::ValuePtr* value;
@ -266,7 +467,7 @@ def dynamic_axes(self):
void *raw_var = 0 ; void *raw_var = 0 ;
int res1 = SWIG_ConvertPtr(key, &raw_var, SWIGTYPE_p_CNTK__Variable, 0); int res1 = SWIG_ConvertPtr(key, &raw_var, SWIGTYPE_p_CNTK__Variable, 0);
if (!SWIG_IsOK(res1)) { if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "cannot convert key of dictionary to CNTK::Variable"); SWIG_exception_fail(SWIG_ArgError(res1), "cannot convert key of dictionary to CNTK::Variable");
} }
if (!raw_var) { if (!raw_var) {
SWIG_exception_fail(SWIG_ValueError, "invalid null reference when converting key of dictionary to CNTK::Variable"); SWIG_exception_fail(SWIG_ValueError, "invalid null reference when converting key of dictionary to CNTK::Variable");
@ -277,7 +478,7 @@ def dynamic_axes(self):
void *raw_value = 0; void *raw_value = 0;
int res2 = SWIG_ConvertPtr(value, &raw_value, SWIGTYPE_p_std__shared_ptrT_CNTK__Value_t, 0); int res2 = SWIG_ConvertPtr(value, &raw_value, SWIGTYPE_p_std__shared_ptrT_CNTK__Value_t, 0);
if (!SWIG_IsOK(res2)) { if (!SWIG_IsOK(res2)) {
SWIG_exception_fail(SWIG_ArgError(res2), "cannot convert value of dictionary to CNTK::ValuePtr"); SWIG_exception_fail(SWIG_ArgError(res2), "cannot convert value of dictionary to CNTK::ValuePtr");
} }
CNTK::ValuePtr* value; CNTK::ValuePtr* value;
@ -300,10 +501,10 @@ def dynamic_axes(self):
// modified values and put them back into the dictionary. This is used, when // modified values and put them back into the dictionary. This is used, when
// e.g. the user puts a variable into the dictionary, hoping that it will // e.g. the user puts a variable into the dictionary, hoping that it will
// afterwards point to the proper value. // afterwards point to the proper value.
%typemap(argout) %typemap(argout)
// Swig would create this conversion for the 'const' variants as well, which // Swig would create this conversion for the 'const' variants as well, which
// we do not want. Therefor, we have to explicitly tell it for which ones it should do it. // we do not want. Therefor, we have to explicitly tell it for which ones it should do it.
std::unordered_map<CNTK::Variable, CNTK::ValuePtr>& outputsToFetch, std::unordered_map<CNTK::Variable, CNTK::ValuePtr>& outputsToFetch,
std::unordered_map<CNTK::Variable, CNTK::ValuePtr>& outputs, std::unordered_map<CNTK::Variable, CNTK::ValuePtr>& outputs,
std::unordered_map<CNTK::Variable, CNTK::ValuePtr>& backPropagatedGradientValuesForInputs std::unordered_map<CNTK::Variable, CNTK::ValuePtr>& backPropagatedGradientValuesForInputs
{ {
@ -338,7 +539,7 @@ def dynamic_axes(self):
void *cntk_key = 0 ; void *cntk_key = 0 ;
int res = SWIG_ConvertPtr(py_key, &cntk_key, SWIGTYPE_p_CNTK__Variable, 0); int res = SWIG_ConvertPtr(py_key, &cntk_key, SWIGTYPE_p_CNTK__Variable, 0);
if (!SWIG_IsOK(res)) { if (!SWIG_IsOK(res)) {
SWIG_exception_fail(SWIG_ArgError(res), "cannot convert key of dictionary to CNTK::Variable"); SWIG_exception_fail(SWIG_ArgError(res), "cannot convert key of dictionary to CNTK::Variable");
} }
if (!cntk_key) { if (!cntk_key) {
SWIG_exception_fail(SWIG_ValueError, "invalid null reference when converting key of dictionary to CNTK::Variable"); SWIG_exception_fail(SWIG_ValueError, "invalid null reference when converting key of dictionary to CNTK::Variable");
@ -376,7 +577,7 @@ def dynamic_axes(self):
void *raw_var = 0 ; void *raw_var = 0 ;
int res1 = SWIG_ConvertPtr(key, &raw_var, SWIGTYPE_p_CNTK__StreamInformation, 0); int res1 = SWIG_ConvertPtr(key, &raw_var, SWIGTYPE_p_CNTK__StreamInformation, 0);
if (!SWIG_IsOK(res1)) { if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "cannot convert key of dictionary to CNTK::StreamInformation"); SWIG_exception_fail(SWIG_ArgError(res1), "cannot convert key of dictionary to CNTK::StreamInformation");
} }
if (!raw_var) { if (!raw_var) {
SWIG_exception_fail(SWIG_ValueError, "invalid null reference when converting key of dictionary to CNTK::StreamInformation"); SWIG_exception_fail(SWIG_ValueError, "invalid null reference when converting key of dictionary to CNTK::StreamInformation");
@ -388,14 +589,14 @@ def dynamic_axes(self):
if (PyTuple_Check(value)) { if (PyTuple_Check(value)) {
PyObject* first = PyTuple_GET_ITEM(value, 0); PyObject* first = PyTuple_GET_ITEM(value, 0);
size_t first_val = PyLong_AsSize_t(first); size_t first_val = PyLong_AsSize_t(first);
PyObject* second = PyTuple_GET_ITEM(value, 1); PyObject* second = PyTuple_GET_ITEM(value, 1);
size_t second_val = PyLong_AsSize_t(second); size_t second_val = PyLong_AsSize_t(second);
args_map.insert(std::make_pair(*var, std::make_pair(first_val, second_val))); args_map.insert(std::make_pair(*var, std::make_pair(first_val, second_val)));
} else { } else {
SWIG_exception(SWIG_TypeError, "tuple expected"); SWIG_exception(SWIG_TypeError, "tuple expected");
} }
} }
$1 = &args_map; $1 = &args_map;
@ -411,7 +612,7 @@ def dynamic_axes(self):
} }
%typemap(in) std::unordered_map<CNTK::StreamInformation, std::pair<CNTK::NDArrayViewPtr, CNTK::NDArrayViewPtr>>& ( %typemap(in) std::unordered_map<CNTK::StreamInformation, std::pair<CNTK::NDArrayViewPtr, CNTK::NDArrayViewPtr>>& (
std::unordered_map<CNTK::StreamInformation, std::pair<CNTK::NDArrayViewPtr, CNTK::NDArrayViewPtr>> args_map std::unordered_map<CNTK::StreamInformation, std::pair<CNTK::NDArrayViewPtr, CNTK::NDArrayViewPtr>> args_map
){ ){
if (PyDict_Check($input)) { if (PyDict_Check($input)) {
@ -422,20 +623,20 @@ def dynamic_axes(self):
void *raw_var = 0 ; void *raw_var = 0 ;
int res = SWIG_ConvertPtr(key, &raw_var, SWIGTYPE_p_CNTK__StreamInformation, 0); int res = SWIG_ConvertPtr(key, &raw_var, SWIGTYPE_p_CNTK__StreamInformation, 0);
if (!SWIG_IsOK(res)) { if (!SWIG_IsOK(res)) {
SWIG_exception_fail(SWIG_ArgError(res), "cannot convert key of dictionary to CNTK::StreamInformation"); SWIG_exception_fail(SWIG_ArgError(res), "cannot convert key of dictionary to CNTK::StreamInformation");
} }
if (!raw_var) { if (!raw_var) {
SWIG_exception_fail(SWIG_ValueError, "invalid null reference when converting key of dictionary to CNTK::StreamInformation"); SWIG_exception_fail(SWIG_ValueError, "invalid null reference when converting key of dictionary to CNTK::StreamInformation");
} }
CNTK::StreamInformation* var = reinterpret_cast<CNTK::StreamInformation*>(raw_var); CNTK::StreamInformation* var = reinterpret_cast<CNTK::StreamInformation*>(raw_var);
if (PyTuple_Check(value)) { if (PyTuple_Check(value)) {
PyObject* first = PyTuple_GET_ITEM(value, 0); PyObject* first = PyTuple_GET_ITEM(value, 0);
void *raw_value1 = 0; void *raw_value1 = 0;
int res1 = SWIG_ConvertPtr(first, &raw_value1, SWIGTYPE_p_std__shared_ptrT_CNTK__NDArrayView_t, 0); int res1 = SWIG_ConvertPtr(first, &raw_value1, SWIGTYPE_p_std__shared_ptrT_CNTK__NDArrayView_t, 0);
if (!SWIG_IsOK(res1)) { if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "cannot convert value of dictionary to CNTK::NDArrayViewPtr"); SWIG_exception_fail(SWIG_ArgError(res1), "cannot convert value of dictionary to CNTK::NDArrayViewPtr");
} }
CNTK::NDArrayViewPtr* value1; CNTK::NDArrayViewPtr* value1;
@ -446,11 +647,11 @@ def dynamic_axes(self):
value1 = new CNTK::NDArrayViewPtr(); value1 = new CNTK::NDArrayViewPtr();
} }
PyObject* second = PyTuple_GET_ITEM(value, 1); PyObject* second = PyTuple_GET_ITEM(value, 1);
void *raw_value2 = 0; void *raw_value2 = 0;
int res2 = SWIG_ConvertPtr(second, &raw_value2, SWIGTYPE_p_std__shared_ptrT_CNTK__NDArrayView_t, 0); int res2 = SWIG_ConvertPtr(second, &raw_value2, SWIGTYPE_p_std__shared_ptrT_CNTK__NDArrayView_t, 0);
if (!SWIG_IsOK(res2)) { if (!SWIG_IsOK(res2)) {
SWIG_exception_fail(SWIG_ArgError(res2), "cannot convert value of dictionary to CNTK::NDArrayViewPtr"); SWIG_exception_fail(SWIG_ArgError(res2), "cannot convert value of dictionary to CNTK::NDArrayViewPtr");
} }
CNTK::NDArrayViewPtr* value2; CNTK::NDArrayViewPtr* value2;
@ -464,7 +665,7 @@ def dynamic_axes(self):
args_map.insert(std::make_pair(*var, std::make_pair(*value1, *value2))); args_map.insert(std::make_pair(*var, std::make_pair(*value1, *value2)));
} else { } else {
SWIG_exception(SWIG_TypeError, "tuple expected"); SWIG_exception(SWIG_TypeError, "tuple expected");
} }
} }
$1 = &args_map; $1 = &args_map;
@ -509,7 +710,7 @@ def dynamic_axes(self):
void *cntk_key = 0 ; void *cntk_key = 0 ;
int res = SWIG_ConvertPtr(py_key, &cntk_key, SWIGTYPE_p_CNTK__StreamInformation, 0); int res = SWIG_ConvertPtr(py_key, &cntk_key, SWIGTYPE_p_CNTK__StreamInformation, 0);
if (!SWIG_IsOK(res)) { if (!SWIG_IsOK(res)) {
SWIG_exception_fail(SWIG_ArgError(res), "cannot convert key of dictionary to CNTK::StreamInformation"); SWIG_exception_fail(SWIG_ArgError(res), "cannot convert key of dictionary to CNTK::StreamInformation");
} }
if (!cntk_key) { if (!cntk_key) {
SWIG_exception_fail(SWIG_ValueError, "invalid null reference when converting key of dictionary to CNTK::StreamInformation"); SWIG_exception_fail(SWIG_ValueError, "invalid null reference when converting key of dictionary to CNTK::StreamInformation");
@ -547,7 +748,7 @@ def dynamic_axes(self):
void *raw_var = 0 ; void *raw_var = 0 ;
int res1 = SWIG_ConvertPtr(key, &raw_var, SWIGTYPE_p_CNTK__Parameter, 0); int res1 = SWIG_ConvertPtr(key, &raw_var, SWIGTYPE_p_CNTK__Parameter, 0);
if (!SWIG_IsOK(res1)) { if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "cannot convert key of dictionary to CNTK::Parameter"); SWIG_exception_fail(SWIG_ArgError(res1), "cannot convert key of dictionary to CNTK::Parameter");
} }
if (!raw_var) { if (!raw_var) {
SWIG_exception_fail(SWIG_ValueError, "invalid null reference when converting key of dictionary to CNTK::Parameter"); SWIG_exception_fail(SWIG_ValueError, "invalid null reference when converting key of dictionary to CNTK::Parameter");
@ -558,7 +759,7 @@ def dynamic_axes(self):
void *raw_value = 0; void *raw_value = 0;
int res2 = SWIG_ConvertPtr(value, &raw_value, SWIGTYPE_p_std__shared_ptrT_CNTK__NDArrayView_t, 0); int res2 = SWIG_ConvertPtr(value, &raw_value, SWIGTYPE_p_std__shared_ptrT_CNTK__NDArrayView_t, 0);
if (!SWIG_IsOK(res2)) { if (!SWIG_IsOK(res2)) {
SWIG_exception_fail(SWIG_ArgError(res2), "cannot convert value of dictionary to CNTK::NDArrayViewPtr"); SWIG_exception_fail(SWIG_ArgError(res2), "cannot convert value of dictionary to CNTK::NDArrayViewPtr");
} }
CNTK::NDArrayViewPtr* value; CNTK::NDArrayViewPtr* value;
@ -595,14 +796,14 @@ def dynamic_axes(self):
PyObject *iterator = PyObject_GetIter($input); PyObject *iterator = PyObject_GetIter($input);
if (iterator == NULL) { if (iterator == NULL) {
SWIG_exception_fail(SWIG_ValueError, "cannot convert list element to CNTK::DictionaryValue"); SWIG_exception_fail(SWIG_ValueError, "cannot convert list element to CNTK::DictionaryValue");
} }
while ((item = PyIter_Next(iterator))) { while ((item = PyIter_Next(iterator))) {
void *raw_var = 0 ; void *raw_var = 0 ;
int res1 = SWIG_ConvertPtr(item, &raw_var, SWIGTYPE_p_CNTK__DictionaryValue, 0); int res1 = SWIG_ConvertPtr(item, &raw_var, SWIGTYPE_p_CNTK__DictionaryValue, 0);
if (!SWIG_IsOK(res1)) { if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "cannot convert list element to CNTK::DictionaryValue"); SWIG_exception_fail(SWIG_ArgError(res1), "cannot convert list element to CNTK::DictionaryValue");
} }
if (!raw_var) { if (!raw_var) {
SWIG_exception_fail(SWIG_ValueError, "invalid null reference when converting a list element to CNTK::DictionaryValue"); SWIG_exception_fail(SWIG_ValueError, "invalid null reference when converting a list element to CNTK::DictionaryValue");
@ -618,7 +819,7 @@ def dynamic_axes(self):
Py_DECREF(iterator); Py_DECREF(iterator);
if (PyErr_Occurred()) { if (PyErr_Occurred()) {
SWIG_exception_fail(SWIG_ValueError, "cannot convert list element to CNTK::DictionaryValue"); SWIG_exception_fail(SWIG_ValueError, "cannot convert list element to CNTK::DictionaryValue");
} }
$1 = vec; $1 = vec;
@ -642,7 +843,7 @@ def dynamic_axes(self):
} }
%typemap(in) std::unordered_set<CNTK::Variable>& ( %typemap(in) std::unordered_set<CNTK::Variable>& (
std::unordered_set<CNTK::Variable> args_set std::unordered_set<CNTK::Variable> args_set
) { ) {
if (PySet_Check($input)) { if (PySet_Check($input)) {
@ -650,14 +851,14 @@ def dynamic_axes(self):
PyObject *iterator = PyObject_GetIter($input); PyObject *iterator = PyObject_GetIter($input);
if (iterator == NULL) { if (iterator == NULL) {
SWIG_exception_fail(SWIG_ValueError, "cannot convert list element to CNTK::Variable"); SWIG_exception_fail(SWIG_ValueError, "cannot convert list element to CNTK::Variable");
} }
while ((item = PyIter_Next(iterator))) { while ((item = PyIter_Next(iterator))) {
void *raw_var = 0 ; void *raw_var = 0 ;
int res1 = SWIG_ConvertPtr(item, &raw_var, SWIGTYPE_p_CNTK__Variable, 0); int res1 = SWIG_ConvertPtr(item, &raw_var, SWIGTYPE_p_CNTK__Variable, 0);
if (!SWIG_IsOK(res1)) { if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "cannot convert set element to CNTK::Variable"); SWIG_exception_fail(SWIG_ArgError(res1), "cannot convert set element to CNTK::Variable");
} }
if (!raw_var) { if (!raw_var) {
SWIG_exception_fail(SWIG_ValueError, "invalid null reference when converting a list element to CNTK::Variable"); SWIG_exception_fail(SWIG_ValueError, "invalid null reference when converting a list element to CNTK::Variable");
@ -673,7 +874,7 @@ def dynamic_axes(self):
Py_DECREF(iterator); Py_DECREF(iterator);
if (PyErr_Occurred()) { if (PyErr_Occurred()) {
SWIG_exception_fail(SWIG_ValueError, "cannot convert set element to CNTK::Variable"); SWIG_exception_fail(SWIG_ValueError, "cannot convert set element to CNTK::Variable");
} }
$1 = &args_set; $1 = &args_set;
@ -693,7 +894,7 @@ def dynamic_axes(self):
} }
%typemap(in) std::unordered_set<CNTK::StreamInformation>& ( %typemap(in) std::unordered_set<CNTK::StreamInformation>& (
std::unordered_set<CNTK::StreamInformation> args_set std::unordered_set<CNTK::StreamInformation> args_set
) { ) {
if (PySet_Check($input)) { if (PySet_Check($input)) {
@ -701,14 +902,14 @@ def dynamic_axes(self):
PyObject *iterator = PyObject_GetIter($input); PyObject *iterator = PyObject_GetIter($input);
if (iterator == NULL) { if (iterator == NULL) {
SWIG_exception_fail(SWIG_ValueError, "cannot convert list element to CNTK::StreamInformation"); SWIG_exception_fail(SWIG_ValueError, "cannot convert list element to CNTK::StreamInformation");
} }
while ((item = PyIter_Next(iterator))) { while ((item = PyIter_Next(iterator))) {
void *raw_var = 0 ; void *raw_var = 0 ;
int res1 = SWIG_ConvertPtr(item, &raw_var, SWIGTYPE_p_CNTK__StreamInformation, 0); int res1 = SWIG_ConvertPtr(item, &raw_var, SWIGTYPE_p_CNTK__StreamInformation, 0);
if (!SWIG_IsOK(res1)) { if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "cannot convert set element to CNTK::StreamInformation"); SWIG_exception_fail(SWIG_ArgError(res1), "cannot convert set element to CNTK::StreamInformation");
} }
if (!raw_var) { if (!raw_var) {
SWIG_exception_fail(SWIG_ValueError, "invalid null reference when converting a set element to CNTK::StreamInformation"); SWIG_exception_fail(SWIG_ValueError, "invalid null reference when converting a set element to CNTK::StreamInformation");
@ -724,7 +925,7 @@ def dynamic_axes(self):
Py_DECREF(iterator); Py_DECREF(iterator);
if (PyErr_Occurred()) { if (PyErr_Occurred()) {
SWIG_exception_fail(SWIG_ValueError, "cannot convert set element to CNTK::StreamInformation"); SWIG_exception_fail(SWIG_ValueError, "cannot convert set element to CNTK::StreamInformation");
} }
$1 = &args_set; $1 = &args_set;
@ -744,7 +945,7 @@ def dynamic_axes(self):
} }
%typemap(in) std::unordered_set<CNTK::Parameter>& ( %typemap(in) std::unordered_set<CNTK::Parameter>& (
std::unordered_set<CNTK::Parameter> args_set std::unordered_set<CNTK::Parameter> args_set
) { ) {
if (PyList_Check($input)) { if (PyList_Check($input)) {
@ -752,14 +953,14 @@ def dynamic_axes(self):
PyObject *iterator = PyObject_GetIter($input); PyObject *iterator = PyObject_GetIter($input);
if (iterator == NULL) { if (iterator == NULL) {
SWIG_exception_fail(SWIG_ValueError, "cannot convert list element to CNTK::Parameter"); SWIG_exception_fail(SWIG_ValueError, "cannot convert list element to CNTK::Parameter");
} }
while ((item = PyIter_Next(iterator))) { while ((item = PyIter_Next(iterator))) {
void *raw_var = 0 ; void *raw_var = 0 ;
int res1 = SWIG_ConvertPtr(item, &raw_var, SWIGTYPE_p_CNTK__Parameter, 0); int res1 = SWIG_ConvertPtr(item, &raw_var, SWIGTYPE_p_CNTK__Parameter, 0);
if (!SWIG_IsOK(res1)) { if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "cannot convert set element to CNTK::Parameter"); SWIG_exception_fail(SWIG_ArgError(res1), "cannot convert set element to CNTK::Parameter");
} }
if (!raw_var) { if (!raw_var) {
SWIG_exception_fail(SWIG_ValueError, "invalid null reference when converting a list element to CNTK::Parameter"); SWIG_exception_fail(SWIG_ValueError, "invalid null reference when converting a list element to CNTK::Parameter");
@ -775,7 +976,7 @@ def dynamic_axes(self):
Py_DECREF(iterator); Py_DECREF(iterator);
if (PyErr_Occurred()) { if (PyErr_Occurred()) {
SWIG_exception_fail(SWIG_ValueError, "cannot convert set element to CNTK::Parameter"); SWIG_exception_fail(SWIG_ValueError, "cannot convert set element to CNTK::Parameter");
} }
$1 = &args_set; $1 = &args_set;
@ -796,7 +997,7 @@ def dynamic_axes(self):
} }
%typemap(in) std::unordered_set<CNTK::LearnerPtr>& ( %typemap(in) std::unordered_set<CNTK::LearnerPtr>& (
std::unordered_set<CNTK::LearnerPtr> args_set std::unordered_set<CNTK::LearnerPtr> args_set
) { ) {
if (PyList_Check($input)) { if (PyList_Check($input)) {
@ -804,14 +1005,14 @@ def dynamic_axes(self):
PyObject *iterator = PyObject_GetIter($input); PyObject *iterator = PyObject_GetIter($input);
if (iterator == NULL) { if (iterator == NULL) {
SWIG_exception_fail(SWIG_ValueError, "cannot convert list element to CNTK::LearnerPtr"); SWIG_exception_fail(SWIG_ValueError, "cannot convert list element to CNTK::LearnerPtr");
} }
while ((item = PyIter_Next(iterator))) { while ((item = PyIter_Next(iterator))) {
void *raw_var = 0 ; void *raw_var = 0 ;
int res1 = SWIG_ConvertPtr(item, &raw_var, SWIGTYPE_p_std__shared_ptrT_CNTK__Learner_t, 0); int res1 = SWIG_ConvertPtr(item, &raw_var, SWIGTYPE_p_std__shared_ptrT_CNTK__Learner_t, 0);
if (!SWIG_IsOK(res1)) { if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "cannot convert list element to CNTK::LearnerPtr"); SWIG_exception_fail(SWIG_ArgError(res1), "cannot convert list element to CNTK::LearnerPtr");
} }
if (!raw_var) { if (!raw_var) {
SWIG_exception_fail(SWIG_ValueError, "invalid null reference when converting a list element to CNTK::LearnerPtr"); SWIG_exception_fail(SWIG_ValueError, "invalid null reference when converting a list element to CNTK::LearnerPtr");
@ -827,7 +1028,7 @@ def dynamic_axes(self):
Py_DECREF(iterator); Py_DECREF(iterator);
if (PyErr_Occurred()) { if (PyErr_Occurred()) {
SWIG_exception_fail(SWIG_ValueError, "cannot convert list element to CNTK::LearnerPtr"); SWIG_exception_fail(SWIG_ValueError, "cannot convert list element to CNTK::LearnerPtr");
} }
$1 = &args_set; $1 = &args_set;
@ -845,7 +1046,7 @@ def dynamic_axes(self):
%typemap(in) std::unordered_map<CNTK::Variable, CNTK::Variable>& ( %typemap(in) std::unordered_map<CNTK::Variable, CNTK::Variable>& (
std::unordered_map<CNTK::Variable, CNTK::Variable> args_map std::unordered_map<CNTK::Variable, CNTK::Variable> args_map
) { ) {
if (PyDict_Check($input)) { if (PyDict_Check($input)) {
@ -856,7 +1057,7 @@ def dynamic_axes(self):
void *raw_var = 0 ; void *raw_var = 0 ;
int res1 = SWIG_ConvertPtr(key, &raw_var, SWIGTYPE_p_CNTK__Variable, 0); int res1 = SWIG_ConvertPtr(key, &raw_var, SWIGTYPE_p_CNTK__Variable, 0);
if (!SWIG_IsOK(res1)) { if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "cannot convert key of dictionary to CNTK::Variable"); SWIG_exception_fail(SWIG_ArgError(res1), "cannot convert key of dictionary to CNTK::Variable");
} }
if (!raw_var) { if (!raw_var) {
SWIG_exception_fail(SWIG_ValueError, "invalid null reference when converting key of dictionary to CNTK::Variable"); SWIG_exception_fail(SWIG_ValueError, "invalid null reference when converting key of dictionary to CNTK::Variable");
@ -867,7 +1068,7 @@ def dynamic_axes(self):
void *raw_value = 0; void *raw_value = 0;
int res2 = SWIG_ConvertPtr(value, &raw_value, SWIGTYPE_p_CNTK__Variable, 0); int res2 = SWIG_ConvertPtr(value, &raw_value, SWIGTYPE_p_CNTK__Variable, 0);
if (!SWIG_IsOK(res2)) { if (!SWIG_IsOK(res2)) {
SWIG_exception_fail(SWIG_ArgError(res2), "cannot convert value of dictionary to CNTK::Variable"); SWIG_exception_fail(SWIG_ArgError(res2), "cannot convert value of dictionary to CNTK::Variable");
} }
CNTK::Variable* value; CNTK::Variable* value;
@ -903,9 +1104,9 @@ def dynamic_axes(self):
{ {
SWIG_exception(SWIG_RuntimeError, "error passing set to Python"); SWIG_exception(SWIG_RuntimeError, "error passing set to Python");
} }
// *&$1 -> $1 is the returned result being converted (unordered_set<...>*), // *&$1 -> $1 is the returned result being converted (unordered_set<...>*),
// wrapped by SwigValueWrapper. So we need to unwrap it using '&', // wrapped by SwigValueWrapper. So we need to unwrap it using '&',
// then access its value using '*'. // then access its value using '*'.
for (auto var : *&$1) for (auto var : *&$1)
{ {
@ -918,7 +1119,7 @@ def dynamic_axes(self):
$result = container; $result = container;
} }
%enddef %enddef
%unordered_set_conversion(Variable, SWIGTYPE_p_CNTK__Variable) %unordered_set_conversion(Variable, SWIGTYPE_p_CNTK__Variable)
%unordered_set_conversion(Constant, SWIGTYPE_p_CNTK__Constant) %unordered_set_conversion(Constant, SWIGTYPE_p_CNTK__Constant)
%unordered_set_conversion(Parameter, SWIGTYPE_p_CNTK__Parameter) %unordered_set_conversion(Parameter, SWIGTYPE_p_CNTK__Parameter)
@ -932,7 +1133,7 @@ def dynamic_axes(self):
{ {
SWIG_exception(SWIG_RuntimeError, "error passing set to Python"); SWIG_exception(SWIG_RuntimeError, "error passing set to Python");
} }
for (auto var : *$1) for (auto var : *$1)
{ {
PyObject *item = SWIG_NewPointerObj(new CNTK::DATA_TYPE(var), _SWIG_TYPE, SWIG_POINTER_OWN ); PyObject *item = SWIG_NewPointerObj(new CNTK::DATA_TYPE(var), _SWIG_TYPE, SWIG_POINTER_OWN );
@ -960,16 +1161,16 @@ def dynamic_axes(self):
{ {
SWIG_exception(SWIG_RuntimeError, "error passing dictionary to Python"); SWIG_exception(SWIG_RuntimeError, "error passing dictionary to Python");
} }
// *&$1 -> $1 is the returned result being converted (unordered_map<...>*), // *&$1 -> $1 is the returned result being converted (unordered_map<...>*),
// wrapped by SwigValueWrapper. So we need to unwrap it using '&', // wrapped by SwigValueWrapper. So we need to unwrap it using '&',
// then access its value using '*'. // then access its value using '*'.
for (auto it : *$1) for (auto it : *$1)
{ {
PyObject *returned_var = SWIG_NewPointerObj(SWIG_as_voidptr(new CNTK::DATA_TYPE1(it.first)), _SWIG_TYPE1, SWIG_POINTER_OWN); PyObject *returned_var = SWIG_NewPointerObj(SWIG_as_voidptr(new CNTK::DATA_TYPE1(it.first)), _SWIG_TYPE1, SWIG_POINTER_OWN);
PyObject *returned_val = SWIG_NewPointerObj(SWIG_as_voidptr(new CNTK::DATA_TYPE2(it.second)), _SWIG_TYPE2, SWIG_POINTER_OWN); PyObject *returned_val = SWIG_NewPointerObj(SWIG_as_voidptr(new CNTK::DATA_TYPE2(it.second)), _SWIG_TYPE2, SWIG_POINTER_OWN);
PyDict_SetItem(container, returned_var, returned_val); PyDict_SetItem(container, returned_var, returned_val);
Py_DECREF(returned_var); Py_DECREF(returned_var);
Py_DECREF(returned_val); Py_DECREF(returned_val);
@ -1024,7 +1225,7 @@ def dynamic_axes(self):
} }
void* buffer = const_cast<void*>(reinterpret_cast<const void*>(cpuMask->DataBuffer())); void* buffer = const_cast<void*>(reinterpret_cast<const void*>(cpuMask->DataBuffer()));
PyObject* ndarray = PyArray_SimpleNew(dimensions.size(), shape, NPY_BYTE); PyObject* ndarray = PyArray_SimpleNew(dimensions.size(), shape, NPY_BYTE);
void *arr_data = PyArray_DATA((PyArrayObject*)ndarray); void *arr_data = PyArray_DATA((PyArrayObject*)ndarray);
@ -1046,20 +1247,20 @@ def dynamic_axes(self):
// //
%extend CNTK::NDArrayView { %extend CNTK::NDArrayView {
NDArrayView(PyObject* pyobj, const CNTK::DeviceDescriptor& device, bool readOnly) NDArrayView(PyObject* pyobj, const CNTK::DeviceDescriptor& device, bool readOnly)
{ {
if (!PyArray_Check((PyArrayObject*)pyobj)) if (!PyArray_Check((PyArrayObject*)pyobj))
{ {
// Note that in contrast to numpy.i's implementation we demand NumPy arrays // Note that in contrast to numpy.i's implementation we demand NumPy arrays
// and do not accept arbitrary sequences, which would needed to be copied around. // and do not accept arbitrary sequences, which would needed to be copied around.
throw std::logic_error("NumPy array expected"); throw std::logic_error("NumPy array expected");
} }
PyArrayObject* array = (PyArrayObject*)pyobj; PyArrayObject* array = (PyArrayObject*)pyobj;
int rank = PyArray_NDIM(array); int rank = PyArray_NDIM(array);
npy_intp* np_shape = PyArray_SHAPE(array); npy_intp* np_shape = PyArray_SHAPE(array);
std::vector<size_t> shape; std::vector<size_t> shape;
npy_intp num_elements = 1; npy_intp num_elements = 1;
@ -1067,11 +1268,11 @@ def dynamic_axes(self):
for (int i=rank-1; i>=0; i--) for (int i=rank-1; i>=0; i--)
{ {
shape.push_back(np_shape[i]); shape.push_back(np_shape[i]);
num_elements *= np_shape[i]; num_elements *= np_shape[i];
} }
int typecode = PyArray_TYPE(array); int typecode = PyArray_TYPE(array);
NDArrayView* view; NDArrayView* view;
if (typecode == NPY_FLOAT) if (typecode == NPY_FLOAT)
{ {
@ -1094,68 +1295,8 @@ def dynamic_axes(self):
} }
PyObject* to_numpy() { PyObject* to_numpy() {
if ((*self).GetStorageFormat() != StorageFormat::Dense) PyObject *NDArrayViewToNumPy(const CNTK::NDArrayView*);
throw std::invalid_argument("only dense supported at the moment"); return NDArrayViewToNumPy(self);
// FIXME use not yet existing NDShape function that returns the dimensions at once
std::vector<size_t> dimensions_cntk = (*self).Shape().Dimensions();
std::vector<size_t> dimensions;
// We have at least one element. In case the shape is empty (e.g.
// '()'), we have a scalar, which we need to copy (e.g. a constant).
size_t num_elements = 1;
// CNTK uses column major, thus we reverse the shape
for (int i=dimensions_cntk.size()-1; i>=0; i--)
{
dimensions.push_back(dimensions_cntk[i]);
num_elements *= dimensions_cntk[i];
}
npy_intp* shape = reinterpret_cast<npy_intp*>(&dimensions[0]);
CNTK::DataType cntk_type = (*self).GetDataType();
NDArrayView* cpuView;
if ((*self).Device() != DeviceDescriptor::CPUDevice())
{
cpuView = new NDArrayView(cntk_type, (*self).Shape(), DeviceDescriptor::CPUDevice());
cpuView->CopyFrom((*self));
}
else
{
cpuView = &(*self);
}
NPY_TYPES numpy_type;
void* buffer;
if (cntk_type == CNTK::DataType::Float)
{
numpy_type = NPY_FLOAT;
buffer = (void*)cpuView->DataBuffer<float>();
}
else if (cntk_type == CNTK::DataType::Double)
{
numpy_type = NPY_DOUBLE;
buffer = (void*)cpuView->DataBuffer<double>();
}
else
{
throw std::invalid_argument("unknown CNTK data type");
}
PyObject* ndarray = PyArray_SimpleNew(dimensions.size(), shape, numpy_type);
void *arr_data = PyArray_DATA((PyArrayObject*)ndarray);
memcpy(arr_data, buffer, PyArray_ITEMSIZE((PyArrayObject*) ndarray) * num_elements);
if ((*self).Device() != DeviceDescriptor::CPUDevice())
{
delete cpuView;
}
return ndarray;
} }
} }
@ -1240,7 +1381,7 @@ StreamInformation.__eq__ = lambda a,b: a.m_name==b.m_name and a.m_id==b.m_id and
%pythoncode %{ %pythoncode %{
# in case of multiple outputs return the function, not the variable # in case of multiple outputs return the function, not the variable
def get_output_and_keep_reference(self): def get_output_and_keep_reference(self):
variable = self._output() variable = self._output()
variable.__owner = self variable.__owner = self
return variable return variable
Function.output = lambda self:get_output_and_keep_reference(self) Function.output = lambda self:get_output_and_keep_reference(self)

Просмотреть файл

@ -0,0 +1,5 @@
# Copyright (c) Microsoft. All rights reserved.
# Licensed under the MIT license. See LICENSE.md file in the project root
# for full license information.
# ==============================================================================

Просмотреть файл

@ -27,7 +27,7 @@ def test_text_format():
mb_source = text_format_minibatch_source(path, [ mb_source = text_format_minibatch_source(path, [
StreamConfiguration( 'features', input_dim, True, 'x' ), StreamConfiguration( 'features', input_dim, True, 'x' ),
StreamConfiguration( 'labels', num_output_classes, False, 'y')], 0) StreamConfiguration( 'labels', num_output_classes, False, 'y')])
assert isinstance(mb_source, MinibatchSource) assert isinstance(mb_source, MinibatchSource)
features_si = mb_source.stream_info('features') features_si = mb_source.stream_info('features')
@ -36,11 +36,11 @@ def test_text_format():
mb = mb_source.get_next_minibatch(7) mb = mb_source.get_next_minibatch(7)
features = mb[features_si].m_data features = mb[features_si].m_data
# 2 samples, max seq len 4, 1000 dim
assert features.data().shape().dimensions() == (2, 4, input_dim)
assert features.data().is_sparse()
# TODO features is sparse and cannot be accessed right now: # TODO features is sparse and cannot be accessed right now:
# *** RuntimeError: DataBuffer/WritableDataBuffer methods can only be called for NDArrayiew objects with dense storage format # *** RuntimeError: DataBuffer/WritableDataBuffer methods can only be called for NDArrayiew objects with dense storage format
# 2 samples, max seq len 4, 1000 dim
#assert features.data().shape().dimensions() == (2, 4, input_dim)
#assert features.data().is_sparse()
labels = mb[labels_si].m_data labels = mb[labels_si].m_data
# 2 samples, max seq len 1, 5 dim # 2 samples, max seq len 1, 5 dim

Просмотреть файл

@ -1810,14 +1810,14 @@ from cntk.axis import Axis
@typemap @typemap
def input_variable(shape, data_type=np.float32, needs_gradient=True, is_sparse=False, def input_variable(shape, dtype=np.float32, needs_gradient=True, is_sparse=False,
dynamic_axes=Axis.default_input_variable_dynamic_axes, name=''): dynamic_axes=Axis.default_input_variable_dynamic_axes(), name=''):
''' '''
It creates an input node. It creates an input node.
Args: Args:
shape (`tuple` or `int`): the shape of the input tensor shape (`tuple` or `int`): the shape of the input tensor
data_type (`type`, optional): np.float32 (default) or np.float64 dtype (`type`, optional): np.float32 (default) or np.float64
needs_gradients (`bool`, optional): whether to back-propagates to it or not. True by default. needs_gradients (`bool`, optional): whether to back-propagates to it or not. True by default.
is_sparse (`bool`, optional): whether the variable is sparse (`False` by default) is_sparse (`bool`, optional): whether the variable is sparse (`False` by default)
dynamic_axes (`list` or `tuple`, default): a list of dynamic axis (e.g., batch axis, time axis) dynamic_axes (`list` or `tuple`, default): a list of dynamic axis (e.g., batch axis, time axis)
@ -1831,9 +1831,9 @@ def input_variable(shape, data_type=np.float32, needs_gradient=True, is_sparse=F
shape = sanitize_shape(shape) shape = sanitize_shape(shape)
if data_type is None: if dtype is None:
data_type = np.float32 dtype = np.float32
dtype = sanitize_dtype_cntk(data_type) dtype = sanitize_dtype_cntk(dtype)
dynamic_axes = sanitize_dynamic_axes(dynamic_axes) dynamic_axes = sanitize_dynamic_axes(dynamic_axes)
# TODO dynamic axis for numpy arrays # TODO dynamic axis for numpy arrays
@ -1863,7 +1863,7 @@ def placeholder_variable(shape=None, dynamic_axes=None, name=''):
shape = sanitize_shape(shape) shape = sanitize_shape(shape)
if dynamic_axes is None: if dynamic_axes is None:
dynamic_axes = Axis.unknown_dynamic_axes dynamic_axes = Axis.unknown_dynamic_axes()
dynamic_axes = sanitize_dynamic_axes(dynamic_axes) dynamic_axes = sanitize_dynamic_axes(dynamic_axes)
return placeholder_variable(shape, name, dynamic_axes) return placeholder_variable(shape, name, dynamic_axes)

Просмотреть файл

@ -51,7 +51,7 @@ def test_op_convolution_without_padding(convolution_map, convolution_input, devi
backward = AA([[conv_map]]) backward = AA([[conv_map]])
a = I(shape=conv_input.shape, a = I(shape=conv_input.shape,
data_type=sanitize_dtype_cntk(precision), dtype=sanitize_dtype_cntk(precision),
needs_gradient=True, needs_gradient=True,
name='a') name='a')
@ -93,7 +93,7 @@ def test_op_avg_pooling(input_size, pooling_window, strides, result, device_id,
input_operand = x.reshape(input_size) input_operand = x.reshape(input_size)
a = I(shape=input_operand.shape, a = I(shape=input_operand.shape,
data_type=sanitize_dtype_cntk(precision), dtype=sanitize_dtype_cntk(precision),
needs_gradient=True, needs_gradient=True,
name='a') name='a')
@ -137,7 +137,7 @@ def test_op_max_pooling(input_size, pooling_window, strides, result, device_id,
input_operand = x.reshape(input_size) input_operand = x.reshape(input_size)
a = I(shape=input_operand.shape, a = I(shape=input_operand.shape,
data_type=sanitize_dtype_cntk(precision), dtype=sanitize_dtype_cntk(precision),
needs_gradient=True, needs_gradient=True,
name='a') name='a')

Просмотреть файл

@ -86,12 +86,12 @@ def test_op_plus_var_sequences_input_input(left_batch, right_batch, device_id, p
right_shape = right_value[0][0].shape right_shape = right_value[0][0].shape
a = I(shape=left_shape, a = I(shape=left_shape,
data_type=sanitize_dtype_cntk(PRECISION_TO_TYPE[precision]), dtype=sanitize_dtype_cntk(PRECISION_TO_TYPE[precision]),
needs_gradient=True, needs_gradient=True,
name='a') name='a')
b = I(shape=right_shape, b = I(shape=right_shape,
data_type=sanitize_dtype_cntk(PRECISION_TO_TYPE[precision]), dtype=sanitize_dtype_cntk(PRECISION_TO_TYPE[precision]),
needs_gradient=True, needs_gradient=True,
name='b') name='b')

Просмотреть файл

@ -137,7 +137,7 @@ def test_op_dropout(shape, dropout_rate, device_id, precision):
value = np.ones(shape=shape, dtype=PRECISION_TO_TYPE[precision]) value = np.ones(shape=shape, dtype=PRECISION_TO_TYPE[precision])
a = I(shape=value.shape, a = I(shape=value.shape,
data_type=sanitize_dtype_cntk(PRECISION_TO_TYPE[precision]), dtype=sanitize_dtype_cntk(PRECISION_TO_TYPE[precision]),
needs_gradient=True, needs_gradient=True,
name='a') name='a')
@ -168,7 +168,7 @@ def test_op_dropout_bad_input(dropout_rate):
from cntk import dropout from cntk import dropout
from cntk.utils import eval, sanitize_dtype_cntk, cntk_device from cntk.utils import eval, sanitize_dtype_cntk, cntk_device
a = I(shape=(1, 2), data_type='float', needs_gradient=True, name='a') a = I(shape=(1, 2), dtype='float', needs_gradient=True, name='a')
with pytest.raises(ValueError): with pytest.raises(ValueError):
dropout_node = dropout(a, dropout_rate=dropout_rate) dropout_node = dropout(a, dropout_rate=dropout_rate)

Просмотреть файл

@ -37,7 +37,7 @@ def _test_unary_op(precision, device_id, op_func,
value = AA(value, dtype=PRECISION_TO_TYPE[precision]) value = AA(value, dtype=PRECISION_TO_TYPE[precision])
a = I(shape=value.shape, a = I(shape=value.shape,
data_type=sanitize_dtype_cntk(PRECISION_TO_TYPE[precision]), dtype=sanitize_dtype_cntk(PRECISION_TO_TYPE[precision]),
needs_gradient=True, needs_gradient=True,
name='a') name='a')
@ -66,12 +66,12 @@ def _test_binary_op(precision, device_id, op_func, left_operand, right_operand,
right_value = AA(right_operand, dtype=PRECISION_TO_TYPE[precision]) right_value = AA(right_operand, dtype=PRECISION_TO_TYPE[precision])
a = I(shape=left_value.shape, a = I(shape=left_value.shape,
data_type=sanitize_dtype_cntk(precision), dtype=sanitize_dtype_cntk(precision),
needs_gradient=True, needs_gradient=True,
name='a') name='a')
b = I(shape=right_value.shape, b = I(shape=right_value.shape,
data_type=sanitize_dtype_cntk(precision), dtype=sanitize_dtype_cntk(precision),
needs_gradient=True, needs_gradient=True,
name='b') name='b')

Просмотреть файл

@ -41,7 +41,7 @@ def test_op_future_value(tensor_number_of_values, input_size, time_step, initial
np.put(backward, range(total_elements - elements_to_roll), 0.0) np.put(backward, range(total_elements - elements_to_roll), 0.0)
a = I(shape=x.shape[1:], a = I(shape=x.shape[1:],
data_type=sanitize_dtype_cntk(precision), dtype=sanitize_dtype_cntk(precision),
needs_gradient=True, needs_gradient=True,
name='a') name='a')
@ -71,7 +71,7 @@ def test_op_past_value(tensor_number_of_values, input_size, time_step, initial_s
expected_forward = AA([x_rolled]) expected_forward = AA([x_rolled])
a = I(shape=x.shape[1:], a = I(shape=x.shape[1:],
data_type=sanitize_dtype_cntk(precision), dtype=sanitize_dtype_cntk(precision),
needs_gradient=True, needs_gradient=True,
name='a') name='a')

Просмотреть файл

@ -5,7 +5,7 @@
# ============================================================================== # ==============================================================================
""" """
Unit tests for reshaping operations. Unit tests for reshaping operations.
""" """
from __future__ import division from __future__ import division
@ -52,7 +52,7 @@ def test_op_reshape(input_shape, output_shape, expected_output_shape, device_id,
input_reshaped = input_tensor.reshape(expected_output_shape) input_reshaped = input_tensor.reshape(expected_output_shape)
a = I(shape=input_tensor.shape, a = I(shape=input_tensor.shape,
data_type=sanitize_dtype_cntk(PRECISION_TO_TYPE[precision]), dtype=sanitize_dtype_cntk(PRECISION_TO_TYPE[precision]),
needs_gradient=True, needs_gradient=True,
name='a') name='a')
@ -94,7 +94,7 @@ def test_op_slice(input_data, slice_params, expected_result, device_id, precisio
input_data = AA(input_data, dtype=PRECISION_TO_TYPE[precision]) input_data = AA(input_data, dtype=PRECISION_TO_TYPE[precision])
a = I(shape=input_data.shape, a = I(shape=input_data.shape,
data_type=sanitize_dtype_cntk(PRECISION_TO_TYPE[precision]), dtype=sanitize_dtype_cntk(PRECISION_TO_TYPE[precision]),
needs_gradient=True, needs_gradient=True,
name='a') name='a')
@ -161,7 +161,7 @@ def test_op_slice_sequence(input_data, slice_params, expected_result, device_id,
t = Axis.new_unique_dynamic_axis('t') t = Axis.new_unique_dynamic_axis('t')
sample_shape = input_data.shape[1:] sample_shape = input_data.shape[1:]
a = I(shape=sample_shape, a = I(shape=sample_shape,
data_type=sanitize_dtype_cntk(PRECISION_TO_TYPE[precision]), dtype=sanitize_dtype_cntk(PRECISION_TO_TYPE[precision]),
needs_gradient=True, needs_gradient=True,
dynamic_axes=[Axis.default_batch_axis(), t], dynamic_axes=[Axis.default_batch_axis(), t],
name='a') name='a')
@ -215,11 +215,11 @@ def test_op_splice(input_data1, input_data2, axis, expected_result, device_id, p
input_data1 = AA(input_data1, dtype=PRECISION_TO_TYPE[precision]) input_data1 = AA(input_data1, dtype=PRECISION_TO_TYPE[precision])
input_data2 = AA(input_data2, dtype=PRECISION_TO_TYPE[precision]) input_data2 = AA(input_data2, dtype=PRECISION_TO_TYPE[precision])
a = I(shape=input_data1.shape, a = I(shape=input_data1.shape,
data_type=sanitize_dtype_cntk(PRECISION_TO_TYPE[precision]), dtype=sanitize_dtype_cntk(PRECISION_TO_TYPE[precision]),
needs_gradient=True, needs_gradient=True,
name='a') name='a')
b = I(shape=input_data2.shape, b = I(shape=input_data2.shape,
data_type=sanitize_dtype_cntk(PRECISION_TO_TYPE[precision]), dtype=sanitize_dtype_cntk(PRECISION_TO_TYPE[precision]),
needs_gradient=True, needs_gradient=True,
name='b') name='b')

Просмотреть файл

@ -110,7 +110,7 @@ class Variable(VariableMixin, TensorOpsMixin, cntk_py.Variable):
Args: Args:
shape (`tuple`): the shape of this variable. shape (`tuple`): the shape of this variable.
data_type (`np.float32 or np.float64`): data type of the values that will be bound to this variable. dtype (`np.float32 or np.float64`): data type of the values that will be bound to this variable.
Default is np.float32 Default is np.float32
needs_gradient (`bool`): if set to True any expression that contains this variable needs_gradient (`bool`): if set to True any expression that contains this variable
will also be differentiated with respect to this variable. will also be differentiated with respect to this variable.
@ -119,16 +119,16 @@ class Variable(VariableMixin, TensorOpsMixin, cntk_py.Variable):
express dimensions that can vary across examples or minibatches. express dimensions that can vary across examples or minibatches.
name(`str`): an optional name for this parameter. name(`str`): an optional name for this parameter.
''' '''
def __init__(self, shape=None, data_type=None, needs_gradient=False, is_sparse=False, def __init__(self, shape=None, dtype=None, needs_gradient=False, is_sparse=False,
dynamic_axes=[cntk_py.Axis.default_dynamic_axis(), cntk_py.Axis.default_batch_axis()], name=''): dynamic_axes=[cntk_py.Axis.default_dynamic_axis(), cntk_py.Axis.default_batch_axis()], name=''):
shape = utils.sanitize_shape(shape) shape = utils.sanitize_shape(shape)
if data_type is None: if dtype is None:
data_type = np.float32 dtype = np.float32
dtype = utils.sanitize_dtype_cntk(data_type) dtype = utils.sanitize_dtype_cntk(dtype)
super().__init__(shape, is_sparse, dtype, needs_gradient, name, super().__init__(shape, is_sparse, dtype, needs_gradient, name,
dynamic_axes) dynamic_axes)
class Parameter(VariableMixin, TensorOpsMixin, cntk_py.Parameter): class Parameter(VariableMixin, TensorOpsMixin, cntk_py.Parameter):
@ -176,7 +176,7 @@ class Parameter(VariableMixin, TensorOpsMixin, cntk_py.Parameter):
''' '''
NumPy array of the value NumPy array of the value
''' '''
return super().value().to_numpy() return super().value().to_numpy()
class Constant(VariableMixin, TensorOpsMixin, cntk_py.Constant): class Constant(VariableMixin, TensorOpsMixin, cntk_py.Constant):
''' '''
@ -188,7 +188,7 @@ class Constant(VariableMixin, TensorOpsMixin, cntk_py.Constant):
Args: Args:
value (`np.ndarray` or `list` or `float` or `int`): Initial value. value (`np.ndarray` or `list` or `float` or `int`): Initial value.
BUGBUG: Document initializers BUGBUG: Document initializers
data_type (`np.float32` or `np.float64`): data type to store the values as. dtype (`np.float32` or `np.float64`): data type to store the values as.
device (:class:`cntk.device.DeviceDescriptor`): the device on which the values should reside. device (:class:`cntk.device.DeviceDescriptor`): the device on which the values should reside.
name (`str`): an optional name for this constant. name (`str`): an optional name for this constant.
''' '''
@ -204,7 +204,7 @@ class Constant(VariableMixin, TensorOpsMixin, cntk_py.Constant):
super().__init__(utils.sanitize_shape(shape), sanitize_dtype_cntk(dtype), value) super().__init__(utils.sanitize_shape(shape), sanitize_dtype_cntk(dtype), value)
else: else:
ndav = sanitize_value(shape, value, dtype, device) ndav = sanitize_value(shape, value, dtype, device)
super().__init__(ndav, name) super().__init__(ndav, name)
@property @property
@ -212,5 +212,5 @@ class Constant(VariableMixin, TensorOpsMixin, cntk_py.Constant):
''' '''
NumPy array of the value NumPy array of the value
''' '''
return super().value().to_numpy() return super().value().to_numpy()

Просмотреть файл

@ -0,0 +1,44 @@
# Copyright (c) Microsoft. All rights reserved.
# Licensed under the MIT license. See LICENSE.md file in the project root
# for full license information.
# ==============================================================================
import cntk as C
import numpy as np
def _check(expected, d):
for key in expected:
assert key in d
assert d[key] == expected[key]
for key in d:
assert key in expected
def test_convolution_attributes():
x = C.input_variable( (1, 5, 5) )
filter = np.reshape(np.array([2, -1, -1, 2], dtype = np.float32), (1, 2, 2))
kernel = C.constant(value = filter)
f = C.convolution(kernel , x, auto_padding = [False])
d = f.root_function.attributes
expected = {'autoPadding': [False, False, False],
'sharing': [True, True, True],
'strides': (1, 1, 1),
'maxTempMemSizeInSamples': 0,
'upperPad': (0, 0, 0),
'lowerPad': (0, 0, 0),
'transpose': False
}
_check(expected, d)
def test_dropout_attributes():
x = C.input_variable( (1, 5, 5) )
f = C.dropout(x, 0.5)
d = f.root_function.attributes
expected = {'dropoutRate': 0.5}
_check(expected, d)
def test_slice_attributes():
x = C.input_variable((2,3))
f = C.slice(x, 0, 1, 2)
d = f.root_function.attributes
expected = {'endIndex': 2, 'beginIndex': 1, 'axis': ('ordered', 'static', 1)}
_check(expected, d)

Просмотреть файл

@ -670,7 +670,7 @@ def sanitize_axis(axis):
def sanitize_dynamic_axes(axes): def sanitize_dynamic_axes(axes):
if axes is not cntk_py.Axis.default_input_variable_dynamic_axes: if axes != cntk_py.Axis.default_input_variable_dynamic_axes():
if not type(axes) in (list, tuple): if not type(axes) in (list, tuple):
axes = [axes] axes = [axes]
else: else:

Просмотреть файл

@ -0,0 +1,5 @@
# Copyright (c) Microsoft. All rights reserved.
# Licensed under the MIT license. See LICENSE.md file in the project root
# for full license information.
# ==============================================================================

Просмотреть файл

@ -154,7 +154,7 @@ cntk_module = Extension(
# Do not include examples # Do not include examples
packages = [x for x in find_packages() if x.startswith('cntk') and not x.startswith('cntk.swig')] packages = [x for x in find_packages() if x.startswith('cntk') and not x.startswith('cntk.swig')]
package_data = { 'cntk': ['pytest.ini'] } package_data = { 'cntk': ['pytest.ini', 'io/tests/tf_data.txt'] }
if IS_WINDOWS: if IS_WINDOWS:
# On Windows copy all runtime libs to the base folder of Python # On Windows copy all runtime libs to the base folder of Python