【问题标题】:Creating n-hot vector in numpy在 numpy 中创建 n-hot 向量
【发布时间】:2018-10-13 12:39:31
【问题描述】:

说我有

q = np.array(['a', 'b']) 
terms = np.array(['a', 'b', 'c', 'd'])

如何创建一个 n-hot 向量 v,如 [1, 1, 0, 0],以便出现在 q 中的每个项目在 length = len(terms) 的零向量中将其索引设置为 1?

【问题讨论】:

    标签: python numpy


    【解决方案1】:

    你可以使用np.isin,把它变成int的数组:

    >>> np.isin(terms,q).astype(int)
    array([1, 1, 0, 0])
    

    【讨论】:

      【解决方案2】:

      如果您有 pandas,则可以使用 pd.Index API 快速(恒定时间)搜索每个术语:

      >>> idx = pd.Index(q)
      >>> (idx.get_indexer_for(terms) >= 0).astype(int)
      array([1, 1, 0, 0])
      

      另一个选项是广播比较:

      >>> (q == terms[:, None]).any(1).astype(int)
      array([1, 1, 0, 0])
      

      这很快,但您应该更喜欢第一个选项,或者@sacul 对大型 (~1M) 数据的回答。

      【讨论】:

        【解决方案3】:

        这是一种基于searchsorted 的方法,该方法快速且易于应用于批量向量:

        时间为 4、12 和 26 个类别以及 1000 个长度为 2 的向量的批次。broadcast 是 @coldspeed 的方法。

        4
        broadcast   :      0.248 ms
        searchsorted:      0.095 ms
        12
        broadcast   :      0.468 ms
        searchsorted:      0.119 ms
        26
        broadcast   :      0.748 ms
        searchsorted:      0.137 ms
        

        代码:

        import numpy as np
        from string import ascii_lowercase
        
        def broadcast(test, classes):
            return (test[..., None] == classes).any(-2).view(np.uint8)
        
        def searchsorted(test, classes):
            X = classes.argsort()
            out = np.zeros((*test.shape[:-1], classes.size), np.uint8)
            idx = np.ogrid[tuple(map(slice, out.shape))]
            idx = *idx[:-1], X[classes[X].searchsorted(test)]
            out[idx] = 1
            return out
        
        letters = np.fromiter(ascii_lowercase, 'U1', 26)
        np.random.shuffle(letters)
        
        def make_test(n=26, shp=(1000,)):
            v = np.random.randint(0, n, shp)
            w = (np.random.randint(0, n-1, shp) + 1 + v) % n
            d = len(shp)
            return letters[:n], letters[np.r_[f'{d},{d+1},0', v, w]]
        
        from timeit import timeit
        
        def test_it(f, args, n=1000, format='{0.__name__:12s}: {1:10.3f} ms'.format):
            res = timeit('f(*args)', globals=dict(f=f, args=args), number=n) * 1000/n
            return res, format(f, res)
        
        for k in [4, 12, 26]:
            T, L = make_test(k)
            print(k)
            for f in [broadcast, searchsorted]:
                t, msg = test_it(f, (L, T))
                print(msg)
        

        【讨论】:

          猜你喜欢
          • 2018-01-15
          • 2020-08-20
          • 2016-01-16
          • 1970-01-01
          • 2017-02-02
          • 1970-01-01
          • 2021-12-22
          • 2020-09-19
          • 1970-01-01
          相关资源
          最近更新 更多