Скользящий классификатор тензорного потока по большим входным данным

#python #keras #time-series #tensorflow2.0

#python #keras #временные ряды #tensorflow2.0

Вопрос:

У меня есть классификатор (реализованный в tensorflow 2.2) с небольшим вводом векторов с плавающей запятой (None, 500,1) и одним горячим выводом (None, 100). Я хочу обучить ту же архитектуру при «скольжении» по большему вектору: входные данные должны быть (None, 5000), а выходные данные будут результатом его результатов по большому вектору: (None, 10,100), которые будут агрегированы с некоторой функцией, такой как average, чтобы получить единицугорячий результат (нет, 100). Я хочу реализовать это внутри модели, не разделяя векторы данных на несколько частей.

#Упрощенная рабочая модель с малым вводом:

 from tensorflow.keras.layers import Input,Conv1D,LSTM,Dense,Flatten
from tensorflow.keras import Model
import tensorflow as tf
import numpy as np

input_vector_length=500
output_size=100
filters, units,kernel_size=4,4,4

small_inp = Input((input_vector_length, 1))
x = Conv1D(filters, kernel_size=kernel_size, activation='relu')(small_inp)
x = LSTM(units, return_sequences=True)(x)
x = Flatten()(x)
preds= Dense(output_size, activation='softmax')(x)
model = Model(inputs=small_inp, outputs=preds)
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy']) 
  

#Генерация данных и обучение:

 X=np.random.normal(size=(200,500,1))
labels=np.random.randint(0,100,(200,))
y=np.eye(100)[labels]
model.fit(X,y,epochs=5)
  

Ответ №1:

Вы можете использовать Lambda комбинированный с Concatenate , идея состоит в том, чтобы разделить входной тензор на Lambda и объединить выходные данные с Concatenate в конце. Вот рабочий пример

 from tensorflow.keras.layers import Input,Conv1D,LSTM,Dense,Flatten
from tensorflow.keras import Model
import tensorflow as tf
import numpy as np

# the additional modules you need to import
from tensorflow.keras.layers import Lambda,Concatenate
from tensorflow.keras import Sequential


filters,units,kernel_size = 4,4,4

# create a smaller example dataset
input_vector_length = 10
output_size = 4
num_samples = 5

X = np.ones((1,input_vector_length*num_samples,1))
labels = np.random.randint(0,output_size,(num_samples,))
y = np.eye(output_size)[labels]
y = np.concatenate(y,axis=0)[None,:]

# get the slices of the input layer
start_inds = range(input_vector_length*num_samples input_vector_length)[::input_vector_length]
start_pairs = [[start_inds[ind],start_inds[ind 1]] for ind in range(len(start_inds)-1)]

conv_layer = Conv1D(filters,kernel_size=kernel_size,activation='relu')
lstm_layer = LSTM(units,return_sequences=True)
flatten_layer = Flatten()
dense_layer = Dense(output_size,activation='softmax')
block_op = Sequential([conv_layer,lstm_layer,flatten_layer,dense_layer])
# create slices of the input layer, return a list of input Tensors
slice_input = Lambda(lambda x: [x[:,inds[0]:inds[1]] for inds in start_pairs])
concat_layer = Concatenate(axis=1)

small_inp = Input(shape=(input_vector_length*num_samples,1),batch_size=1)
preds = concat_layer([block_op(x_slice) for x_slice in slice_input(small_inp)])
model = Model(inputs=small_inp,outputs=preds)
model.compile(optimizer='adam',loss='categorical_crossentropy',metrics=['accuracy'])
model.fit(X,y,epochs=5)

pred = model.predict(X)
  

Комментарии:

1. зависит ли нарезка входного вектора от размера пакета X, равного 1, или вы написали это, чтобы быстрее завершить выполнение кода?

2. @Tolik нарезка входных векторов основана как на input_vector_length , num_samples так и на том, что вы хотите передать все примеры сразу. Я не знаю, будет ли подача всех входных данных сразу, а затем их нарезка с помощью Lambda , быстрее, чем dataloader, вам нужно протестировать его на своем наборе данных.

Ответ №2:

Вы можете использовать tf.data.Dataset.window для этого.

 import tensorflow as tf

x = tf.reshape(tf.range(1, 1000   1), (-1, 1))
y = tf.random.uniform((1000, 1), minval=0, maxval=2, dtype=tf.int32)

ds = tf.data.Dataset.from_tensor_slices((x, y))
ds = ds.window(size=10, shift=1, stride=1)
ds = ds.flat_map(lambda x, y: tf.data.Dataset.zip((x, y)).take(4).batch(4))

for batch in ds.take(10):
    print(batch[0])
  
 tf.Tensor(
[[1], [2], [3], [4]], shape=(4, 1), dtype=int32)
tf.Tensor(
[[2], [3], [4], [5]], shape=(4, 1), dtype=int32)
tf.Tensor(
[[3], [4], [5], [6]], shape=(4, 1), dtype=int32)
tf.Tensor(
[[4], [5], [6], [7]], shape=(4, 1), dtype=int32)
tf.Tensor(
[[5], [6], [7], [8]], shape=(4, 1), dtype=int32)
tf.Tensor(
[[6], [7], [8], [9]], shape=(4, 1), dtype=int32)
tf.Tensor(
[[7], [8], [9], [10]], shape=(4, 1), dtype=int32)
  

Как вы можете видеть, пакеты «скользят» в том смысле, что они перекрываются.