2017-04-06 11 views
0

Jaccard距離を使って距離行列を計算したいと思います。そしてできるだけ早くそれをしてください。私はscikit-learn's pairwise_distances関数を使用していました。しかしscikit-learnはGPUをサポートする予定はなく、並行して実行すると機能を遅くするknown bugもあります。ヤコカードのテンソルフロー距離行列

私の唯一の制約は、得られた距離行列をscikit-learn's DBSCANクラスタリングアルゴリズムに供給できることです。私はtensorflowで計算を実装することを考えていましたが、それを行うためのすてきで簡単な方法を見つけることができませんでした。


PS:私は、必要に応じてDBSCANにそれをさせるのではなく、距離行列を事前計算する理由があります。

答えて

3

私はテンソルフローの専門家ではありませんが、私が得た解決策はここにあります。私が知る限り、テンソルフローの計算はオールペアのの行列乗算やブロードキャストルールを使用する唯一の方法ですが、この解決法はある時点で両方を使用します。

入力ブール値行列がn_samples行(1セットに1つ)、n_features列(可能な要素ごとに1つ)としましょう。 I行目の値Truejは番目の列は、I番目のセットは、要素Jを含むことを意味します。ちょうどscikit-learn's pairwise_distancesのように。それから、次のように進むことができます。

  1. キャストFalseためTrueための1と0を取得番号にマトリックス。
  2. マトリックスにそれ自身の転置を掛けます。これにより、各要素M[i][j]i番目とj番目のセットの間の交差のサイズを含む行列が生成されます。
  3. 入力行列を行で合計することによって、すべての集合の基数を含むベクトルを計算します(cardv)。
  4. 行と列のベクトルをcardvから作成します。
  5. 計算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として行うことは、まだ関連しているようです。

1

ヘイ私は同じ問題に直面していました。ジャカード類似性が真の陽性、偽陰性(FN)と偽陽性(FP)の合計に対する真postives(TP)の比率であるという考えを考える

は、私はこの解決策を考え出した:

def jaccard_distance(self): 
     tp = tf.reduce_sum(tf.mul(self.target, self.prediction), 1) 
     fn = tf.reduce_sum(tf.mul(self.target, 1-self.prediction), 1) 
     fp = tf.reduce_sum(tf.mul(1-self.target, self.prediction), 1) 
     return 1 - (tp/(tp + fn + fp)) 

希望します。

+0

3つの行列乗算がありますが、パフォーマンスが悪い可能性があります。 – Celelibi

関連する問題