私はテンソルフローの専門家ではありませんが、私が得た解決策はここにあります。私が知る限り、テンソルフローの計算はオールペアのの行列乗算やブロードキャストルールを使用する唯一の方法ですが、この解決法はある時点で両方を使用します。
入力ブール値行列がn_samples
行(1セットに1つ)、n_features
列(可能な要素ごとに1つ)としましょう。 I行目の値True
、jは番目の列は、I番目のセットは、要素Jを含むことを意味します。ちょうどscikit-learn's pairwise_distancesのように。それから、次のように進むことができます。
- キャスト
False
ためTrue
ための1と0を取得番号にマトリックス。
- マトリックスにそれ自身の転置を掛けます。これにより、各要素
M[i][j]
がi番目とj番目のセットの間の交差のサイズを含む行列が生成されます。
- 入力行列を行で合計することによって、すべての集合の基数を含むベクトルを計算します(
cardv
)。
- 行と列のベクトルを
cardv
から作成します。
- 計算
1 - M/(cardvrow + cardvcol - M)
。放送規則は、行と列ベクトルを追加するときにすべての作業を行います。
全体としてこのアルゴリズムは少しハックっぽいようだが、それは作品とのscikit-学ぶpairwise_distances
関数によって計算された結果から、合理的なマージン内の結果を生み出します。より良いアルゴリズムは、入力ベクトルのすべての対に対して単一パスを行い、対称であるので行列の半分だけを計算する必要があります。どんな改善も歓迎です。
setsin = tf.placeholder(tf.bool, shape=(N, M))
sets = tf.cast(setsin, tf.float16)
mat = tf.matmul(sets, sets, transpose_b=True, name="Main_matmul")
#mat = tf.cast(mat, tf.float32, name="Upgrade_mat")
#sets = tf.cast(sets, tf.float32, name="Upgrade_sets")
cardinal = tf.reduce_sum(sets, 1, name="Richelieu")
cardinalrow = tf.expand_dims(cardinal, 0)
cardinalcol = tf.expand_dims(cardinal, 1)
mat = 1 - mat/(cardinalrow + cardinalcol - mat)
それはfloat32
よりもはるかに速いようだと私はfloat16
タイプを使用。 float32
へのキャスティングは、枢機卿が不正確であるか、または除算を実行するときにさらに精度が必要な場合にのみ有用です。しかし、キャストが必要な場合であっても、行列乗算をfloat16
として行うことは、まだ関連しているようです。
3つの行列乗算がありますが、パフォーマンスが悪い可能性があります。 – Celelibi