I'm working on a project to implement an FGSM (Fast Gradient Sign Method) attack on an LSTM model for stock price prediction using TensorFlow and Keras. Despite my efforts, I'm encountering persistent issues with tensor shape mismatches, and I'm hoping to get some advice from this community.
I’ve created an LSTM model to predict stock prices and tried generating adversarial examples using the FGSM method. The training seems to proceed without issues, but when I attempt to generate adversarial examples and evaluate the model with this data, I encounter the following error: Exception encountered when calling Sequential.call(). Cannot take the length of shape with unknown rank.
Arguments received by Sequential.call():
• inputs=tf.Tensor(shape=
ValueError: Exception encountered when calling Sequential.call().
Here’s a summary of the relevant sections of my code:
import numpy as np
import pandas as pd
import os
import tensorflow as tf
from keras.models import load_model
from sklearn.preprocessing import MinMaxScaler
from keras.models import Sequential
from keras.layers import Dense, LSTM, Dropout, Input
def fgsm(input_data, model, loss, epsilon=0.01):
"""
Generate adversarial examples using FGSM.
:param input_data: Input data to be perturbed
:param model: Trained model
:param epsilon: Perturbation size
"""
input_data = tf.convert_to_tensor(input_data, dtype=tf.float32)
loss = tf.convert_to_tensor(loss, dtype=tf.float32)
with tf.GradientTape() as tape:
tape.watch(input_data)
prediction = model(input_data)
loss = tf.keras.losses.MeanSquaredError()(loss, prediction)
gradient = tape.gradient(loss, input_data)
adversarial_example = input_data + epsilon * tf.sign(gradient)
return adversarial_example.numpy()
## Read each stock datasets as dataframe ##
rootpath = os.path.dirname(__file__)
print (rootpath)
folderpath = os.path.join(rootpath, './Stocks')
for file_name in os.listdir(folderpath):
if file_name.endswith('.csv'):
df = pd.read_csv(os.path.join(folderpath,file_name),delimiter=',',usecols=['Date','Open','High','Low','Close','Adj Close','Volume'])
basename, ext = os.path.splitext(file_name)
df['Date'] = pd.to_datetime(df['Date']) ## Convert 'Date' column to datetime format
print ('file:', file_name)
data = df.filter(['Close'])
# Convert the dataframe to a numpy array
dataset = data.values
# Get the number of rows to train the model on
training_data_len = int(np.ceil(len(dataset)* 0.8))
scaler = MinMaxScaler(feature_range=(0,1))
scale_data = scaler.fit_transform(dataset)
## Create the scaled training data set ##
train_data = scale_data[0:int(training_data_len), :]
## Split the data into train data and test data sets ##
x_train = []
y_train = []
for i in range(50, len(train_data)):
x_train.append(train_data[i-50:i, 0])
y_train.append(train_data[i,0])
if i < 50:
print(x_train)
print(y_train)
print()
## Convert the x_data and y_data to numpy arrays ##
x_train, y_train = np.array(x_train), np.array(y_train)
## Reshape the data
x_train = np.reshape(x_train, (x_train.shape[0], x_train.shape[1], 1))
y_train = np.reshape(y_train, (y_train.shape[0], 1))
## Build the LSTM model ##
model = Sequential()
#model.add(LSTM(128, return_sequences=True, input_shape=(x_train.shape[1],1)))
model.add(Input(shape=(x_train.shape[1], 1)))
model.add(LSTM(128, return_sequences=True))
model.add(LSTM(64, return_sequences=False))
model.add(Dropout(0.2))
model.add(Dense(25))
model.add(Dense(1))
## Compile the model ##
model.compile(optimizer='adam', loss='mean_squared_error')
## Train the model ##
model.fit(x_train, y_train, batch_size=32, epochs=1,validation_split=0.2)
## Create the testing dataset ##
test_data = scale_data[training_data_len - 50: , :]
## Create the datasets x_test
x_test = []
y_test = dataset[training_data_len: , :]
for i in range (50, len(test_data)):
x_test.append(test_data[i-50:i, 0])
x_test = np.array(x_test)
y_test = np.array(y_test)
## Reshape the data ##
x_test = np.reshape(x_test, (x_test.shape[0], x_test.shape[1],1))
y_test = np.reshape(y_test, (y_test.shape[0], 1))
## Generate adversarial examples for the training data ##
adversarial_train_data = fgsm(x_train, model, y_train, epsilon=0.01)
#Generate adversarial examples for the test data
adversarial_test_data = fgsm(x_test, model, y_test, epsilon=0.01)
# Ensure that the adversarial data has the correct shape
adversarial_train_data = np.reshape(adversarial_train_data, (adversarial_train_data.shape[0], adversarial_train_data.shape[1], 1))
adversarial_test_data = np.reshape(adversarial_test_data, (adversarial_test_data.shape[0], adversarial_test_data.shape[1], 1))
## Save adversarial examples to CSV files
adversarial_train_data = pd.DataFrame(adversarial_train_data.reshape(adversarial_train_data.shape[0], -1))
adversarial_train_data.to_csv('adversarial_train_data.csv', index=False)
## Evaluate the model with adversarial training data
train_predictions = model.predict(adversarial_train_data)
train_rmse = np.sqrt(np.mean((train_predictions - y_train) ** 2))
print (f'Training RMSE with adversarial examples: {train_rmse}')
## Evaluate the model with adversarial test data
test_predictions = model.predict(adversarial_test_data)
test_rmse = np.sqrt(np.mean((test_predictions - y_test) ** 2))
print (f'Test RMSE with adversarial examples: {test_rmse}')
How to properly handle tensor shapes in TensorFlow/Keras to avoid shape mismatch errors. Any insights into why the Sequential.call() method might be encountering an unknown rank shape error.
Any help or pointers would be greatly appreciated. Thank you in advance!
Comment From: mehtamansi29
Hi @Headshake -
Can you provide dummy data dataset to reproduce the issue ?
Comment From: Headshake
Here is the testing dataset: Stocks.zip
Comment From: mehtamansi29
Hi @Headshake -
Here in your code Generate adversarial examples train data and test data are correct. So no need to correct shape of adversarial generated data. Removing this two line from the code will remove error and will Evaluate the model with adversarial train and test data.
adversarial_train_data = np.reshape(adversarial_train_data, (adversarial_train_data.shape[0], adversarial_train_data.shape[1], 1))
adversarial_test_data = np.reshape(adversarial_test_data, (adversarial_test_data.shape[0], adversarial_test_data.shape[1], 1))
Attached gist for the reference as well. Thanks..!!
Comment From: Headshake
Hi @mehtamansi29,
Thanks for your response. I've tried the suggested solution, but I still get the same error message.
Comment From: mehtamansi29
Hi @Headshake -
Which keras version are you using ?
Comment From: Headshake
I'm using Keras 3.3.3
Comment From: mehtamansi29
Can you try to upgrade keras with latest version using pip install --upgrade keras
and try to run code with my suggestion?
Comment From: Headshake
Update: I upgraded the keras model to 3.4.1, it's the same issue when I re-run the code.
Comment From: ghsanti
Are pandas dataframes accepted as inputs?
The error happens in predict where you feed a dataframe instead of a numpy array.
Comment From: Headshake
Yes, I read inputs as dataframes and convert them to numpy array before passing them to the function using these lines: x_train, y_train = np.array(x_train), np.array(y_train)
x_test = np.array(x_test) y_test = np.array(y_test)
Comment From: mehtamansi29
Hi @Headshake -
This code will work successful on evaluating the model with adversarial training and testing data with keras(3.4.1) and tensorflow(2.17.0).
import numpy as np
import pandas as pd
import os
import tensorflow as tf
print(tf.__version__)
import keras
print(keras.__version__)
from keras.models import load_model
from sklearn.preprocessing import MinMaxScaler
from keras.models import Sequential
from keras.layers import Dense, LSTM, Dropout, Input
def fgsm(input_data, model, loss, epsilon=0.01):
"""
Generate adversarial examples using FGSM.
:param input_data: Input data to be perturbed
:param model: Trained model
:param epsilon: Perturbation size
"""
input_data = tf.convert_to_tensor(input_data, dtype=tf.float32)
loss = tf.convert_to_tensor(loss, dtype=tf.float32)
with tf.GradientTape() as tape:
tape.watch(input_data)
prediction = model(input_data)
loss = tf.keras.losses.MeanSquaredError()(loss, prediction)
gradient = tape.gradient(loss, input_data)
adversarial_example = input_data + epsilon * tf.sign(gradient)
return adversarial_example.numpy()
df = pd.read_csv('/content/AAPL.csv')
df['Date'] = pd.to_datetime(df['Date']) ## Convert 'Date' column to datetime format
data = df.filter(['Close'])
# Convert the dataframe to a numpy array
dataset = data.values
# Get the number of rows to train the model on
training_data_len = int(np.ceil(len(dataset)* 0.8))
scaler = MinMaxScaler(feature_range=(0,1))
scale_data = scaler.fit_transform(dataset)
## Create the scaled training data set ##
train_data = scale_data[0:int(training_data_len), :]
## Split the data into train data and test data sets ##
x_train = []
y_train = []
for i in range(50, len(train_data)):
x_train.append(train_data[i-50:i, 0])
y_train.append(train_data[i,0])
if i < 50:
print(x_train)
print(y_train)
print()
## Convert the x_data and y_data to numpy arrays ##
x_train, y_train = np.array(x_train), np.array(y_train)
## Reshape the data
x_train = np.reshape(x_train, (x_train.shape[0], x_train.shape[1], 1))
y_train = np.reshape(y_train, (y_train.shape[0], 1))
## Build the LSTM model ##
model = Sequential()
#model.add(LSTM(128, return_sequences=True, input_shape=(x_train.shape[1],1)))
model.add(Input(shape=(x_train.shape[1], 1)))
model.add(LSTM(128, return_sequences=True))
model.add(LSTM(64, return_sequences=False))
model.add(Dropout(0.2))
model.add(Dense(25))
model.add(Dense(1))
## Compile the model ##
model.compile(optimizer='adam', loss='mean_squared_error')
## Train the model ##
print(f'Training Model...')
model.fit(x_train, y_train, batch_size=32, epochs=1,validation_split=0.2)
## Create the testing dataset ##
test_data = scale_data[training_data_len - 50: , :]
## Create the datasets x_test
x_test = []
y_test = dataset[training_data_len: , :]
for i in range (50, len(test_data)):
x_test.append(test_data[i-50:i, 0])
x_test = np.array(x_test)
y_test = np.array(y_test)
## Reshape the data ##
x_test = np.reshape(x_test, (x_test.shape[0], x_test.shape[1],1))
y_test = np.reshape(y_test, (y_test.shape[0], 1))
## Generate adversarial examples for the training data ##
adversarial_train_data = fgsm(x_train, model, y_train, epsilon=0.01)
#Generate adversarial examples for the test data
adversarial_test_data = fgsm(x_test, model, y_test, epsilon=0.01)
print(adversarial_train_data.shape)
print(adversarial_test_data.shape)
## Evaluate the model with adversarial training data
print(f'Evaluate the model with adversarial training data...')
train_predictions = model.predict(adversarial_train_data)
train_rmse = np.sqrt(np.mean((train_predictions - y_train) ** 2))
print (f'Training RMSE with adversarial examples: {train_rmse}')
## Evaluate the model with adversarial test data
print(f'Evaluate the model with adversarial test data...')
test_predictions = model.predict(adversarial_test_data)
test_rmse = np.sqrt(np.mean((test_predictions - y_test) ** 2))
print (f'Test RMSE with adversarial examples: {test_rmse}')
Comment From: Headshake
Yes, I can run the code above successfully, but only when the codes below are removed. In order to write the adversarial data into the file, I need to reshape the data.
adversarial_train_data = pd.DataFrame(adversarial_train_data.reshape(adversarial_train_data.shape[0], -1))
adversarial_train_data.to_csv('adversarial_train_data.csv', index=False)
Comment From: sonali-kumari1
Hi @Headshake -
Could you please confirm if this issue is resolved for you ? Please feel free to close the issue if it is resolved!
Comment From: github-actions[bot]
This issue is stale because it has been open for 14 days with no activity. It will be closed if no further activity occurs. Thank you.
Comment From: github-actions[bot]
This issue was closed because it has been inactive for 28 days. Please reopen if you'd like to work on this further.
Comment From: google-ml-butler[bot]