如何对张量的每一行/列使用tf.unique_with_counts函数

3
我正在尝试使用TensorFlow解决KNN问题。在获取N个向量的K个最近邻之后,我获得了一个N*K的张量。现在,对于N中的每个向量,我需要使用tf.unique_with_counts来找到多数票。但是,我不能在张量中进行迭代,并且我不能使用多维张量运行tf.unique_with_counts。它一直给我InvalidArgumentError (see above for traceback): unique expects a 1D vector.错误。 示例:
def knnVote():
  '''
  KNN using majority vote
  '''
  #nearest indices
  A = tf.constant([1, 1, 2, 4, 4, 4, 7, 8, 8])
  print(A.shape)

  nearest_k_y, idx, votes = tf.unique_with_counts(A)
  print("y", nearest_k_y.eval())
  print("idx", idx.eval())
  print("votes", votes.eval())
  majority = tf.argmax(votes)
  predict_res = tf.gather(nearest_k_y, majority)


  print("majority", majority.eval())
  print("predict", predict_res.eval())
  return predict_res

结果:

y [1 2 4 7 8]
idx [0 0 1 2 2 2 3 4 4]
votes [2 1 3 1 2]
majority 2
predict 4

但是如何将此扩展到NxD输入A,例如当A = tf.constant([[1, 1, 2, 4, 4, 4, 7, 8, 8], [2, 2, 3, 3, 3, 4, 4, 5, 6]])的情况呢?

2个回答

1
你可以使用 tf.while_loop 来迭代处理每一行的A。这需要一些关于 shape_invariants 的黑魔法(用来累积结果)和在循环体中仔细地处理。但是,如果你花费一些时间来仔细研究它,它会变得更加清晰明了。
以下是代码:
def multidimensionalKnnVote():
  A = tf.constant([
    [1, 1, 2, 4, 4, 4, 7, 8, 8],
    [2, 2, 3, 3, 3, 4, 4, 5, 6],
  ])

  def cond(i, all_idxs, all_vals):
    return i < A.shape[0]

  def body(i, all_idxs, all_vals):
    nearest_k_y, idx, votes = tf.unique_with_counts(A[i])
    majority_idx = tf.argmax(votes)
    majority_val = nearest_k_y[majority_idx]

    majority_idx = tf.reshape(majority_idx, shape=(1,))
    majority_val = tf.reshape(majority_val, shape=(1,))

    new_idxs = tf.cond(tf.equal(i, 0),
                       lambda: majority_idx,
                       lambda: tf.concat([all_idxs, majority_idx], axis=0))

    new_vals = tf.cond(tf.equal(i, 0),
                       lambda: majority_val,
                       lambda: tf.concat([all_vals, majority_val], axis=0))

    return i + 1, new_idxs, new_vals

  # This means: starting from 0, apply the `body`, while the `cond` is true.
  # Note that `shape_invariants` allow the 2nd and 3rd tensors to grow.
  i0 = tf.constant(0)
  idx0 = tf.constant(0, shape=(1,), dtype=tf.int64)
  val0 = tf.constant(0, shape=(1,), dtype=tf.int32)
  _, idxs, vals = tf.while_loop(cond, body,
                                loop_vars=(i0, idx0, val0),
                                shape_invariants=(i0.shape, tf.TensorShape([None]), tf.TensorShape([None])))

  print('majority:', idxs.eval())
  print('predict:', vals.eval())

1
您可以使用tf.map_fn将一个函数应用于矩阵变量的每一行。
def knnVote(A):
  nearest_k_y, idx, votes = tf.unique_with_counts(A)
  majority = tf.argmax(votes)
  predict_res = tf.gather(nearest_k_y, majority)
  return predict_res

sess = tf.Session()
with sess.as_default():
  B = tf.constant([[1, 1, 2, 4, 4, 4, 7, 8, 8],
                   [2, 2, 3, 3, 3, 4, 4, 5, 6]])
  C = tf.map_fn(knnVote, B)
  print(C.eval())

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接