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

时间:2018-01-27 16:40:16

标签: python tensorflow machine-learning artificial-intelligence nearest-neighbor

我试图使用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

但是如何通过D输入A将其扩展为N,例如A = tf.constant([[1, 1, 2, 4, 4, 4, 7, 8, 8], [2, 2, 3, 3, 3, 4, 4, 5, 6]])

时的情况

2 个答案:

答案 0 :(得分: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 :(得分: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())