8000 BUG: copy and keep ordering · seckcoder/scikit-learn@08d170d · GitHub
[go: up one dir, main page]

Skip to content

Commit 08d170d

Browse files
committed
BUG: copy and keep ordering
This is due to a change in behavior in numpy that now does not keep the ordering by default when copying. Fixes scikit-learn#1186 Conflicts: sklearn/utils/validation.py
1 parent 133aaf0 commit 08d170d

File tree

4 files changed

+39
-13
lines changed

4 files changed

+39
-13
lines changed

sklearn/linear_model/coordinate_descent.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ def fit(self, X, y, Xy=None, coef_init=None):
154154
"""
155155
X = atleast2d_or_csc(X, dtype=np.float64, order='F',
156156
copy=self.copy_X and self.fit_intercept)
157+
print X.strides, X.shape
157158
# From now on X can be touched inplace
158159
y = np.asarray(y, dtype=np.float64)
159160
# now all computation with X can be done inplace

sklearn/utils/fixes.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@
1010
# License: BSD
1111

1212
import collections
13-
import numpy as np
1413
from operator import itemgetter
14+
import inspect
1515

16+
import numpy as np
1617

1718
try:
1819
Counter = collections.Counter
@@ -176,3 +177,15 @@ def savemat(file_name, mdict, oned_as="column", **kwargs):
176177
except ImportError:
177178
def count_nonzero(X):
178179
return len(np.flatnonzero(X))
180+
181+
# little danse to see if np.copy has an 'order' keyword argument
182+
if 'order' in inspect.getargspec(np.copy)[0]:
183+
def safe_copy(X):
184+
# Copy, but keep the order
185+
return np.copy(X, order='K')
186+
else:
187+
# Before an 'order' argument was introduced, numpy wouldn't muck with
188+
# the ordering
189+
safe_copy = np.copy
190+
191+

sklearn/utils/tests/test_validation.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,20 @@ def test_memmap():
8989
X[:] = 1
9090
assert_array_equal(X.ravel(), M)
9191
X[:] = 0
92+
93+
94+
def test_ordering():
95+
# Check that ordering is enforced correctly by the different
96+
# validation utilities
97+
# We need to check each validation utility, because a 'copy' without
98+
# 'order=K' will kill the ordering
99+
X = np.ones((10, 5))
100+
for A in X, X.T:
101+
for validator in (array2d, atleast2d_or_csr, atleast2d_or_csc):
102+
for copy in (True, False):
103+
B = validator(A, order='C', copy=copy)
104+
assert_true(B.flags['C_CONTIGUOUS'])
105+
B = validator(A, order='F', copy=copy)
106+
assert_true(B.flags['F_CONTIGUOUS'])
107+
if copy:
108+
assert_false(A is B)

sklearn/utils/validation.py

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
"""
2-
Utilities for input validation
3-
"""
1+
"""Utilities for input validation"""
2+
# Authors: Olivier Grisel and Gael Varoquaux and others (please update me)
3+
# License: BSD 3
44

55
import numpy as np
66
from scipy import sparse
77
import warnings
88

9+
from .fixes import safe_copy
910

1011
def assert_all_finite(X):
1112
"""Throw a ValueError if X contains NaN or infinity.
@@ -68,7 +69,7 @@ def array2d(X, dtype=None, order=None, copy=False):
6869
'is required. Use X.todense() to convert to dense.')
6970
X_2d = np.asarray(np.atleast_2d(X), dtype=dtype, order=order)
7071
if X is X_2d and copy:
71-
X_2d = X_2d.copy()
72+
X_2d = safe_copy(X_2d)
7273
return X_2d
7374

7475

@@ -77,18 +78,15 @@ def atleast2d_or_csc(X, dtype=None, order=None, copy=False):
7778
7879
Also, converts np.matrix to np.ndarray.
7980
"""
80-
X_init = X
8181
if sparse.issparse(X):
8282
# Note: order is ignored because CSR matrices hold data in 1-d arrays
8383
if dtype is None or X.dtype == dtype:
8484
X = X.tocsc()
8585
else:
8686
X = sparse.csc_matrix(X, dtype=dtype)
8787
else:
88-
X = array2d(X, dtype=dtype, order=order)
88+
X = array2d(X, dtype=dtype, order=order, copy=copy)
8989
assert_all_finite(X)
90-
if X is X_init and copy:
91-
X = X.copy()
9290
return X
9391

9492

@@ -97,18 +95,15 @@ def atleast2d_or_csr(X, dtype=None, order=None, copy=False):
9795
9896
Also, converts np.matrix to np.ndarray.
9997
"""
100-
X_init = X
10198
if sparse.issparse(X):
10299
# Note: order is ignored because CSR matrices hold data in 1-d arrays
103100
if dtype is None or X.dtype == dtype:
104101
X = X.tocsr()
105102
else:
106103
X = sparse.csr_matrix(X, dtype=dtype)
107104
else:
108-
X = array2d(X, dtype=dtype, order=order)
105+
X = array2d(X, dtype=dtype, order=order, copy=copy)
109106
assert_all_finite(X)
110-
if X is X_init and copy:
111-
X = X.copy()
112107
return X
113108

114109

0 commit comments

Comments
 (0)
0