3

可変数の配列に対してデカルト積を効率的に実装する必要があります。

productの機能を試してみましたIterators.jlが、性能不足でした。

私は Python ハッカーであり、sklearn のこの関数を使用しており、良好なパフォーマンス結果が得られています。

この関数の Julia バージョンを作成しようとしましたが、Python 関数と同じ結果を生成できません。

私のコードは次のとおりです。

function my_repeat(a, n)
    # mimics numpy.repeat
    m = size(a, 1)
    out = Array(eltype(a), n * m)
    out[1:n] = a[1]
    for i=2:m
        out[(i-1)*n+1:i*n] = a[i]
    end
    return out
end

function cartesian(arrs; out=None)
    dtype = eltype(arrs[1])

    n = prod([size(i, 1) for i in arrs])

    if is(out, None)
        out = Array(dtype, n, length(arrs))
    end

    m = int(n / size(arrs[1], 1))
    out[:, 1] = my_repeat(arrs[1], m)

    if length(arrs[2:]) > 0
        cartesian(arrs[2:], out=out[1:m, 2:])
        for j = 1:size(arrs[1], 1)-1
            out[(j*m + 1):(j+1)*m, 2:] = out[1:m, 2:]
        end
    end

    return out
end

私は次のようにテストします:

aa = ([1, 2, 3], [4, 5], [6, 7])
cartesian(aa)

戻り値は次のとおりです。

12x3 Array{Float64,2}:
1.0  9.88131e-324  2.13149e-314
1.0  2.76235e-318  2.13149e-314
1.0  9.88131e-324  2.13676e-314
1.0  9.88131e-324  2.13676e-314
2.0  9.88131e-324  2.13149e-314
2.0  2.76235e-318  2.13149e-314
2.0  9.88131e-324  2.13676e-314
2.0  9.88131e-324  2.13676e-314
3.0  9.88131e-324  2.13149e-314
3.0  2.76235e-318  2.13149e-314
3.0  9.88131e-324  2.13676e-314
3.0  9.88131e-324  2.13676e-314

ここでの問題は、この行を使用すると: cartesian(arrs[2:], out=out[1:m, 2:])、キーワード引数outが再帰呼び出しでインプレースで更新されないことだと思います。

ご覧のとおり、この関数の Python バージョンを非常に単純に変換しました (上記のリンクを参照)。単純な翻訳を不可能にする内部言語の違いが存在する可能性は十分にあります。ジュリアのドキュメントの関数セクションからのこの引用のため、これは真実ではないと思います:

Julia 関数の引数は、「共有渡し」と呼ばれることもある規則に従います。これは、値が関数に渡されるときに値がコピーされないことを意味します。関数の引数自体は新しい変数バインディング (値を参照できる新しい場所) として機能しますが、それらが参照する値は渡された値と同じです。関数内で変更可能な値 (配列など) への変更は、呼び出し元に表示されます。これは、Scheme、ほとんどの Lisp、Python、Ruby、および Perl などの動的言語で見られるのと同じ動作です。

Juliaでこの(または同等の)関数を機能させるにはどうすればよいですか?

4

3 に答える 3

4

repeatBase には関数があります。

短くて高速なバリアントは@forcartesian、Cartesian パッケージのマクロを使用する可能性があります。

using Cartesian

function cartprod(arrs, out=Array(eltype(arrs[1]), prod([length(a) for a in arrs]), length(arrs)))
    sz = Int[length(a) for a in arrs]
    narrs = length(arrs)
    @forcartesian I sz begin
        k = sub2ind(sz, I)
        for i = 1:narrs
            out[k,i] = arrs[i][I[i]]
        end
    end
    out
end

行の順序はあなたのソリューションとは異なりますが、おそらくそれは問題ではありませんか?

于 2013-10-22T09:27:29.077 に答える