【问题标题】:numpy random choice in TensorflowTensorflow中的numpy随机选择
【发布时间】:2017-04-28 16:16:31
【问题描述】:

Tensorflow 中是否有与 numpy 随机选择等效的函数。 在 numpy 中,我们可以从给定列表中随机获取一个项目及其权重。

 np.random.choice([1,2,3,5], 1, p=[0.1, 0, 0.3, 0.6, 0])

此代码将从给定列表中选择具有 p 个权重的项目。

【问题讨论】:

  • ValueError: 'a' and 'p' must have the same size

标签: python numpy tensorflow deep-learning


【解决方案1】:

不,但您可以使用tf.multinomial 获得相同的结果:

elems = tf.convert_to_tensor([1,2,3,5])
samples = tf.multinomial(tf.log([[1, 0, 0.3, 0.6]]), 1) # note log-prob
elems[tf.cast(samples[0][0], tf.int32)].eval()
Out: 1
elems[tf.cast(samples[0][0], tf.int32)].eval()
Out: 5

[0][0] 部分在这里,因为multinomial 期望批次的每个元素都有一行未标准化的对数概率,并且样本数量还有另一个维度。

【讨论】:

  • 如何将其扩展到 (i) 动态张量的情况,其形状只能在执行期间推断,以及 (ii) 该张量中每个元素的选择概率相等?
  • 我会尝试类似:tf.multinomial(tf.ones_like(dynamic_tensor), num_samples=1).
【解决方案2】:

如果您希望从 n 维张量中随机抽样行,而不是从 1 维张量中抽样随机元素,则可以组合 tf.multinomialtf.gather

def _random_choice(inputs, n_samples):
    """
    With replacement.
    Params:
      inputs (Tensor): Shape [n_states, n_features]
      n_samples (int): The number of random samples to take.
    Returns:
      sampled_inputs (Tensor): Shape [n_samples, n_features]
    """
    # (1, n_states) since multinomial requires 2D logits.
    uniform_log_prob = tf.expand_dims(tf.zeros(tf.shape(inputs)[0]), 0)

    ind = tf.multinomial(uniform_log_prob, n_samples)
    ind = tf.squeeze(ind, 0, name="random_choice_ind")  # (n_samples,)

    return tf.gather(inputs, ind, name="random_choice")

【讨论】:

    【解决方案3】:

    在 tf.你可以直接使用 np.random.choice(data, p=probs) 来做,tf 可以接受。

    【讨论】:

    • 但它不在 gpu 上
    【解决方案4】:

    我和我的团队在将所有操作保留为 tensorflow 操作并实施“无替换”版本的要求方面遇到了同样的问题。

    解决方案:

    def tf_random_choice_no_replacement_v1(one_dim_input, num_indices_to_drop=3):
    
        input_length = tf.shape(one_dim_input)[0]
    
        # create uniform distribution over the sequence
        # for tf.__version__<1.11 use tf.random_uniform - no underscore in function name
        uniform_distribution = tf.random.uniform(
            shape=[input_length],
            minval=0,
            maxval=None,
            dtype=tf.float32,
            seed=None,
            name=None
        )
    
        # grab the indices of the greatest num_words_to_drop values from the distibution
        _, indices_to_keep = tf.nn.top_k(uniform_distribution, input_length - num_indices_to_drop)
        sorted_indices_to_keep = tf.contrib.framework.sort(indices_to_keep)
    
        # gather indices from the input array using the filtered actual array
        result = tf.gather(one_dim_input, sorted_indices_to_keep)
        return result
    

    此代码背后的想法是生成一个随机均匀分布,其维度等于您要执行选择的向量的维度。由于分布将产生一系列唯一且能够排名的数字,因此您可以获取前 k 个位置的索引,并将其用作您的选择。由于top k的位置会和均匀分布一样随机,所以相当于进行了不放回的随机选择。

    这可以对tensorflow中的任何一维序列进行选择操作。

    【讨论】:

    • OP 的问题不假设均匀分布。每个选择的概率都被指定了。
    • 感谢您的回答!这对我正在从事的项目很有帮助,我同样在寻找用 replace=False 替换 np.random.choice 的张量流。
    【解决方案5】:

    聚会很晚,但我会添加另一个解决方案,因为现有的tf.multinomial 方法会占用大量临时内存,因此不能用于大量输入。这是我使用的方法(对于 TF 2.0):

    # Sampling k members of 1D tensor a using weights w
    cum_dist = tf.math.cumsum(w)
    cum_dist /= cum_dist[-1]  # to account for floating point errors
    unif_samp = tf.random.uniform((k,), 0, 1)
    idxs = tf.searchsorted(cum_dist, unif_samp)
    samp = tf.gather(a, idxs)  # samp contains the k weighted samples
    

    【讨论】:

    • 有没有机会将它用于形状 [batch,timesteps,probabilities] 的张量?对于混合密度网络,每个时间步都有少量分配给它的概率,例如[0.2,0.1,0.7]。要求是每行从另一个相同形状的张量中选择一个,导致 [batch,timesteps,1]
    【解决方案6】:

    在 tensorflow 2.0 中,tf.compat.v1.multinomial 已弃用,而是使用 tf.random.categorical

    【讨论】:

      【解决方案7】:
      N = np.random.choice([0,1,2,3,4], 5000, p=[i/sum(range(1,6)) for i in range(1,6)])
      plt.hist(N, density=True, bins=5)
      plt.grid()
      

      T = tf.random.categorical(tf.math.log([[i/sum(range(1,6)) for i in range(1,6)]]), 5000)
      # T = tf.random.categorical([[i/sum(range(1,6)) for i in range(1,6)]], 1000)
      plt.hist(T, density=True, bins=5)
      plt.grid()
      

          def random_choice(a, size):
              """Random choice from 'a' based on size without duplicates
              Args:
                  a: Tensor
                  size: int or shape as tuple of ints e.g., (m, n, k).
              Returns: Tensor of the shape specified with 'size' arg.
      
              Examples:
                  X = tf.constant([[1,2,3],[4,5,6]])
                  random_choice(X, (2,1,2)).numpy()
                  -----
                  [
                    [
                      [5 4]
                    ],
                    [
                      [1 2]
                    ]
                  ]
              """
              if isinstance(size, int) or np.issubdtype(type(a), np.integer) or (tf.is_tensor(a) and a.shape == () and a.dtype.is_integer):
                  shape = (size,)
              elif isinstance(size, tuple) and len(size) > 0:
                  shape = size
              else:
                  raise AssertionError(f"Unexpected size arg {size}")
      
              sample_size = tf.math.reduce_prod(size, axis=None)
              assert sample_size > 0
      
              # --------------------------------------------------------------------------------
              # Select elements from a flat array
              # --------------------------------------------------------------------------------
              a = tf.reshape(a, (-1))
              length = tf.size(a)
              assert sample_size <= length
      
              # --------------------------------------------------------------------------------
              # Shuffle a sequential numbers (0, ..., length-1) and take size.
              # To select 'sample_size' elements from a 1D array of shape (length,),
              # TF Indices needs to have the shape (sample_size,1) where each index
              # has shape (1,),
              # --------------------------------------------------------------------------------
              indices = tf.reshape(
                  tensor=tf.random.shuffle(tf.range(0, length, dtype=tf.int32))[:sample_size],
                  shape=(-1, 1)   # Convert to the shape:(sample_size,1)
              )
              return tf.reshape(tensor=tf.gather_nd(a, indices), shape=shape)
      
      
      X = tf.constant([[1,2,3],[4,5,6]])
      print(random_choice(X, (2,2,1)).numpy())
      ---
      [[[5]
        [4]]
      
       [[2]
        [1]]]
      

      【讨论】:

        【解决方案8】:

        派对也很晚了,我找到了最简单的解决方案。

        #sample source matrix
        M = tf.constant(np.arange(4*5).reshape(4,5))
        N_samples = 2
        tf.gather(M, tf.cast(tf.random.uniform([N_samples])*M.shape[0], tf.int32), axis=0)
        

        【讨论】:

          猜你喜欢
          • 2014-06-20
          • 2017-09-16
          • 1970-01-01
          • 1970-01-01
          • 2014-04-21
          • 2014-05-22
          • 1970-01-01
          • 2018-03-25
          • 2014-05-15
          相关资源
          最近更新 更多