2

のような配列db(およそ になります(1e6, 300)) とmask = [1, 0, 1]ベクトルから、最初の列でターゲットを 1 として定義します。

の対応する行が and と一致するものと、それ以外の場所のゼロoutで構成されるベクトルを作成したいと考えています。dbmasktarget==1

db = np.array([       # out for mask = [1, 0, 1]
# target,  vector     #
  [1,      1, 0, 1],  # 1
  [0,      1, 1, 1],  # 0 (fit to mask but target == 0)
  [0,      0, 1, 0],  # 0
  [1,      1, 0, 1],  # 1
  [0,      1, 1, 0],  # 0
  [1,      0, 0, 0],  # 0
  ])

ベクトル 101 と 111 がマスクに適合することを確認するために を使用して各配列行に をvline適用し、インデックスのみを保持する関数を定義しました。masknp.array_equal(mask, mask & vector)target == 1

outに初期化されますarray([0, 0, 0, 0, 0, 0])

out = [0, 0, 0, 0, 0, 0]

vline関数は次のように定義されます。

def vline(idx, mask):
    line = db[idx]
    target, vector = line[0], line[1:]
    if np.array_equal(mask, mask & vector):
        if target == 1:
            out[idx] = 1

この関数を 1 行forずつループに適用すると、正しい結果が得られます。

def check_mask(db, out, mask=[1, 0, 1]):
    # idx_db to iterate over db lines without enumerate
    for idx in np.arange(db.shape[0]):
        vline(idx, mask=mask)
    return out

assert check_mask(db, out, [1, 0, 1]) == [1, 0, 0, 1, 0, 0] # it works !

vline今、次を作成してベクトル化したいufunc:

ufunc_vline = np.frompyfunc(vline, 2, 1)
out = [0, 0, 0, 0, 0, 0]
ufunc_vline(db, [1, 0, 1])
print out

しかし、ufuncこれらの形状で入力をブロードキャストすることについて不満があります。

In [217]:     ufunc_vline(db, [1, 0, 1])
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-217-9008ebeb6aa1> in <module>()
----> 1 ufunc_vline(db, [1, 0, 1])
ValueError: operands could not be broadcast together with shapes (6,4) (3,)
In [218]:
4

1 に答える 1

1

numpy ufuncvlineへの変換は基本的に意味がありません。ufunc は常に numpy 配列に要素ごとに適用されるためです。このため、入力引数は同じ形状であるか、同じ形状にブロードキャスト可能でなければなりません。互換性のない形状の 2 つの配列を関数 (および) に渡しているため、表示されています。ufunc_vlinedb.shape == (6, 4)mask.shape == (3,)ValueError

には他にもいくつかの問題がありますufunc_vline

  • np.frompyfunc(vline, 2, 1)vlineは単一の出力引数を返す必要があることを指定しますが、vline実際には何も返しません (ただし、その場で変更outします)。

  • db最初の引数として に渡していますが、 では最初の引数がufunc_vlineであるvlineと想定idxされており、これは の行へのインデックスとして使用されますdb

また、を使用して Python 関数から ufunc を作成しても、標準の Pythonループnp.frompyfuncよりも顕著なパフォーマンス上の利点が得られないことに注意してください。for大幅な改善を確認するには、おそらく C などの低レベル言語で ufunc をコーディングする必要があります (ドキュメントのこの例を参照してください)。


そうは言っても、vline関数は標準のブール配列操作を使用して簡単にベクトル化できます。

def vline_vectorized(db, mask): 
    return db[:, 0] & np.all((mask & db[:, 1:]) == mask, axis=1)

例えば:

db = np.array([       # out for mask = [1, 0, 1]
# target,  vector     #
  [1,      1, 0, 1],  # 1
  [0,      1, 1, 1],  # 0 (fit to mask but target == 0)
  [0,      0, 1, 0],  # 0
  [1,      1, 0, 1],  # 1
  [0,      1, 1, 0],  # 0
  [1,      0, 0, 0],  # 0
  ])

mask = np.array([1, 0, 1])

print(repr(vline_vectorized(db, mask)))
# array([1, 0, 0, 1, 0, 0])
于 2015-12-29T16:11:16.000 に答える