I am developing a neural network that use image data and a matrix of additional data (all floats) to predict a continuous value. I am new to tensorflow, so I was following a tutorial to learn how to alter my neural network to take both image and float data as input I am having an issue with the code from the tutorial. The main error at the end of the stack trace is as follows:
ValueError: Exception encountered when calling layer "lambda" (type Lambda).
Dimensions must be equal, but are 1 and 3 for '{{node lambda/BiasAdd}} = BiasAdd[T=DT_FLOAT, data_format="NHWC"](lambda/strided_slice, lambda/Const)' with input shapes: [?,999,999,1], [3].
Call arguments received by layer "lambda" (type Lambda):
• inputs=tf.Tensor(shape=(None, 999, 999, 1), dtype=float32)
• mask=None
• training=None
My questions are: How do I solve this error? Is this the proper way to build a neural network with mixed input data? If not, could you please give an example of what the architecture should look like? (with VGGnet-16 architecture for image input ONLY)
The relevant code is as follows. Images are .TIF files.
def get_data(path):
df = pd.read_csv(path)
df['cn2_scaled'] = scale_cn2(df['bls_cn2'])
print('df.head(): ', df.head())
img_shape = get_img_shape(df['img_path'].iloc[0])
print('img_shape: ', img_shape)
return df
def scale_cn2(cn2_arr):
scaled_cn2_arr = []
for cn2 in cn2_arr:
cn2_scaled = ((-1*np.log10(cn2))-12)/5
scaled_cn2_arr.append(cn2_scaled)
return scaled_cn2_arr
def reverse_cn2_scaling(cn2_arr):
reverse_scaled_cn2_arr = []
for cn2 in cn2_arr:
reverse_scaled = 10**(-1*((cn2*5)+12))
reverse_scaled_cn2_arr.append(reverse_scaled)
return reverse_scaled_cn2_arr
def get_img_shape(img_path):
img = Image.open(img_path)
img_arr = np.array(img).astype('float32')
img_shape = img_arr.shape
return img_shape
def accuracy(y_true, y_pred):
y_true = np.log(y_true)
y_pred = np.log(y_pred)
return np.abs((y_pred - y_true)/y_true)
def split_data(df):
# remove unused data cols
df.drop(['timestamp', 'bls_cn2', 'day', 'hour', 'minute', 'min_hour'], inplace=True, axis=1)
print('df.head(): ', df.head())
# shuffle df then split into training, test, validation sets
shuffled_df = df.sample(frac=1) # shuffle
first_80_percent = int(len(df)*0.8)
next_10_percent = first_80_percent + int(len(df)*0.1)
df_train = shuffled_df[:first_80_percent]
df_test = shuffled_df[first_80_percent:next_10_percent]
df_val = shuffled_df[next_10_percent:]
return df_train, df_test, df_val
def get_X_y_from_df(df):
# separate dataframe into X data, picture data, y data
X_pic = []
for img in df['img_path']:
im = load_img(img, target_size=(999, 999), color_mode='grayscale')
im = img_to_array(im)*(1./255)
#im = np.reshape(-1, 999, 999, 1) # not working
X_pic.append(im)
X_stats = []
for i in range(0, len(df['day_sin'])):
stats_1 = df['day_sin'].iloc[i]
stats_2 = df['hour_sin'].iloc[i]
stats_3 = df['Barometric Pressure (mbar)'].iloc[i]
stats_4 = df['Air Temperature (C)'].iloc[i]
stats_5 = df['Relative Humidity (%)'].iloc[i]
stats_6 = df['Shortwave Downwelling Radiation (W/m^2)'].iloc[i]
stats_7 = df['Soil Temperature (C)'].iloc[i]
stats_8 = df['Wind Speed (m/s)'].iloc[i]
X_stats.append([stats_1, stats_2, stats_3, stats_4, stats_5, stats_6, stats_7, stats_8])
y = []
for i in range(0, len(df['cn2_scaled'])):
y_val = df['cn2_scaled'].iloc[i]
y.append(y_val)
X_pic, X_stats = np.array(X_pic), np.array(X_stats)
y = np.array(y)
return (X_pic, X_stats), y
def initiate_get_X_y(df_train, df_val, df_test):
(X_train_pic, X_train_stats), y_train = get_X_y_from_df(df_train)
(X_val_pic, X_val_stats), y_val = get_X_y_from_df(df_val)
(X_test_pic, X_test_stats), y_test = get_X_y_from_df(df_test)
return (X_train_pic, X_train_stats), y_train, (X_val_pic, X_val_stats), y_val, (X_test_pic, X_test_stats), y_test
def create_model():
# define picture (CNN) stream
### change shape of inputs (to what??) ###
input_pic = layers.Input(shape=(999, 999, 1)) # input (define shape)
f = tf.reshape(input_pic, (-1, 999, 999, 1))
print('shape: ', f.shape)
x = layers.Lambda(preprocess_input)(f) # do preprocessing
x = VGG16(input_shape=(999, 999, 1), include_top=False)(x)
x = layers.GlobalAveragePooling2D()(x)
x = layers.Dense(10, activation='relu')(x)
x = Model(inputs=input_pic, outputs=x)
# define stats (Feed-Forward) stream
# shape: # of features/cols in stats dataframe
input_stats = layers.Input(shape=(8,))
y = layers.Dense(32, activation='relu')(input_stats)
y = layers.Dense(10, activation='relu')(y)
y = Model(inputs=input_stats, outputs=y)
# concatinate two layers together
combined = layers.concatenate([x.output, y.output])
z = layers.Dense(4, activation='relu')(combined)
z = layers.Dense(1, activation='linear')(z) # regression: output 1 node
model = Model(inputs=[x.input, y.input], outputs=z)
print(model.summary())
return model
def train_model(model_save_path, model, X_train_pic, X_train_stats, y_train, X_val_pic, X_val_stats, y_val):
optimizer = Adam(learning_rate=0.001)
model.compile(loss='mse', optimizer=optimizer, metrics=['mean_absolute_error'])
cp = ModelCheckpoint(model_save_path, save_best_only=True)
model.fit(x=[X_train_pic, X_train_stats], y=y_train,
validation_data=([X_val_pic, X_val_stats], y_val),
epochs=15, callbacks=[cp])
return model
The full stack trace is as follows:
Traceback (most recent call last):
File "C:\Users\WPRG\Desktop\AI_ML_files\cnn_working.py", line 246, in <module>
model = create_model()
File "C:\Users\WPRG\Desktop\AI_ML_files\cnn_working.py", line 134, in create_model
x = layers.Lambda(preprocess_input)(f) # do preprocessing
File "C:\Users\WPRG\anaconda3\envs\AI_ML\lib\site-packages\keras\utils\traceback_utils.py", line 70, in error_handler
raise e.with_traceback(filtered_tb) from None
File "C:\Users\WPRG\anaconda3\envs\AI_ML\lib\site-packages\keras\backend.py", line 6751, in bias_add
return tf.nn.bias_add(x, bias, data_format="NHWC")
ValueError: Exception encountered when calling layer "lambda" (type Lambda).
Dimensions must be equal, but are 1 and 3 for '{{node lambda/BiasAdd}} = BiasAdd[T=DT_FLOAT, data_format="NHWC"](lambda/strided_slice, lambda/Const)' with input shapes: [?,999,999,1], [3].
Call arguments received by layer "lambda" (type Lambda):
• inputs=tf.Tensor(shape=(None, 999, 999, 1), dtype=float32)
• mask=None
• training=None