Multiple predicted values with tensorflow Bidirectional LSTM - tensorflow

I want to predict 4 values (4 columns) using tensorflow Bidirectional LSTM. The input shape is (30, 525). Howerver, I obtained a prediction result containing one column (1 value).
Can you help me please?
I used this program:
tf.random.set_seed(1234)
file_training = 'trainingData.csv'
raw_data_training = pd.read_csv(file_training)
df_training = raw_data_training.copy()
df_training.isnull().sum()
file_validation = 'validationData.csv'
raw_data_validation = pd.read_csv(file_validation)
df_validation = raw_data_validation.copy()
df_validation.isnull().sum()
X_train = df_training.drop(['LO','LA','FL','BU'],axis = 1)
y_train = df_training.loc[:,['LO','LA','FL','BU']]
X_test = df_validation.drop(['LO','LA','FL','BU'], axis = 1)
y_test = df_validation.loc[:,['LO','LA','FL','BU']]
scaler_x = MinMaxScaler(feature_range = (0,1))
scaler_y = MinMaxScaler(feature_range = (0,1))
input_scaler = scaler_x.fit(X_train)
output_scaler = scaler_y.fit(y_train)
train_y_norm = output_scaler.transform(y_train)
train_x_norm = input_scaler.transform(X_train)
test_y_norm = output_scaler.transform(y_test)
test_x_norm = input_scaler.transform(X_test)
def create_dataset (X, y, time_steps = 1):
Xs, ys = [], []
for i in range(len(X)-time_steps):
v = X[i:i+time_steps, :]
Xs.append(v)
ys.append(y[i+time_steps])
return np.array(Xs), np.array(ys)
TIME_STEPS = 30
X_test, y_test = create_dataset(test_x_norm, test_y_norm, TIME_STEPS)
X_train, y_train = create_dataset(train_x_norm, train_y_norm, TIME_STEPS)
def create_model_bilstm(units):
model = Sequential()
model.add(Bidirectional(LSTM(units = units, return_sequences=True),
input_shape=(X_train.shape[1], X_train.shape[2])))
model.add(Bidirectional(LSTM(units = units)))
model.add(Dense(1))
model.compile(loss='mse', optimizer='adam')
return model
model_bilstm = create_model_bilstm(64)
def fit_model(model):
early_stop = keras.callbacks.EarlyStopping(monitor = 'val_loss',
patience = 10)
history = model.fit(X_train, y_train, epochs = 100, validation_split = 0.2,
batch_size = 32, shuffle = True, callbacks = [early_stop])
return history
history_bilstm = fit_model(model_bilstm)
y_test = scaler_y.inverse_transform(y_test)
y_train = scaler_y.inverse_transform(y_train)
def prediction(model):
prediction = model.predict(X_test)
prediction = scaler_y.inverse_transform(prediction)# this gives ValueError: non-broadcastable output operand with shape (1081,1) doesn't match the broadcast shape (1081,4)
return prediction
prediction_bilstm = prediction(model_bilstm)```

Related

Keras Model works w/ 3 inputs but not 4

I'm trying to build a VAE for some time series data, but am having a hard time getting the model to work with 4 inputs instead of 3, and I'm not sure what's causing the problem.
Here's the complete code that I have:
# data for each time series
import yfinance as yf
import tensorflow as tf
import numpy as np
from sklearn.preprocessing import StandardScaler
from tensorflow import keras
from tensorflow.keras import layers
# load in the data
msft = yf.Ticker('MSFT').history(period = '5y')[['Close']]
googl = yf.Ticker('GOOGL').history(period = '5y')[['Close']]
amzn = yf.Ticker('AMZN').history(period = '5y')[['Close']]
vals = np.sin(np.linspace(-100, 100, msft.shape[0]))[:, None]
# scale the data for numeric stability
msft = StandardScaler().fit_transform(msft)
googl = StandardScaler().fit_transform(googl)
amzn = StandardScaler().fit_transform(amzn)
# global variables
latent_dim = 2
batch_size = 32
sequence_length = 30
# build time series samplers for each time series
c1 = keras.utils.timeseries_dataset_from_array(
msft,
targets = None,
sequence_length = sequence_length
)
c2 = keras.utils.timeseries_dataset_from_array(
googl,
targets = None,
sequence_length = sequence_length
)
c3 = keras.utils.timeseries_dataset_from_array(
amzn,
targets = None,
sequence_length = sequence_length
)
c4 = keras.utils.timeseries_dataset_from_array(
vals,
targets = None,
sequence_length = sequence_length
)
# add the encoder for the sine wave
sin_inputs = keras.layers.Input(shape=(sequence_length, 1))
# stack two lstm layers
sx = layers.LSTM(64, return_sequences = True)(sin_inputs)
sx = layers.LSTM(64)(sx)
# build the encoders for each of the separate time series
msft_inputs = layers.Input(shape=(sequence_length, 1))
# stack two lstm layers
mx = layers.LSTM(64, return_sequences = True)(msft_inputs)
mx = layers.LSTM(64)(mx)
# now for google
googl_inputs = layers.Input(shape=(sequence_length, 1))
gx = layers.LSTM(64, return_sequences = True)(googl_inputs)
gx = layers.LSTM(64)(gx)
# and for amazon
amzn_inputs = layers.Input(shape = (sequence_length, 1))
ax = layers.LSTM(64, return_sequences = True)(amzn_inputs)
ax = layers.LSTM(64)(ax)
# now combine them together for a single joint time series!
x = layers.Concatenate()([mx, gx, ax, sx])
# pass into a dense layer
x = layers.Dense(64, activation = 'relu')(x)
# and finally pass them into the final decoder!
z_mean = layers.Dense(latent_dim, name = 'z_mean')(x)
z_logvar = layers.Dense(latent_dim, name = 'z_logvar')(x)
encoder = keras.Model([msft_inputs, googl_inputs, amzn_inputs, sin_inputs], [z_mean, z_logvar], name = 'encoder')
class Sampler(layers.Layer):
def call(self, z_mean, z_logvar):
batch_size = tf.shape(z_mean)[0]
n_dims = tf.shape(z_mean)[1]
epsilon = tf.random.normal(shape = (batch_size, n_dims))
return z_mean + tf.exp(0.5 * z_logvar) * epsilon
latent_inputs = keras.Input(shape=(latent_dim,))
dec = layers.RepeatVector(sequence_length)(latent_inputs)
dec = layers.LSTM(64, return_sequences=True)(dec)
out = layers.TimeDistributed(layers.Dense(1))(dec)
decoder = keras.Model(latent_inputs, out)
class VAE(keras.Model):
def __init__(self, encoder, decoder, **kwargs):
super().__init__(**kwargs)
self.encoder = encoder
self.decoder = decoder
self.sampler = Sampler()
self.total_loss_tracker = keras.metrics.Mean(name = 'total_loss')
self.reconstruction_loss_tracker = keras.metrics.Mean(name = 'reconstruction_loss')
self.kl_loss_tracker = keras.metrics.Mean(name = 'kl_loss')
#property
def metrics(self):
return [self.total_loss_tracker,
self.reconstruction_loss_tracker,
self.kl_loss_tracker]
def train_step(self, data):
with tf.GradientTape() as tape:
z_mean, z_logvar = self.encoder(data)
z = self.sampler(z_mean, z_logvar)
reconstruction = decoder(z)
reconstruction_loss = tf.reduce_mean(
tf.reduce_sum(
keras.losses.binary_crossentropy(data, reconstruction),
axis = (1, 2)
)
)
kl_loss = -0.5 * (1 + z_logvar - tf.square(z_mean) - tf.exp(z_logvar))
total_loss = reconstruction_loss + tf.reduce_mean(kl_loss)
grads = tape.gradient(total_loss, self.trainable_weights)
self.optimizer.apply_gradients(zip(grads, self.trainable_weights))
self.total_loss_tracker.update_state(total_loss)
self.reconstruction_loss_tracker.update_state(reconstruction_loss)
self.kl_loss_tracker.update_state(kl_loss)
return {
"total_loss": self.total_loss_tracker.result(),
"reconstruction_loss": self.reconstruction_loss_tracker.result(),
"kl_loss": self.kl_loss_tracker.result(),
}
vae = VAE(encoder, decoder)
vae.compile(optimizer=keras.optimizers.Adam(), run_eagerly=False)
vae.fit(zip(c1.repeat(), c2.repeat(), c3.repeat(), c4.repeat()), epochs = 10, steps_per_epoch = 10)
When I fit this model I get the following error:
ValueError: Data is expected to be in format `x`, `(x,)`, `(x, y)`, or `(x, y, sample_weight)`, found: (<tf.Tensor: shape=(128, 30, 1),
My issue is that this exact same model works when I only have 3 inputs instead of 4.
If I replace the lines where I specify the inputs everything seems to work fine:
x = layers.Concatenate()([mx, gx, sx])
encoder = keras.Model([msft_inputs, googl_inputs, amzn_inputs], [z_mean, z_logvar], name = 'encoder')
vae.fit(zip(c1.repeat(), c2.repeat(), c3.repeat()), epochs = 10, steps_per_epoch = 10)
So I'm curious about what it is about my setup that is causing my model to break when I add the fourth input.

How to build a Siamese Network from Transformer Model? Shape Input Error

I have the following Base Network with some important (error is coming due to these) parameters (please assume every else parameter)
maxlen = 250
model_dense = 256
Base Model :
def build_base_model(inputs):
inputs = layers.Input(shape=(maxlen,),name='base_input')
embedding_layer = TokenAndPositionEmbedding(maxlen, vocab_size, embed_dim)
x = embedding_layer(inputs)
transformer_block = TransformerBlock(embed_dim, num_heads, ff_dim, trans_drop1, trans_drop2, trans_reg1, trans_reg2)
x = transformer_block(x)
x = layers.GlobalAveragePooling1D()(x)
x = layers.Dropout(model_drop1)(x)
outputs = layers.Dense(model_dense)(x)
base_model = keras.Model(inputs=inputs, outputs=outputs)
return base_model
and I my Siamese network as:
base_model = build_base_model()
input_text1 = layers.Input(shape=(maxlen,))
input_text2 = layers.Input(shape=(maxlen,))
emb1 = base_model(input_text1)
emb2 = base_model(input_text2)
distance = layers.Lambda(euclidean_distance)([emb1, emb2])
outputs = layers.Dense(1, activation="sigmoid")(distance)
model = keras.Model(inputs=[emb1, emb2], outputs=outputs)
model.compile(
optimizer="adam", metrics = ["accuracy",], loss= 'binary_crossentropy')
history = model.fit(
train_X, train_y, batch_size=batch_size, epochs = 50, validation_split = 0.15, callbacks = callbacks, verbose = 1,
)
It gives me an error as:
ValueError: Input 0 of layer "model_11" is incompatible with the layer: expected shape=(None, 256), found shape=(None, 250)
What am I doing wrong?
Base Transformer model tutorial taken from this
Siamese Model Structure, cosine distance, make_pairs from this
UPDATE- I have built the new network in a different manner and it is up and running. Can someone please confirms if it is the correct one:
inputs1 = layers.Input(shape=(maxlen,),name='inp_1')
inputs2 = layers.Input(shape=(maxlen,),name='inp_2')
embedding_layer = TokenAndPositionEmbedding(maxlen, vocab_size, embed_dim)
transformer_block = TransformerBlock(embed_dim, num_heads, ff_dim, trans_drop1, trans_drop2, trans_reg1, trans_reg2)
pooling = layers.GlobalAveragePooling1D()
drop_layer = layers.Dropout(model_drop1)
out_dense = layers.Dense(model_dense)
x1 = embedding_layer(inputs1)
x2 = embedding_layer(inputs2)
x1 = transformer_block(x1)
x2 = transformer_block(x2)
x1 = pooling(x1)
x2 = pooling(x2)
x1 = drop_layer(x1)
x2 = drop_layer(x2)
vec_x1 = out_dense(x1)
vec_x2 = out_dense(x2)
distance = layers.Lambda(euclidean_distance)([vec_x1, vec_x2])
outputs = layers.Dense(1, activation="sigmoid")(distance)
model = keras.Model(inputs=[inputs1, inputs2], outputs=outputs)
in the linemodel = keras.Model(inputs=[emb1, emb2], outputs=outputs):
I suspect that you are mean to saymodel = keras.Model(inputs=[input_text1, input_text2], outputs=outputs)

Inputs shape is uknown during training (model subclassing)

Consider following model
class FractalNeuralNetwork(tf.keras.Model):
def __init__(self, class_number):
super(FractalNeuralNetwork, self).__init__()
self.box_counting_patches = [BoxCountingPatch(box_size) for box_size in range(3, 41 + 1, 2)]
self.chebyshev = ChebyshevBinaryPatch()
self.euclidean = EuclideanBinaryPatch()
self.manhattan = ManhattanBinaryPatch()
self.percolation_c = PercolationC()
self.percolation_m = PercolationM()
self.percolation_q = PercolationQ()
self.probability = ProbabilityMatrix()
self.fractal_dimension = FractalDimension()
self.lacunarity = Lacunarity()
self.assemble = AssembleFractalImage()
self.resize = tf.keras.layers.Resizing(width=224, height=224)
self.rescale = tf.keras.layers.Rescaling(scale=1./255)
self.mobilenet_v2 = hub.KerasLayer("https://tfhub.dev/google/tf2-preview/mobilenet_v2/feature_vector/4",
output_shape=[1280],
trainable=False)
self.combine = tf.keras.layers.Add()
self.score = tf.keras.layers.Dense(class_number, activation='softmax')
def call(self, inputs):
inputs = tf.ensure_shape(inputs, self.ensure_input_shape)
box_counting_patches = [box_counting_patch(inputs) for box_counting_patch in self.box_counting_patches]
chebyshev = self.chebyshev(inputs=box_counting_patches)
euclidean = self.euclidean(inputs=box_counting_patches)
manhattan = self.manhattan(inputs=box_counting_patches)
percolation_c = self.percolation_c(inputs=[chebyshev, euclidean, manhattan])
percolation_m = self.percolation_m(inputs=[chebyshev, euclidean, manhattan])
percolation_q = self.percolation_q(inputs=[chebyshev, euclidean, manhattan])
probability = self.probability(inputs=[chebyshev, euclidean, manhattan])
fractal_dimension = self.fractal_dimension(inputs=probability)
lacunarity = self.lacunarity(inputs=probability)
fractal_output = self.assemble(
inputs=[
fractal_dimension,
lacunarity,
percolation_c,
percolation_m,
percolation_q
]
)
fractal_output = self.resize(fractal_output)
fractal_output = self.rescale(fractal_output)
fractal_output = self.mobilenet_v2(fractal_output)
original_output = self.rescale(inputs)
original_output = self.mobilenet_v2(original_output)
combined_output = self.combine([fractal_output, original_output])
output = self.score(combined_output)
return output
Every custom layer here is not trainable, they just perform calculations - extract fractal features from images.
The model is trained with the following code:
model = FractalNeuralNetwork(
class_number=CLASS_NUMBER
)
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
model.fit(
training_set,
validation_data=validation_set,
epochs=1
)
The first batch comes with a normal shape (None, 224, 224, 3) but the second (None, None, None, None) and it break my model. Why does it happen?

Unable to interpret an argument of type tensorflow.python.data.ops.dataset_ops.PrefetchDataset as a TFF value in iterative process

I'm trying to run a classification simulation in tff, but I'm getting this error:
TypeError: Unable to interpret an argument of type tensorflow.python.data.ops.dataset_ops.PrefetchDataset as a TFF value.
Here is the code I'm using
client_lr = 1e-3
server_lr = 1e-1
NUM_ROUNDS = 200
NUM_EPOCHS = 5
BATCH_SIZE = 2048
EPOCHS = 400
TH = 0.5
def base_model():
return Sequential([
Dense(256, activation='relu', input_shape=(x_train.shape[-1],)),
Dropout(0.5),
Dense(256, activation='relu'),
Dropout(0.5),
Dense(256, activation='relu'),
Dropout(0.5),
Dense(1, activation='sigmoid'),
])
client_train_dataset = collections.OrderedDict()
for i in range(1, total_clients+1):
client_name = "client_" + str(i)
start = samples_per_set * (i-1)
end = samples_per_set * i
data = collections.OrderedDict((('y', y_train[start:end]), ('x', x_train[start:end])))
client_train_dataset[client_name] = data
train_dataset = tff.simulation.FromTensorSlicesClientData(client_train_dataset)
sample_dataset = train_dataset.create_tf_dataset_for_client(train_dataset.client_ids[0])
sample_element = next(iter(sample_dataset))
PREFETCH_BUFFER = 10
SHUFFLE_BUFFER = samples_per_set
def preprocess(dataset):
def batch_format_fn(element):
return collections.OrderedDict(
x=element['x'],
y=tf.reshape(element['y'], [-1, 1]))
return dataset.repeat(NUM_EPOCHS).shuffle(SHUFFLE_BUFFER).batch(BATCH_SIZE).map(batch_format_fn).prefetch(PREFETCH_BUFFER)
preprocessed_sample_dataset = preprocess(sample_dataset)
sample_batch = tf.nest.map_structure(lambda x: x.numpy(), next(iter(preprocessed_sample_dataset)))
def make_federated_data(client_data, client_ids):
return [preprocess(client_data.create_tf_dataset_for_client(x)) for x in client_ids]
federated_train_data = make_federated_data(train_dataset, train_dataset.client_ids)
def model_tff():
model = base_model()
return tff.learning.from_keras_model(
model,
input_spec=preprocessed_sample_dataset.element_spec,
loss=tf.keras.losses.BinaryCrossentropy(),
metrics=[
tfa.metrics.F1Score(num_classes=1, threshold=TH),
keras.metrics.Precision(name="precision", thresholds=TH),
keras.metrics.Recall(name="recall", thresholds=TH)
])
iterative_process = tff.learning.build_federated_averaging_process(
model_tff,
client_optimizer_fn=lambda: optimizers.Adam(learning_rate=client_lr),
server_optimizer_fn=lambda: optimizers.SGD(learning_rate=server_lr))
state = iterative_process.initialize()
federated_model = None
for round_num in range(1, NUM_ROUNDS+1):
state, tff_metrics = iterative_process.next(state, federated_train_data) # THE ERROR IS HERE
federated_model = base_model()
federated_model.compile(optimizer=optimizers.Adam(learning_rate=client_lr),
loss=tf.keras.losses.BinaryCrossentropy(),
metrics=[
tfa.metrics.F1Score(num_classes=1, threshold=TH),
keras.metrics.Precision(name="precision", thresholds=TH),
keras.metrics.Recall(name="recall", thresholds=TH)
])
state.model.assign_weights_to(model=federated_model)
federated_result = federated_model.evaluate(x_val, y_val, verbose=1, return_dict=True)
federated_test = federated_model.evaluate(x_test, y_test, verbose=1, return_dict=True)
I'm using this creditcard dataset: https://www.kaggle.com/mlg-ulb/creditcardfraud
The federated_train_data is a list of <PrefetchDataset shapes: OrderedDict([(x, (None, 29)), (y, (None, 1))]), types: OrderedDict([(x, tf.float64), (y, tf.int64)])>, just like the tutorial from the Tensorflow Federated website Federated Learning for Image Classification.
This might be issue#918. Does this only occur when running in Google Colab? What version of TFF is being used?
Commit#4e57386 is believed to have fixed this, which is now part of the tensorflow-federated-nightly pip package.

Tensor flow error in shape input for a simple classifier

I've looked through existing q&a for this type of problem but couldn't quite work it out. When I fit my image classifier model using the VGG model, I get the the following error message:
Error when checking input: expected input_1 to have 4 dimensions, but got array with shape (None, None, 224, 224, 3)
Here's the code I have used so far:
!wget -qq https://www.dropbox.com/s/9gc4fr1uiveedn6/simpsons.zip?dl=0
!unzip -qq simpsons.zip?dl=0
!rm simpsons.zip?dl=0import glob
import pandas as pd
filenames_n0 = glob.glob('./simpsons/homer /*.jpg')
filenames_n1 = glob.glob('./simpsons/marge /*.jpg')
filenames_n2 = glob.glob('./simpsons/bart /*.jpg')
filenames_n3 = glob.glob('./simpsons/lisa /*.jpg')
filenames_n4 = glob.glob('./simpsons/maggie /*.jpg')
names = ['homer', 'marge','bart', 'lisa', 'maggie']
!ls
df = pd.DataFrame(filenames_n0, columns = ["filename"])
df1 = pd.DataFrame(filenames_n1, columns = ["filename"])
df2 = pd.DataFrame(filenames_n2, columns = ["filename"])
df3 = pd.DataFrame(filenames_n3, columns = ["filename"])
df4 = pd.DataFrame(filenames_n4, columns = ["filename"])
df['class'] = pd.Series([0 for x in range(len(df.index))], index=df.index)
df1['class'] = pd.Series([1 for x in range(len(df1.index))], index=df1.index)
df2['class'] = pd.Series([2 for x in range(len(df2.index))], index=df2.index)
df3['class'] = pd.Series([3 for x in range(len(df3.index))], index=df3.index)
df4['class'] = pd.Series([4 for x in range(len(df4.index))], index=df4.index)
train_set_percentage = .9
train_df = df[:int(len(df)*train_set_percentage)]
val_df = df[int(len(df)*train_set_percentage):]
train_df1 = df1[:int(len(df1)*train_set_percentage)]
val_df1 = df1[int(len(df1)*train_set_percentage):]
train_df2 = df2[:int(len(df2)*train_set_percentage)]
val_df2 = df2[int(len(df2)*train_set_percentage):]
train_df3 = df3[:int(len(df3)*train_set_percentage)]
val_df3 = df3[int(len(df3)*train_set_percentage):]
train_df4 = df4[:int(len(df4)*train_set_percentage)]
val_df4 = df4[int(len(df4)*train_set_percentage):]
#concat train & val datasets to form 1 of each.
df_new_train = pd.concat([train_df, train_df1, train_df2, train_df3, train_df4])
df_new_val = pd.concat([val_df, val_df1, val_df2, val_df3, val_df4])
df = df_new_train.sample(frac=1).reset_index(drop=True)
df_val = df_new_val.sample(frac=1).reset_index(drop=True)
train_filenames_list = df["filename"].tolist()
train_labels_list = df['class'].astype('int32').tolist()
val_filenames_list = df_val["filename"].tolist()
val_labels_list = df_val['class'].astype('int32').tolist()
num_classes = 5
train_set_percentage = .9
train_filenames_list = train_filenames_list[:int(len(train_filenames_list)*train_set_percentage)]
train_labels_list = train_labels_list[:int(len(train_labels_list)*train_set_percentage)]
val_filenames_list = val_filenames_list[int(len(val_filenames_list)*train_set_percentage):]
val_labels_list = val_labels_list[int(len(val_labels_list)*train_set_percentage):]
img_rows, img_cols = 299, 299
def _parse_function(filename, label):
image_string = tf.read_file(filename)
image_decoded = tf.image.decode_jpeg(image_string)
image_decoded = tf.image.decode_gif(image_string)
image_resized = tf.image.resize_images(image_decoded, [img_rows, img_cols])
label = tf.one_hot(label, num_classes)
return image_resized, label
filenames = tf.constant(train_filenames_list)
# Labels that match the training files - from a list
labels = tf.constant(train_labels_list)
# Same as above but for validation set
val_filenames = tf.constant(val_filenames_list)
val_labels = tf.constant(val_labels_list)
train_dataset = tf.data.Dataset.from_tensor_slices((filenames, labels))
train_dataset = train_dataset.map(_parse_function)
train_dataset = train_dataset.repeat(100)
train_dataset = train_dataset.batch(10)
valid_dataset = tf.data.Dataset.from_tensor_slices((val_filenames, val_labels))
valid_dataset = valid_dataset.map(_parse_function)
valid_dataset = valid_dataset.repeat(100)
valid_dataset = valid_dataset.batch(10)
base_model = tf.keras.applications.vgg16.VGG16(weights='imagenet', include_top=False, input_shape=(224, 224, 3))
x = base_model.output
x = GlobalAveragePooling2D()(x)
x = Dense(512, activation='relu')(x)
x = Dropout(0.3)(x)
predictions = Dense(2, activation='softmax')(x)
model = Model(inputs=base_model.input, outputs=predictions)
opt = tf.keras.optimizers.Adam(lr=0.001)
model.compile(optimizer=opt, loss='categorical_crossentropy',metrics=['accuracy'])
train_steps = int(372/1) #total trains set / batch_size
val_steps = int(43/1)
epochs = 4
history = model.fit( train_dataset, steps_per_epoch = train_steps,
epochs = epochs,
validation_data = valid_dataset,
validation_steps = val_steps)
Any advice please. I'm new to tf and have looked at changing input shapes. They methods I didnt' work and I'm unsure how to proceed.
First of all please forgive my poor English. I am also new to tensorflow. through checking document, I found tf.image.decode_gif will return a tensor with shape [num_frames, height, width, 3] for GIF images. train_dataset.batch(10) will also add a dimension to [num_frames, height, width, 3], so the shape of input is 5 dimensions. but model only take as input arrays of 4 dimensions.
if your image format is all jpg-type,you can delete
image_decoded = tf.image.decode_gif(image_string)
the below two statement will make the first statement useless,because this two statement has same left side,the latter will override the first
image_decoded = tf.image.decode_jpeg(image_string)
image_decoded = tf.image.decode_gif(image_string)