我正在尝试使用numpy优化内置的函数来生成温度计编码。温度计编码基本上是在给定长度的情况下产生n个量。例如,在8长度内,3将编码为:
1 1 1 0 0 0 0 0使用numpy来生成基于整数输入的向量基本上是切片和设置1。
stream[:num_ones] = 1因此,我的问题是给出一个向量作为输入,例如,生成矩阵输出的最佳方法是什么:
[2 3 4 1]作为投入,应产生:
[[1 1 0 0 0 0 0 0],
[1 1 1 0 0 0 0 0],
[1 1 1 1 0 0 0 0],
[1 0 0 0 0 0 0 0]]我的当前解决方案是迭代所需大小的零矩阵,并使用我前面编写的切片方法将所需的元素数设置为1。我有更快的办法吗?
发布于 2018-03-03 05:49:40
我以前从未听说过“温度计编码”,但当你意识到它与一种热编码是如此相似时,你就可以使用位移位操作( bit shift Ops)实现它了:
>>> a = np.array([2, 3, 4, 1], dtype=np.uint8)
>>> print(np.fliplr(np.unpackbits((1 << a) - 1).reshape(-1,8)))
[[1 1 0 0 0 0 0 0]
[1 1 1 0 0 0 0 0]
[1 1 1 1 0 0 0 0]
[1 0 0 0 0 0 0 0]]编辑:通过在8列块中工作,您可以将这种想法推广到任意大小的整数:
a = np.array([2, 13, 4, 0, 1, 17], dtype=np.uint8)
out = np.empty((len(a), 0), dtype=np.uint8)
while a.any():
block = np.fliplr(np.unpackbits((1 << a) - 1).reshape(-1,8))
out = np.concatenate([out, block], axis=1)
a = np.where(a<8, 0, a-8)
print(out)
[[1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0]
[1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0]]发布于 2018-03-03 06:58:00
In [22]: x = [2, 3, 4, 1, 0, 8]
In [23]: length = 8
In [24]: (np.arange(length) < np.array(x).reshape(-1, 1)).astype(int)
Out[24]:
array([[1, 1, 0, 0, 0, 0, 0, 0],
[1, 1, 1, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 0, 0, 0, 0],
[1, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 1, 1, 1]])或者,创建一个不同长度的“条形图”数组:
In [46]: k = np.arange(length + 1)
In [47]: bars = (k[:-1] < k.reshape(-1, 1)).astype(int)
In [48]: bars
Out[48]:
array([[0, 0, 0, 0, 0, 0, 0, 0],
[1, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 0, 0, 0, 0, 0, 0],
[1, 1, 1, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 0, 0, 0],
[1, 1, 1, 1, 1, 1, 0, 0],
[1, 1, 1, 1, 1, 1, 1, 0],
[1, 1, 1, 1, 1, 1, 1, 1]])并将其用作查找表:
In [49]: bars[x]
Out[49]:
array([[1, 1, 0, 0, 0, 0, 0, 0],
[1, 1, 1, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 0, 0, 0, 0],
[1, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 1, 1, 1]])在上面的代码中,预先分配的数组bars具有形状(length+1, length)。可以使用以下方法创建更高内存效率的bars表示:
In [61]: from numpy.lib.stride_tricks import as_strided
In [62]: u = np.zeros(2*length, dtype=int)
In [63]: u[length:] = 1
In [64]: bars = as_strided(u[length-1:], shape=(length+1, length), strides=(u.strides[0], -u.strides[0]))
In [65]: bars
Out[65]:
array([[0, 0, 0, 0, 0, 0, 0, 0],
[1, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 0, 0, 0, 0, 0, 0],
[1, 1, 1, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 0, 0, 0],
[1, 1, 1, 1, 1, 1, 0, 0],
[1, 1, 1, 1, 1, 1, 1, 0],
[1, 1, 1, 1, 1, 1, 1, 1]])然后bars是一维数组u的视图,它只使用2*length整数.
发布于 2018-03-03 06:46:00
Wim的回答令人难以置信。我也从来没有听说过温度计编码,但如果我要这样做,我将与地图。如果没有for循环解,它就会更短。表演非常相似。
>>> def setValue(val):
return np.append(np.ones(val), np.zeros(8-val))
>>> np.array(list(map(setValue, [2,3,4,5])))
array([[ 1., 1., 0., 0., 0., 0., 0., 0.],
[ 1., 1., 1., 0., 0., 0., 0., 0.],
[ 1., 1., 1., 1., 0., 0., 0., 0.],
[ 1., 1., 1., 1., 1., 0., 0., 0.]])或具有lambda函数的一行
>>> np.array(list(map(lambda v: np.append(np.ones(v), np.zeros(8-v)), [1,6,3,8])))
array([[ 1., 0., 0., 0., 0., 0., 0., 0.],
[ 1., 1., 1., 1., 1., 1., 0., 0.],
[ 1., 1., 1., 0., 0., 0., 0., 0.],
[ 1., 1., 1., 1., 1., 1., 1., 1.]])https://stackoverflow.com/questions/49080613
复制相似问题