#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)
Как вы можете видеть, пакеты «скользят» в том смысле, что они перекрываются.