2016-12-02 86 views
3

为了进行K-fold验证,我想使用slice一个numpy数组,以便创建原始数组的视图,但删除每个第n个元素。跳过numpy数组的每个第n个索引

例如:[0,1,2,3,4,5,6,7,8,9]

如果n = 4,则结果将是[1,2,4,5, 6,8,9]

注意:numpy要求是由于这被用于机器学习任务,其中依赖关系是固定的。

+0

对于交叉验证的用例这种方法看起来很可怕。关于数据的顺序有一些隐藏的假设。我更喜欢一些基于shuffle/random_permutation的方法,但也会坚持[scikit-learn](http://scikit-learn.org/stable/model_selection.html)中提供的功能,因为还有更强大的功能如分层抽样(如果需要)。注意:把你的标签清理成'''fold'''(函数式编程)和''''k'''(编程语言)是错误的。 – sascha

+0

我同意sascha。特别是,看看交叉验证迭代器。 http://scikit-learn.org/stable/modules/cross_validation.html#cross-validation-iterators –

+0

@sascha我同意使用现有的库会更好但是我应该提到我只能使用numpy作为依赖因为这是一个机器学习任务抱歉!为了实现随机性,我使用'np.random.shuffle'来混洗行。 –

回答

5

方法#1 modulus

a[np.mod(np.arange(a.size),4)!=0] 

样品运行 -

In [255]: a 
Out[255]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) 

In [256]: a[np.mod(np.arange(a.size),4)!=0] 
Out[256]: array([1, 2, 3, 5, 6, 7, 9]) 

方法#2 masking:要求作为view

考虑到视图要求,如果想法是节省内存,我们可以存储相当的布尔数组,这会在Linux系统上占用内存少8的空间。因此,这种面具为基础的方法是像这样 -

# Create mask 
mask = np.ones(a.size, dtype=bool) 
mask[::4] = 0 

这里的内存需求统计 -

In [311]: mask.itemsize 
Out[311]: 1 

In [312]: a.itemsize 
Out[312]: 8 

然后,我们可以使用布尔索引的视图 -

In [313]: a 
Out[313]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) 

In [314]: a[mask] = 10 

In [315]: a 
Out[315]: array([ 0, 10, 10, 10, 4, 10, 10, 10, 8, 10]) 

方法3与NumPy array strides:要求作为view

如果输入数组的长度为n的倍数,则可以使用np.lib.stride_tricks.as_strided来创建这样的视图。如果它不是多个,它仍然可以工作,但不会是一个安全的做法,因为我们将超出分配给输入数组的内存。请注意,这样创建的视图将是2D

因此,implementaion得到这样的图将是 -

def skipped_view(a, n): 
    s = a.strides[0] 
    strided = np.lib.stride_tricks.as_strided 
    return strided(a,shape=((a.size+n-1)//n,n),strides=(n*s,s))[:,1:] 

样品运行 -

In [50]: a = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]) # Input array 

In [51]: a_out = skipped_view(a, 4) 

In [52]: a_out 
Out[52]: 
array([[ 1, 2, 3], 
     [ 5, 6, 7], 
     [ 9, 10, 11]]) 

In [53]: a_out[:] = 100 # Let's prove output is a view indeed 

In [54]: a 
Out[54]: array([ 0, 100, 100, 100, 4, 100, 100, 100, 8, 100, 100, 100]) 
+0

伟大的答案谢谢@Divakar#2看起来像我最好的解决方案 –

+0

@BenHazelwood我同意,这是一个通用的解决方案。 – Divakar

2

numpy.delete

In [18]: arr = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) 

In [19]: arr = np.delete(arr, np.arange(0, arr.size, 4)) 

In [20]: arr 
Out[20]: array([1, 2, 3, 5, 6, 7, 9]) 
+1

这看起来不像**视图**。 – sascha

+0

我同意@sascha的观点,如果存在更高效的内存方法,它会更好 –