【发布时间】: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?
【问题讨论】:
说我有
q = np.array(['a', 'b'])
terms = np.array(['a', 'b', 'c', 'd'])
如何创建一个 n-hot 向量 v,如 [1, 1, 0, 0],以便出现在 q 中的每个项目在 length = len(terms) 的零向量中将其索引设置为 1?
【问题讨论】:
你可以使用np.isin,把它变成int的数组:
>>> np.isin(terms,q).astype(int)
array([1, 1, 0, 0])
【讨论】:
如果您有 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) 数据的回答。
【讨论】:
这是一种基于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)
【讨论】: