在Julia中从大型数组中对子列集进行子采样的最快方法

时间:2016-07-20 23:30:14

标签: arrays subset julia

我对在大数据矩阵的不同随机采样子集上执行统计感兴趣,现在我的代码中的瓶颈是实际的子采样。这对我来说似乎很奇怪,因为在二次采样数据上有相当数量的O(N ^ 2)距离计算。我根本没有修改子样本,只是看着它们。

using Distributions, Distances

function test_subsetting(X; batch_size=500, nloops=100)
    nfeatures, nsamples = size(X)
    ref_samples = X[:,1:10]
    batch_inds = zeros(batch_size)
    batch = zeros(nfeatures,batch_size)
    d_matrix = zeros(batch_size,batch_size)
    for i = 1:nloops
        batch_inds = sort(sample(1:nsamples, batch_size, replace = false))
        batch = X[:,batch_inds]
        d_matrix = pairwise(SqEuclidean(), batch, ref_samples)
    end
end

当我通过50000样本矩阵在5000特征上测试时:

X_test = randn(5000,50000);

我发现我花了大约一半的时间在_unsafe_getindex multidimensional.jl,而另一半花在距离计算上。

有没有更有效的方法来解决这个问题?

2 个答案:

答案 0 :(得分:3)

这对我来说是julia 0.5:

julia> using Distances, Distributions

julia> X = randn(500,1000);

julia> S = sample(1:1000,500,replace=false);

julia> M = view(X, :, S);

julia> S2 = sample(1:1000,500,replace=false);

julia> R = view(X, :, S2);

julia> pairwise(SqEuclidean(), M, R)
500×500 Array{Float64,2}:
  994.67 ...
...
关于julia 0.5的

view在julia 0.4上被称为slice(或sub,这里它们将是相同的)。不要与ArrayViews.view混淆,view执行类似但具有完全不同的实现。

从理论上讲,您似乎应该只能将slice替换为At_mul_B!,但似乎julia 0.4上缺少{{1}}方法。所以你可能会被困在制作副本。

答案 1 :(得分:2)

如果您乐意“预先生成”随后在运行时引用的随机索引的大矩阵,则可以完全缩短“采样”时间。您甚至可以在每次使用之前为该矩阵提供一些“行和列”洗牌,并且成本最低。

另外,为什么你需要排序呢?当然,这会使随机抽样失败,并引入不必要的计算?