提交 1f0f9126 authored 作者: Pascal Lamblin's avatar Pascal Lamblin 提交者: GitHub

Merge pull request #5301 from bscellier/cleanup_numpy_min_version

Cleanup numpy min version
......@@ -1145,10 +1145,6 @@ Getting a Theano result like NumPy:
>>> t[(t > 4).nonzero()].eval()
array([5, 6, 7, 8])
The gradient of Advanced indexing needs in many cases NumPy
1.8. It is not released yet as of April 30th, 2013. You can use NumPy
development version to have this feature now.
Index-assignment is *not* supported. If you want to do something like ``a[5]
= b`` or ``a[5]+=b``, see :func:`theano.tensor.set_subtensor` and :func:`theano.tensor.inc_subtensor` below.
......
......@@ -161,7 +161,6 @@ def do_setup():
license=LICENSE,
platforms=PLATFORMS,
packages=find_packages(),
# 1.7.0 give too much warning related to numpy.diagonal.
install_requires=['numpy>=1.9.1', 'scipy>=0.14', 'six>=1.9.0'],
# pygments is a dependency for Sphinx code highlight
extras_require={
......
......@@ -2128,23 +2128,10 @@ class GCC_compiler(Compiler):
if march_flags and GCC_compiler.march_flags:
cxxflags.extend(GCC_compiler.march_flags)
# NumPy 1.7 Deprecate the old API. I updated most of the places
# to use the new API, but not everywhere. When finished, enable
# the following macro to assert that we don't bring new code
# NumPy 1.7 Deprecate the old API.
# The following macro asserts that we don't bring new code
# that use the old API.
cxxflags.append("-DNPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION")
numpy_ver = [int(n) for n in numpy.__version__.split('.')[:2]]
# numpy 1.7 deprecated the following macro but the new one didn't
# existed in the past
if bool(numpy_ver < [1, 7]):
cxxflags.append("-DNPY_ARRAY_ENSUREARRAY=NPY_ENSUREARRAY")
cxxflags.append("-DNPY_ARRAY_ENSURECOPY=NPY_ENSURECOPY")
cxxflags.append("-DNPY_ARRAY_ALIGNED=NPY_ALIGNED")
cxxflags.append("-DNPY_ARRAY_WRITEABLE=NPY_WRITEABLE")
cxxflags.append("-DNPY_ARRAY_UPDATE_ALL=NPY_UPDATE_ALL")
cxxflags.append("-DNPY_ARRAY_C_CONTIGUOUS=NPY_C_CONTIGUOUS")
cxxflags.append("-DNPY_ARRAY_F_CONTIGUOUS=NPY_F_CONTIGUOUS")
# Platform-specific flags.
# We put them here, rather than in compile_str(), so they en up
......
......@@ -326,12 +326,7 @@ class TestComputeTestValue(unittest.TestCase):
n_steps=k)
assert False
except ValueError as e:
# The first message is for numpy before 1.6.
# The second is a new message in numpy 1.6.
assert (str(e).startswith("shape mismatch") or
str(e).startswith("operands could not be broadcast "
"together with shapes") or
str(e).startswith("could not broadcast input")), str(e)
assert (str(e).startswith("could not broadcast input")), str(e)
finally:
theano.config.compute_test_value = orig_compute_test_value
......
......@@ -6,8 +6,6 @@ import subprocess
import sys
from locale import getpreferredencoding
import numpy
from theano import config
from theano.compat import decode, decode_with
from theano.configdefaults import local_bitwidth
......@@ -95,23 +93,11 @@ class NVCC_compiler(Compiler):
os.path.join(os.path.split(__file__)[0], 'cuda_ndarray.cuh'))
flags.append('-DCUDA_NDARRAY_CUH=' + cuda_ndarray_cuh_hash)
# NumPy 1.7 Deprecate the old API. I updated most of the places
# to use the new API, but not everywhere. When finished, enable
# the following macro to assert that we don't bring new code
# NumPy 1.7 Deprecate the old API.
# The following macro asserts that we don't bring new code
# that use the old API.
flags.append("-DNPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION")
# numpy 1.7 deprecated the following macro but the didn't
# existed in the past
numpy_ver = [int(n) for n in numpy.__version__.split('.')[:2]]
if bool(numpy_ver < [1, 7]):
flags.append("-DNPY_ARRAY_ENSURECOPY=NPY_ENSURECOPY")
flags.append("-DNPY_ARRAY_ALIGNED=NPY_ALIGNED")
flags.append("-DNPY_ARRAY_WRITEABLE=NPY_WRITEABLE")
flags.append("-DNPY_ARRAY_UPDATE_ALL=NPY_UPDATE_ALL")
flags.append("-DNPY_ARRAY_C_CONTIGUOUS=NPY_C_CONTIGUOUS")
flags.append("-DNPY_ARRAY_F_CONTIGUOUS=NPY_F_CONTIGUOUS")
# If the user didn't specify architecture flags add them
if not any(['-arch=sm_' in f for f in flags]):
# We compile cuda_ndarray.cu during import.
......
......@@ -4608,14 +4608,6 @@ class Reshape(Op):
except Exception:
raise ValueError('Cannot reshape input of shape %s to shape %s' %
(x.shape, shp))
if not out[0].flags.aligned:
raise RuntimeError("numpy.reshape returned a not aligned tensor."
" NumPy versions 1.6.2, 1.7.0 and 1.7.1 have"
" this problem for some input shape/new shape"
" combinations. Use another NumPy version."
" Input shape: %s, input stride: %s,"
" new_shape: %s, new_strides: %s." % (
x.shape, x.strides, shp, out[0].strides))
def connection_pattern(self, node):
return [[True], [False]]
......@@ -4688,7 +4680,7 @@ class Reshape(Op):
for i in xrange(self.ndim)])]
def c_code_cache_version(self):
return (6,)
return (7,)
def c_code(self, node, name, inputs, outputs, sub):
if isinstance(node.inputs[0], TensorVariable):
......@@ -4721,15 +4713,6 @@ class Reshape(Op):
//The error message should have been set by PyArray_Newshape
%(fail)s;
}
if (!PyArray_ISALIGNED(%(z)s)) {
PyErr_Format(
PyExc_RuntimeError,
"PyArray_Newshape returned an object that isn't aligned!"
" NumPy versions 1.6.2, 1.7.0 and 1.7.1 have"
" this problem for some input shape/new shape"
" combinations. Use another NumPy version.");
%(fail)s;
}
""" % locals()
else:
return Op.c_code(self, node, name, inputs, outputs, sub)
......@@ -4902,15 +4885,6 @@ class Flatten(Op):
// PyArray_Newshape
%(fail)s;
}
if (!PyArray_ISALIGNED(%(out)s)) {
PyErr_Format(
PyExc_RuntimeError,
"PyArray_Newshape returned an object that isn't"
" aligned! NumPy versions 1.6.2, 1.7.0 and 1.7.1 have"
" this problem for some input shape/new shape"
" combinations. Use another NumPy version.");
%(fail)s;
}
""" % locals()
......@@ -5455,14 +5429,6 @@ class PermuteRowElements(Op):
out[y] = x[:]
else:
out[:] = x[y]
if (numpy.__version__ <= '1.6.1' and
out.size != numpy.uint32(out.size)):
warnings.warn(
'Numpy versions 1.6.1 and below have a bug preventing '
'advanced indexing from correctly filling arrays that '
'are too big (>= 2^32 elements). It is possible that '
'out (%s), with shape %s, is not correctly filled.'
% (out, out.shape))
else:
xs0 = x.shape[0]
ys0 = y.shape[0]
......
......@@ -1419,18 +1419,8 @@ class CAReduce(Op):
"self.scalar_op (%s) has no attribute 'identity'"
% (variable, dimension, self.scalar_op)))
else:
# Numpy 1.6 has a bug where you sometimes have to specify
# "dtype='object'" in reduce for it to work, if the ufunc
# was built with "frompyfunc". We need to find out if we
# are in one of these cases (only "object" is supported in
# the output).
if ((self.ufunc.ntypes == 1) and
(self.ufunc.types[0][-1] == 'O')):
variable = self.ufunc.reduce(variable, dimension,
dtype='object')
else:
variable = self.ufunc.reduce(variable, dimension,
dtype=acc_dtype)
variable = self.ufunc.reduce(variable, dimension,
dtype=acc_dtype)
variable = numpy.asarray(variable)
if numpy.may_share_memory(variable, input):
......@@ -1545,7 +1535,7 @@ class CAReduce(Op):
if input.type.dtype in ["float32", "float64"]:
identity = "-__builtin_inf()"
elif input.type.dtype.startswith("uint"):
# numpy1.5.1 don't define NPY_MIN_UINT*
# numpy does not define NPY_MIN_UINT*
identity = "0"
else:
identity = "NPY_MIN_" + str(input.type.dtype).upper()
......
......@@ -456,10 +456,8 @@ class EighGrad(Op):
# implements the necessary logic.
out = self.tri0(g) + self.tri1(g).T
# The call to self.tri0 in perform upcast from float32 to
# float64 or from int* to int64 in numpy 1.6.1 but not in
# 1.6.2. We do not want version dependent dtype in Theano.
# We think it should be the same as the output.
# Make sure we return the right dtype even if NumPy performed
# upcasting in self.tri0.
outputs[0][0] = numpy.asarray(out, dtype=node.outputs[0].dtype)
def infer_shape(self, node, shapes):
......@@ -559,14 +557,10 @@ def qr(a, mode="reduced"):
'raw'
returns h, tau with dimensions (N, M), (K,)
The options 'reduced', 'complete', and 'raw' are new in numpy
1.8, see the notes for more information. The default is
'reduced' and to maintain backward compatibility with earlier
versions of numpy it can be
omitted. Note that array h returned in 'raw' mode is
Note that array h returned in 'raw' mode is
transposed for calling Fortran.
Default mode is 'reduced' which is also default for numpy 1.8
Default mode is 'reduced'
Returns
-------
......
......@@ -647,11 +647,6 @@ def choice(random_state, size=None, a=2, replace=True, p=None, ndim=None,
If size is None, a scalar will be returned.
"""
# numpy.random.choice is only available for numpy versions >= 1.7
major, minor, _ = numpy.version.short_version.split('.')
if (int(major), int(minor)) < (1, 7):
raise ImportError('choice requires at NumPy version >= 1.7 '
'(%s)' % numpy.__version__)
a = tensor.as_tensor_variable(a)
if isinstance(replace, bool):
replace = tensor.constant(replace, dtype='int8')
......
from __future__ import absolute_import, print_function, division
from copy import copy
import sys
from textwrap import dedent
import warnings
......@@ -13,23 +12,19 @@ import theano
from theano.compat import izip
from theano.gradient import DisconnectedType
from theano import gof
from theano.gof import Apply, Constant, hashtype, Op, Type, MethodNotDefined
from theano.gof import Apply, hashtype, Op, Type, MethodNotDefined
from theano.printing import pprint
from theano import scalar as scal
from theano.tensor.basic import alloc
from theano.tensor.basic import (addbroadcast, clip, get_scalar_constant_value,
ARange, TensorType, NotScalarConstantError)
TensorType, NotScalarConstantError)
from theano.tensor.elemwise import DimShuffle
from theano.tensor.type_other import NoneConst, SliceType, NoneTypeT, make_slice
from theano import config
inplace_increment = None
if config.cxx:
import theano.gof.cutils # needed to import cutils_ext
try:
from cutils_ext.cutils_ext import inplace_increment
except ImportError:
pass
from cutils_ext.cutils_ext import inplace_increment
_logger = logging.getLogger("theano.tensor.subtensor")
......@@ -933,8 +928,6 @@ class Subtensor(Op):
""" % locals()
finish_view = """
//This is needed for NumPy 1.5, but not 1.7.2
PyArray_UpdateFlags(xview, NPY_ARRAY_C_CONTIGUOUS| NPY_ARRAY_F_CONTIGUOUS);
Py_XDECREF(%(z)s);
Py_INCREF(py_%(x)s);
#if NPY_API_VERSION < 0x00000007
......@@ -1536,8 +1529,6 @@ class IncSubtensor(Op):
PyArray_BYTES(%(x)s) + xview_offset, //PyArray_DATA(%(x)s),
PyArray_FLAGS(%(x)s),
NULL);
//This is needed for NumPy 1.5, but not 1.7.2
PyArray_UpdateFlags(zview, NPY_ARRAY_C_CONTIGUOUS| NPY_ARRAY_F_CONTIGUOUS);
""" % locals()
def get_helper_c_code_args(self):
......@@ -2005,8 +1996,9 @@ class AdvancedIncSubtensor1(Op):
if self.set_instead_of_inc:
x[idx] = y
else:
increment = inplace_increment
if increment is None:
if config.cxx:
increment = inplace_increment
else:
increment = self.inplace_increment1d_slow
increment(x, idx, y)
......@@ -2197,12 +2189,6 @@ advanced_subtensor = AdvancedSubtensor()
class AdvancedIncSubtensor(Op):
"""
Increments a subtensor using advanced indexing.
Notes
-----
We need the numpy.inplace_increment() function currently
numpy's PR 326 to be able to make an inplace version of this op.
"""
__props__ = ("inplace", "set_instead_of_inc")
......@@ -2217,8 +2203,6 @@ class AdvancedIncSubtensor(Op):
raise NotImplementedError('In place computation is not'
' implemented')
self.allow_legacy_perform = False
def __str__(self):
return "%s{%s, %s}" % (self.__class__.__name__,
"inplace=" + str(self.inplace),
......@@ -2229,46 +2213,12 @@ class AdvancedIncSubtensor(Op):
x = theano.tensor.as_tensor_variable(x)
y = theano.tensor.as_tensor_variable(y)
op = self
# If we are incrementing, but the increment compiled function is not
# available, we need to support legacy cases.
if not self.set_instead_of_inc and inplace_increment is None:
legacy_conditions = False
if x.ndim == 2 and y.ndim == 1 and len(inputs) == 2:
ind1 = theano.tensor.as_tensor_variable(inputs[0])
ind2 = theano.tensor.as_tensor_variable(inputs[1])
if ind1.ndim == 1 and ind2.ndim == 1:
if ind1.owner and isinstance(ind1.owner.op, ARange):
legacy_conditions = True
elif isinstance(ind1, Constant):
# Make sure no index is duplicated
val = ind1.value
if numpy.unique(val).size == val.size:
legacy_conditions = True
elif ind2.owner and isinstance(ind2.owner.op, ARange):
legacy_conditions = True
elif isinstance(ind2, Constant):
# Make sure no index is duplicated
val = ind2.value
if numpy.unique(val).size == val.size:
legacy_conditions = True
if legacy_conditions:
op = copy(self)
op.allow_legacy_perform = True
else:
raise NotImplementedError(
'Could not import inplace_increment, so some advanced '
'indexing features are disabled. They will be '
'available if you update NumPy to version 1.8 or '
'later, or to the latest development version. '
'You may need to clear the cache (theano-cache clear) '
'afterwards.')
new_inputs = []
for inp in inputs:
if isinstance(inp, (list, tuple)):
inp = theano.tensor.as_tensor_variable(inp)
new_inputs.append(inp)
return gof.Apply(op,
return gof.Apply(self,
(x, y) + tuple(new_inputs),
[theano.tensor.tensor(
dtype=x.type.dtype,
......@@ -2286,27 +2236,14 @@ class AdvancedIncSubtensor(Op):
if self.set_instead_of_inc:
out[0][inputs[2:]] = inputs[1]
elif inplace_increment is not None:
elif config.cxx:
inplace_increment(out[0], tuple(inputs[2:]), inputs[1])
elif self.allow_legacy_perform:
out[0][inputs[2:]] += inputs[1]
else:
raise NotImplementedError(
'Could not import inplace_increment, so some advanced '
'indexing features are disabled. They will be '
'available if you update NumPy to version 1.8 or '
'later, or to the latest development version. '
'You may need to clear the cache (theano-cache clear) '
'afterwards.')
if (numpy.__version__ <= '1.6.1' and
out[0].size != numpy.uint32(out[0].size)):
warnings.warn(
'Numpy versions 1.6.1 and below have a bug preventing '
'advanced indexing from correctly filling arrays that '
'are too big (>= 2^32 elements). It is possible that '
'out[0] (%s), with shape %s, is not correctly filled.'
% (out[0], out[0].shape))
'Could not import inplace_increment, so advanced '
'indexing is disabled. '
'Please make sure that you have a working C++ compiler '
'and that config.cxx is correctly set.')
def infer_shape(self, node, ishapes):
return [ishapes[0]]
......
......@@ -6797,33 +6797,6 @@ class T_long_tensor(unittest.TestCase):
assert numpy.all(matrix_ct.value == val)
def test_too_big(self):
val = L(2 ** 63)
# NumPy 1.7 this will raise an exception
# NumPy 1.7.1 this will work
try:
cst = constant(val)
assert cst.value == val
assert cst.dtype == "uint64"
except OverflowError:
pass
try:
cst = constant([val, val])
assert cst.value[0] == val
assert cst.value[1] == val
assert cst.value.size == 2
assert cst.dtype == "uint64"
except TypeError:
pass
try:
cst = constant([[val, val]])
assert cst.value[0, 0] == val
assert cst.value[0, 1] == val
assert cst.value.size == 2
assert cst.dtype == "uint64"
except TypeError:
pass
val = L(2 ** 64)
# This fail for all NumPy version.
self.assertRaises(Exception, constant, val)
......
......@@ -3003,9 +3003,6 @@ class Test_alloc_zero(unittest.TestCase):
for n in f.maker.fgraph.toposort()])
def test_advancedincsubtensor_allocs0(self):
if tensor.inplace_increment is None:
raise SkipTest('NumPy version >= 1.8 not available')
x = tensor.matrix()
y = tensor.matrix()
y0 = tensor.zeros_like(y)
......@@ -3015,9 +3012,6 @@ class Test_alloc_zero(unittest.TestCase):
for n in f.maker.fgraph.toposort()])
def test_advancedincsubtensor_allocs0t(self):
if tensor.inplace_increment is None:
raise SkipTest('NumPy version >= 1.8 not available')
x = tensor.matrix()
y = tensor.matrix()
y0 = tensor.zeros_like(y)
......@@ -3027,9 +3021,6 @@ class Test_alloc_zero(unittest.TestCase):
for n in f.maker.fgraph.toposort()])
def test_advancedincsubtensor_allocs1(self):
if tensor.inplace_increment is None:
raise SkipTest('NumPy version >= 1.8 not available')
x = tensor.matrix()
y0 = tensor.constant(numpy.asarray(numpy.zeros_like((2, 2)),
dtype=config.floatX))
......@@ -3856,9 +3847,6 @@ class Test_local_useless_inc_subtensor_alloc(unittest.TestCase):
self.mode = compile.mode.get_mode(mode)
def test_advanced_inc_subtensor(self):
if tensor.inplace_increment is None:
raise SkipTest('NumPy version >= 1.8 not available')
x = tensor.vector('x')
y = tensor.scalar('y')
i = tensor.matrix('i', dtype='int64')
......@@ -3889,9 +3877,6 @@ class Test_local_useless_inc_subtensor_alloc(unittest.TestCase):
self.assertTrue(check_stack_trace(f2, ops_to_check=tensor.AdvancedIncSubtensor))
def test_advanced_inc_subtensor1(self):
if tensor.inplace_increment is None:
raise SkipTest('NumPy version >= 1.8 not available')
x = tensor.vector('x')
y = tensor.scalar('y')
i = tensor.vector('i', dtype='int64')
......
......@@ -459,12 +459,6 @@ class T_random_function(utt.InferShapeTester):
def test_choice(self):
"""Test that raw_random.choice generates the same
results as numpy."""
# numpy.random.choice is only available for numpy versions >= 1.7
major, minor, _ = numpy.version.short_version.split('.')
if (int(major), int(minor)) < (1, 7):
raise utt.SkipTest('choice requires at NumPy version >= 1.7 '
'(%s)' % numpy.__version__)
# Check over two calls to see if the random state is correctly updated.
rng_R = random_state_type()
# Use non-default parameters, and larger dimensions because of
......
......@@ -190,12 +190,6 @@ class T_SharedRandomStreams(unittest.TestCase):
def test_choice(self):
"""Test that RandomStreams.choice generates the same results as numpy"""
# numpy.random.choice is only available for numpy versions >= 1.7
major, minor, _ = numpy.version.short_version.split('.')
if (int(major), int(minor)) < (1, 7):
raise utt.SkipTest('choice requires at NumPy version >= 1.7 '
'(%s)' % numpy.__version__)
# Check over two calls to see if the random state is correctly updated.
random = RandomStreams(utt.fetch_seed())
fn = function([], random.choice((11, 8), 10, 1, 0))
......
......@@ -30,7 +30,8 @@ from theano.tensor.subtensor import (AdvancedIncSubtensor,
advanced_set_subtensor,
advanced_set_subtensor1,
get_canonical_form_slice, inc_subtensor,
inplace_increment, set_subtensor)
set_subtensor)
from theano.tensor.tests.test_basic import inplace_func, rand, randint_ranged
from theano.tests import unittest_tools as utt
from theano.tests.unittest_tools import attr
......@@ -1340,12 +1341,6 @@ class TestIncSubtensor1(unittest.TestCase):
utt.assert_allclose(out1val, out2val)
inplace_increment_missing = SkipTest(
"inc_subtensor with advanced indexing not enabled. "
"Installing NumPy 1.8 or the latest development version "
"should make that feature available.")
class TestAdvancedSubtensor(unittest.TestCase):
# test inc_subtensor
# also tests set_subtensor
......@@ -1494,8 +1489,8 @@ class TestAdvancedSubtensor(unittest.TestCase):
utt.assert_allclose(rval, aval)
def test_inc_adv_subtensor_w_2vec(self):
if inplace_increment is None:
raise inplace_increment_missing
if not config.cxx:
raise SkipTest('config.cxx empty')
subt = self.m[self.ix1, self.ix12]
a = inc_subtensor(subt, subt)
......@@ -1515,8 +1510,8 @@ class TestAdvancedSubtensor(unittest.TestCase):
[.5, .3 * 2, .15]]), aval
def test_inc_adv_subtensor_with_broadcasting(self):
if inplace_increment is None:
raise inplace_increment_missing
if not config.cxx:
raise SkipTest('config.cxx empty')
inc = dscalar()
a = inc_subtensor(self.m[self.ix1, self.ix12], inc)
......@@ -1538,8 +1533,8 @@ class TestAdvancedSubtensor(unittest.TestCase):
assert numpy.allclose(gval, 3.0), gval
def test_inc_adv_subtensor1_with_broadcasting(self):
if inplace_increment is None:
raise inplace_increment_missing
if not config.cxx:
raise SkipTest('config.cxx empty')
inc = dscalar()
a = inc_subtensor(self.m[self.ix1], inc)
......@@ -1560,8 +1555,8 @@ class TestAdvancedSubtensor(unittest.TestCase):
assert numpy.allclose(gval, 9.0), gval
def test_inc_adv_subtensor_with_index_broadcasting(self):
if inplace_increment is None:
raise inplace_increment_missing
if not config.cxx:
raise SkipTest('config.cxx empty')
a = inc_subtensor(self.m[self.ix1, self.ix2], 2.1)
......
......@@ -22,9 +22,7 @@ def hash_from_ndarray(data):
# python hash are not strong, so I always use md5 in order not to have a
# too long hash, I call it again on the concatenation of all parts.
if not data.flags["C_CONTIGUOUS"]:
# Version 1.7.1 and previous of NumPy allowed calling
# hash_from_code on an F-contiguous array, but more recent
# versions need a C-contiguous one.
# hash_from_code needs a C-contiguous array.
data = numpy.ascontiguousarray(data)
return hash_from_code(hash_from_code(data) +
hash_from_code(str(data.shape)) +
......
......@@ -88,16 +88,7 @@ class _tensor_py_operators(object):
return True
else:
raise TypeError(
"Variables do not support boolean operations. This "
"can happen if you do a logical operation (<, <=, >, <=, "
"==, !=) between a numpy.ndarray and a Theano tensor"
"variable. Due to NumPy implementation before NumPy 1.8, "
"we cannot make the Python syntax work when the ndarray "
"is on the left, and this results in this error. To work "
"around that, either call "
"theano.tensor.{lt,le,eq,ne,gt,ge}(ndarray, tensor), or "
"use the Python syntax with the Theano tensor on the "
"left. Or update to NumPy 1.8 or above."
"Variables do not support boolean operations."
)
# BITWISE
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论