Создание n-hot вектора в numpy - PullRequest
0 голосов
/ 12 октября 2018

Скажите, у меня есть

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

Как я могу создать n-горячий вектор v, как [1, 1, 0, 0], чтобы каждый элемент, который появляется в q, имел свой индекс, установленный на 1 в нуле-вектор length = len(terms)?

Ответы [ 3 ]

0 голосов
/ 12 октября 2018

Если у вас есть панда, вы можете использовать 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) данных.

0 голосов
/ 13 октября 2018

Вот метод, основанный на 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)
0 голосов
/ 12 октября 2018

Вы можете использовать np.isin и превратить его в массив int:

>>> np.isin(terms,q).astype(int)
array([1, 1, 0, 0])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...