Без тестирования вещей, вот несколько быстрых решений:
def gen_data(data,p=0, batch_size = BATCH_SIZE, n_session = N_SESSION,
x = np.zeros((batch_size,SEQ_LENGTH,vocab_size))
y = np.zeros(batch_size, dtype=int) # initial to desired type
for n in range(batch_size):
ptr = n
for i in range(SEQ_LENGTH):
x[n,i,char_to_ix[data[p+ptr+i]]] = 1.
if(return_target):
y[n] = char_to_ix[data[p+ptr+SEQ_LENGTH]]
return x, y
# y is already an array; don't need this: np.array(y,dtype='int32')
nest = [gen_data(datum) for datum in data]
производит, я думаю,
[(x0,y0), (x1,y1),...]
где x
является 3d (п, т, у), и y
является 1d (n)
x = np.concatenate([n[0] for n in nest])
(Мне нравится этот формат для сопоставления). По сравнению со всеми операциями по составлению списка, concatenate
относительно дешево. Посмотрите на кишки np.vstack
и т. Д., Чтобы увидеть, как они используют понимание вместе с конкатенацией.
Небольшой пример:
In [515]: def gen():
return np.arange(8).reshape(2,4),np.arange(1,3)
.....:
In [516]: gen()
Out[516]:
(array([[0, 1, 2, 3],
[4, 5, 6, 7]]), array([1, 2]))
In [517]: nest=[gen() for _ in range(3)]
In [518]: nest
Out[518]:
[(array([[0, 1, 2, 3],
[4, 5, 6, 7]]), array([1, 2])),
(array([[0, 1, 2, 3],
[4, 5, 6, 7]]), array([1, 2])),
(array([[0, 1, 2, 3],
[4, 5, 6, 7]]), array([1, 2]))]
In [519]: np.concatenate([x[0] for x in nest])
Out[519]:
array([[0, 1, 2, 3],
[4, 5, 6, 7],
[0, 1, 2, 3],
[4, 5, 6, 7],
[0, 1, 2, 3],
[4, 5, 6, 7]])
In [520]: np.concatenate([x[1] for x in nest])
Out[520]: array([1, 2, 1, 2, 1, 2])
zip*
эффективно делает 'tanspose' на вложенном списке, поэтому массивы могут быть построены с:
In [532]: nest1=zip(*nest)
In [533]: np.concatenate(nest1[0])
Out[533]:
array([[0, 1, 2, 3],
[4, 5, 6, 7],
[0, 1, 2, 3],
[4, 5, 6, 7],
[0, 1, 2, 3],
[4, 5, 6, 7]])
In [534]: np.concatenate(nest1[1])
Out[534]: array([1, 2, 1, 2, 1, 2])
Тем не менее требует Сцепляет.
Поскольку nest
список кортежей, он может служить в качестве входных данных для структурированного массива:
In [524]: arr=np.array(nest,dtype=[('x','(2,4)int'),('y','(2,)int')])
In [525]: arr['x']
Out[525]:
array([[[0, 1, 2, 3],
[4, 5, 6, 7]],
[[0, 1, 2, 3],
[4, 5, 6, 7]],
[[0, 1, 2, 3],
[4, 5, 6, 7]]])
In [526]: arr['y']
Out[526]:
array([[1, 2],
[1, 2],
[1, 2]])
Другая возможность заключается в начальной x
и y
и итерацию. Но вы уже делаете это в gen_data
. Единственное, что нового, это то, что я буду назначать большие блоки.
x = ...
y = ...
for i in range(...):
x[i,...], y[i] = gen(data[i])
Мне больше нравятся осмысленные решения, но я не буду спекулировать на скорости.
С точки зрения скорости, я думаю, что это итерация низкого уровня в gen_data
, которая является потребителем времени. Конкатенирование больших блоков относительно быстро.
Еще одна идея - так как вы итерацию над рядами решеток в gen_data
, как о переходе взгляды на эту функцию, и перебирать их.
def gen_data(data,x=None,y=None):
# accept array or make own
if x is None:
x = np.zeros((3,4),int)
if y is None:
y = np.zeros(3,int)
for n in range(3):
x[n,...] = np.arange(4)+n
y[n] = n
return x,y
без каких-либо ресурсов, создавать массивы, как и раньше:
In [543]: gen_data(None)
Out[543]:
(array([[0, 1, 2, 3],
[1, 2, 3, 4],
[2, 3, 4, 5]]),
array([0, 1, 2]))
или парафировать пару, и перебирать просмотров:
In [544]: x,y = np.zeros((9,4),int),np.zeros(9,int)
In [546]: for i in range(0,9,3):
.....: gen_data(None,x[i:i+3,...],y[i:i+3])
In [547]: x
Out[547]:
array([[0, 1, 2, 3],
[1, 2, 3, 4],
[2, 3, 4, 5],
[0, 1, 2, 3],
[1, 2, 3, 4],
[2, 3, 4, 5],
[0, 1, 2, 3],
[1, 2, 3, 4],
[2, 3, 4, 5]])
In [548]: y
Out[548]: array([0, 1, 2, 0, 1, 2, 0, 1, 2])
ли вы имеете в виду что-то вроде 'х, у = почтовый индекс (* гнездо) '? –
Чтобы уточнить, целью было бы удалить необходимость в zip/concat/splat/list comp в целом. Чтобы иметь возможность инициализировать тензор x до правильных размеров, а затем перебирать каждую точку привязки/SEQ_LENGTH, batch_size за один проход. – user2726995
Вы можете передавать представления глобальных массивов в 'gen_data'. – hpaulj