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;
public:
CNTK_API static const std::vector<Axis> DefaultInputVariableDynamicAxes;
CNTK_API static const std::vector<Axis>& DefaultInputVariableDynamicAxes();
///
/// Axis object representing unknown dynamic axes
///
CNTK_API static const std::vector<Axis> UnknownDynamicAxes;
CNTK_API static const std::vector<Axis>& UnknownDynamicAxes();
public:
///
@ -1548,8 +1548,8 @@ namespace CNTK
typedef Dictionary ParameterInitializer;
// Forward declarations
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 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 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
private:
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""*/);
#endif
@ -1812,7 +1812,7 @@ private:
/// 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.
///
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);
}
@ -1823,13 +1823,13 @@ private:
///
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
///
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));
}
@ -1837,7 +1837,7 @@ private:
///
/// 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);
}
@ -1845,7 +1845,7 @@ private:
///
/// 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);
}
@ -1853,7 +1853,7 @@ private:
///
/// 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);
}
@ -1861,7 +1861,7 @@ private:
///
/// 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);
}
@ -1869,7 +1869,7 @@ private:
///
/// 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);
}
@ -1877,7 +1877,7 @@ private:
///
/// 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);
}
@ -1885,7 +1885,7 @@ private:
///
/// 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);
}

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

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

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

@ -267,7 +267,8 @@ namespace CNTK
/*static*/ DeviceDescriptor DeviceDescriptor::DefaultDevice()
{
std::call_once(s_initDefaultDeviceFlag, [=]{
std::call_once(s_initDefaultDeviceFlag, []
{
s_defaultDevice.reset(new DeviceDescriptor(DeviceDescriptor::BestDevice()));
});
return *s_defaultDevice;
@ -293,7 +294,8 @@ namespace CNTK
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");
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.
});
@ -313,7 +315,8 @@ namespace CNTK
{
using namespace Microsoft::MSR::CNTK;
std::call_once(s_initAllDevicesFlag, [=]{
std::call_once(s_initAllDevicesFlag, []
{
s_allDevices.reset(new std::vector<DeviceDescriptor>());
#ifndef CPUONLY
auto allGpusData = GetAllGpusData();
@ -352,8 +355,26 @@ namespace CNTK
/*static*/ Axis::UniqueDynamicAxesNames Axis::s_uniqueDynamicAxisNames;
/*static*/ const std::vector<Axis> Axis::DefaultInputVariableDynamicAxes = { Axis::DefaultDynamicAxis(), Axis::DefaultBatchAxis() };
/*static*/ const std::vector<Axis> Axis::UnknownDynamicAxes = { Axis(SentinelStaticAxisIndexValueForUnknownAxes) };
static std::shared_ptr<std::vector<Axis>> s_defaultInputVariableDynamicAxes, s_unknownDynamicAxes;
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()
{

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

@ -92,7 +92,7 @@ namespace CNTK
if (var.Shape().IsUnknown() && !placeholder.Shape().IsUnknown())
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();
}
}
@ -164,7 +164,7 @@ namespace CNTK
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;
currentOutputVar.m_dataFields->m_dynamicAxes = newOutputVar.DynamicAxes();
@ -172,7 +172,7 @@ namespace CNTK
if ((!newOutputVar.Shape().IsUnknown() && (currentOutputVar.Shape() != newOutputVar.Shape())) ||
((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");
}
@ -642,13 +642,13 @@ namespace CNTK
auto allInputDynamicAxesEmpty = std::find_if(inputs.begin(), inputs.end(), [](const Variable& input) { return !input.DynamicAxes().empty(); }) == inputs.end();
if (!allInputDynamicAxesEmpty)
{
outputDynamicAxes = Axis::UnknownDynamicAxes;
outputDynamicAxes = Axis::UnknownDynamicAxes();
for (auto inputVar : inputs)
{
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;
else
{
@ -808,7 +808,7 @@ namespace CNTK
Variable initialStateVar = inputs[1];
// 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)");
if (!initialStateVar.DynamicAxes().empty())
@ -1322,7 +1322,7 @@ namespace CNTK
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());
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());
// 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");
%include "stl.i"
%include "std_wstring.i"
%include "std_wstring.i"
%include <std_vector.i>
%include <std_map.i>
%include <std_set.i>
@ -74,9 +74,210 @@
//
%feature("shadow") CNTK::Variable::DynamicAxes %{
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)
%rename(EQ) operator==(const DATA_TYPE&, const DATA_TYPE&);
%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"
#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 {
// '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::Dimensions;
%typemap(out) CNTK::NDShape {
size_t rank = $1.Rank();
$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));
}
%typemap(out, fragment="NDShapeToTuple") CNTK::NDShape {
$result = NDShapeToTuple($1);
}
%extend CNTK::NDShape {
@ -173,7 +374,7 @@ def dynamic_axes(self):
return (*self)[rank-1-i];
}
PyObject* dimensions() {
PyObject* dimensions() {
std::vector<size_t> dims = (*self).Dimensions();
size_t rank = (*self).Rank();
PyObject* result = PyTuple_New(rank);
@ -181,7 +382,7 @@ def dynamic_axes(self):
for (size_t i=0; i<rank; 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;
}
@ -199,7 +400,7 @@ def dynamic_axes(self):
//%constant long CNTK::NDShape::InferredDimension = -1;
%constant long InferredDimension = -1;
// end of NDShape
// end of NDShape
//
// Converting Python dictionary {Variable: ValuePtr} to std::unordered_map
@ -222,7 +423,7 @@ def dynamic_axes(self):
void *raw_var = 0 ;
int res1 = SWIG_ConvertPtr(key, &raw_var, SWIGTYPE_p_CNTK__Variable, 0);
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) {
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;
int res2 = SWIG_ConvertPtr(value, &raw_value, SWIGTYPE_p_std__shared_ptrT_CNTK__Value_t, 0);
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;
@ -266,7 +467,7 @@ def dynamic_axes(self):
void *raw_var = 0 ;
int res1 = SWIG_ConvertPtr(key, &raw_var, SWIGTYPE_p_CNTK__Variable, 0);
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) {
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;
int res2 = SWIG_ConvertPtr(value, &raw_value, SWIGTYPE_p_std__shared_ptrT_CNTK__Value_t, 0);
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;
@ -300,10 +501,10 @@ def dynamic_axes(self):
// 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
// afterwards point to the proper value.
%typemap(argout)
// Swig would create this conversion for the 'const' variants as well, which
%typemap(argout)
// 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.
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>& backPropagatedGradientValuesForInputs
{
@ -338,7 +539,7 @@ def dynamic_axes(self):
void *cntk_key = 0 ;
int res = SWIG_ConvertPtr(py_key, &cntk_key, SWIGTYPE_p_CNTK__Variable, 0);
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) {
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 ;
int res1 = SWIG_ConvertPtr(key, &raw_var, SWIGTYPE_p_CNTK__StreamInformation, 0);
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) {
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)) {
PyObject* first = PyTuple_GET_ITEM(value, 0);
size_t first_val = PyLong_AsSize_t(first);
PyObject* second = PyTuple_GET_ITEM(value, 1);
size_t first_val = PyLong_AsSize_t(first);
PyObject* second = PyTuple_GET_ITEM(value, 1);
size_t second_val = PyLong_AsSize_t(second);
args_map.insert(std::make_pair(*var, std::make_pair(first_val, second_val)));
} else {
SWIG_exception(SWIG_TypeError, "tuple expected");
}
}
$1 = &args_map;
@ -411,7 +612,7 @@ def dynamic_axes(self):
}
%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)) {
@ -422,20 +623,20 @@ def dynamic_axes(self):
void *raw_var = 0 ;
int res = SWIG_ConvertPtr(key, &raw_var, SWIGTYPE_p_CNTK__StreamInformation, 0);
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) {
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)) {
PyObject* first = PyTuple_GET_ITEM(value, 0);
void *raw_value1 = 0;
int res1 = SWIG_ConvertPtr(first, &raw_value1, SWIGTYPE_p_std__shared_ptrT_CNTK__NDArrayView_t, 0);
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;
@ -446,11 +647,11 @@ def dynamic_axes(self):
value1 = new CNTK::NDArrayViewPtr();
}
PyObject* second = PyTuple_GET_ITEM(value, 1);
PyObject* second = PyTuple_GET_ITEM(value, 1);
void *raw_value2 = 0;
int res2 = SWIG_ConvertPtr(second, &raw_value2, SWIGTYPE_p_std__shared_ptrT_CNTK__NDArrayView_t, 0);
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;
@ -464,7 +665,7 @@ def dynamic_axes(self):
args_map.insert(std::make_pair(*var, std::make_pair(*value1, *value2)));
} else {
SWIG_exception(SWIG_TypeError, "tuple expected");
}
}
}
$1 = &args_map;
@ -509,7 +710,7 @@ def dynamic_axes(self):
void *cntk_key = 0 ;
int res = SWIG_ConvertPtr(py_key, &cntk_key, SWIGTYPE_p_CNTK__StreamInformation, 0);
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) {
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 ;
int res1 = SWIG_ConvertPtr(key, &raw_var, SWIGTYPE_p_CNTK__Parameter, 0);
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) {
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;
int res2 = SWIG_ConvertPtr(value, &raw_value, SWIGTYPE_p_std__shared_ptrT_CNTK__NDArrayView_t, 0);
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;
@ -595,14 +796,14 @@ def dynamic_axes(self):
PyObject *iterator = PyObject_GetIter($input);
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))) {
void *raw_var = 0 ;
int res1 = SWIG_ConvertPtr(item, &raw_var, SWIGTYPE_p_CNTK__DictionaryValue, 0);
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) {
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);
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;
@ -642,7 +843,7 @@ def dynamic_axes(self):
}
%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)) {
@ -650,14 +851,14 @@ def dynamic_axes(self):
PyObject *iterator = PyObject_GetIter($input);
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))) {
void *raw_var = 0 ;
int res1 = SWIG_ConvertPtr(item, &raw_var, SWIGTYPE_p_CNTK__Variable, 0);
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) {
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);
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;
@ -693,7 +894,7 @@ def dynamic_axes(self):
}
%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)) {
@ -701,14 +902,14 @@ def dynamic_axes(self):
PyObject *iterator = PyObject_GetIter($input);
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))) {
void *raw_var = 0 ;
int res1 = SWIG_ConvertPtr(item, &raw_var, SWIGTYPE_p_CNTK__StreamInformation, 0);
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) {
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);
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;
@ -744,7 +945,7 @@ def dynamic_axes(self):
}
%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)) {
@ -752,14 +953,14 @@ def dynamic_axes(self):
PyObject *iterator = PyObject_GetIter($input);
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))) {
void *raw_var = 0 ;
int res1 = SWIG_ConvertPtr(item, &raw_var, SWIGTYPE_p_CNTK__Parameter, 0);
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) {
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);
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;
@ -796,7 +997,7 @@ def dynamic_axes(self):
}
%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)) {
@ -804,14 +1005,14 @@ def dynamic_axes(self):
PyObject *iterator = PyObject_GetIter($input);
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))) {
void *raw_var = 0 ;
int res1 = SWIG_ConvertPtr(item, &raw_var, SWIGTYPE_p_std__shared_ptrT_CNTK__Learner_t, 0);
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) {
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);
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;
@ -845,7 +1046,7 @@ def dynamic_axes(self):
%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)) {
@ -856,7 +1057,7 @@ def dynamic_axes(self):
void *raw_var = 0 ;
int res1 = SWIG_ConvertPtr(key, &raw_var, SWIGTYPE_p_CNTK__Variable, 0);
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) {
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;
int res2 = SWIG_ConvertPtr(value, &raw_value, SWIGTYPE_p_CNTK__Variable, 0);
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;
@ -903,9 +1104,9 @@ def dynamic_axes(self):
{
SWIG_exception(SWIG_RuntimeError, "error passing set to Python");
}
// *&$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 '*'.
for (auto var : *&$1)
{
@ -918,7 +1119,7 @@ def dynamic_axes(self):
$result = container;
}
%enddef
%unordered_set_conversion(Variable, SWIGTYPE_p_CNTK__Variable)
%unordered_set_conversion(Constant, SWIGTYPE_p_CNTK__Constant)
%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");
}
for (auto var : *$1)
{
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");
}
// *&$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 '*'.
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_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_val);
@ -1024,7 +1225,7 @@ def dynamic_axes(self):
}
void* buffer = const_cast<void*>(reinterpret_cast<const void*>(cpuMask->DataBuffer()));
PyObject* ndarray = PyArray_SimpleNew(dimensions.size(), shape, NPY_BYTE);
void *arr_data = PyArray_DATA((PyArrayObject*)ndarray);
@ -1046,20 +1247,20 @@ def dynamic_axes(self):
//
%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))
{
// 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.
throw std::logic_error("NumPy array expected");
}
PyArrayObject* array = (PyArrayObject*)pyobj;
int rank = PyArray_NDIM(array);
npy_intp* np_shape = PyArray_SHAPE(array);
int rank = PyArray_NDIM(array);
npy_intp* np_shape = PyArray_SHAPE(array);
std::vector<size_t> shape;
npy_intp num_elements = 1;
@ -1067,11 +1268,11 @@ def dynamic_axes(self):
for (int i=rank-1; i>=0; i--)
{
shape.push_back(np_shape[i]);
num_elements *= np_shape[i];
num_elements *= np_shape[i];
}
int typecode = PyArray_TYPE(array);
NDArrayView* view;
if (typecode == NPY_FLOAT)
{
@ -1094,68 +1295,8 @@ def dynamic_axes(self):
}
PyObject* to_numpy() {
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 = &(*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;
PyObject *NDArrayViewToNumPy(const CNTK::NDArrayView*);
return NDArrayViewToNumPy(self);
}
}
@ -1240,7 +1381,7 @@ StreamInformation.__eq__ = lambda a,b: a.m_name==b.m_name and a.m_id==b.m_id and
%pythoncode %{
# in case of multiple outputs return the function, not the variable
def get_output_and_keep_reference(self):
variable = self._output()
variable = self._output()
variable.__owner = self
return variable
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, [
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)
features_si = mb_source.stream_info('features')
@ -36,11 +36,11 @@ def test_text_format():
mb = mb_source.get_next_minibatch(7)
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:
# *** 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
# 2 samples, max seq len 1, 5 dim

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

@ -1810,14 +1810,14 @@ from cntk.axis import Axis
@typemap
def input_variable(shape, data_type=np.float32, needs_gradient=True, is_sparse=False,
dynamic_axes=Axis.default_input_variable_dynamic_axes, name=''):
def input_variable(shape, dtype=np.float32, needs_gradient=True, is_sparse=False,
dynamic_axes=Axis.default_input_variable_dynamic_axes(), name=''):
'''
It creates an input node.
Args:
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.
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)
@ -1831,9 +1831,9 @@ def input_variable(shape, data_type=np.float32, needs_gradient=True, is_sparse=F
shape = sanitize_shape(shape)
if data_type is None:
data_type = np.float32
dtype = sanitize_dtype_cntk(data_type)
if dtype is None:
dtype = np.float32
dtype = sanitize_dtype_cntk(dtype)
dynamic_axes = sanitize_dynamic_axes(dynamic_axes)
# TODO dynamic axis for numpy arrays
@ -1863,7 +1863,7 @@ def placeholder_variable(shape=None, dynamic_axes=None, name=''):
shape = sanitize_shape(shape)
if dynamic_axes is None:
dynamic_axes = Axis.unknown_dynamic_axes
dynamic_axes = Axis.unknown_dynamic_axes()
dynamic_axes = sanitize_dynamic_axes(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]])
a = I(shape=conv_input.shape,
data_type=sanitize_dtype_cntk(precision),
dtype=sanitize_dtype_cntk(precision),
needs_gradient=True,
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)
a = I(shape=input_operand.shape,
data_type=sanitize_dtype_cntk(precision),
dtype=sanitize_dtype_cntk(precision),
needs_gradient=True,
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)
a = I(shape=input_operand.shape,
data_type=sanitize_dtype_cntk(precision),
dtype=sanitize_dtype_cntk(precision),
needs_gradient=True,
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
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,
name='a')
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,
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])
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,
name='a')
@ -168,7 +168,7 @@ def test_op_dropout_bad_input(dropout_rate):
from cntk import dropout
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):
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])
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,
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])
a = I(shape=left_value.shape,
data_type=sanitize_dtype_cntk(precision),
dtype=sanitize_dtype_cntk(precision),
needs_gradient=True,
name='a')
b = I(shape=right_value.shape,
data_type=sanitize_dtype_cntk(precision),
dtype=sanitize_dtype_cntk(precision),
needs_gradient=True,
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)
a = I(shape=x.shape[1:],
data_type=sanitize_dtype_cntk(precision),
dtype=sanitize_dtype_cntk(precision),
needs_gradient=True,
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])
a = I(shape=x.shape[1:],
data_type=sanitize_dtype_cntk(precision),
dtype=sanitize_dtype_cntk(precision),
needs_gradient=True,
name='a')

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

@ -5,7 +5,7 @@
# ==============================================================================
"""
Unit tests for reshaping operations.
Unit tests for reshaping operations.
"""
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)
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,
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])
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,
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')
sample_shape = input_data.shape[1:]
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,
dynamic_axes=[Axis.default_batch_axis(), t],
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_data2 = AA(input_data2, dtype=PRECISION_TO_TYPE[precision])
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,
name='a')
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,
name='b')

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

@ -110,7 +110,7 @@ class Variable(VariableMixin, TensorOpsMixin, cntk_py.Variable):
Args:
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
needs_gradient (`bool`): if set to True any expression that contains 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.
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=''):
shape = utils.sanitize_shape(shape)
if data_type is None:
data_type = np.float32
dtype = utils.sanitize_dtype_cntk(data_type)
if dtype is None:
dtype = np.float32
dtype = utils.sanitize_dtype_cntk(dtype)
super().__init__(shape, is_sparse, dtype, needs_gradient, name,
dynamic_axes)
dynamic_axes)
class Parameter(VariableMixin, TensorOpsMixin, cntk_py.Parameter):
@ -176,7 +176,7 @@ class Parameter(VariableMixin, TensorOpsMixin, cntk_py.Parameter):
'''
NumPy array of the value
'''
return super().value().to_numpy()
return super().value().to_numpy()
class Constant(VariableMixin, TensorOpsMixin, cntk_py.Constant):
'''
@ -188,7 +188,7 @@ class Constant(VariableMixin, TensorOpsMixin, cntk_py.Constant):
Args:
value (`np.ndarray` or `list` or `float` or `int`): Initial value.
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.
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)
else:
ndav = sanitize_value(shape, value, dtype, device)
super().__init__(ndav, name)
super().__init__(ndav, name)
@property
@ -212,5 +212,5 @@ class Constant(VariableMixin, TensorOpsMixin, cntk_py.Constant):
'''
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):
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):
axes = [axes]
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
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:
# On Windows copy all runtime libs to the base folder of Python