ValueError: could not broadcast input array from shape (512,512) into shape (512,512,1) - tensorflow

I've tried modifying the code with the pre_process function and the color_mode but each time a different error pops up.
def pre_process(img):
ret, mask = cv2. threshold(img, 100, 255, cv2.THRESH_BINARY_INV)
mask_inv = cv2.bitwise_not(mask)
return mask_inv
train = ImageDataGenerator(rescale=1/255, vertical_flip=True,preprocessing_function=pre_process)
test = ImageDataGenerator(rescale=1/255, vertical_flip=True,preprocessing_function=pre_process)
train_dataset = train.flow_from_directory(path,
target_size=(512,512),
batch_size = 32,
class_mode = 'binary',
color_mode = 'grayscale',
shuffle = True
)
test_dataset = test.flow_from_directory(path,
target_size=(512,512),
batch_size =32,
class_mode = 'binary',
color_mode = 'grayscale',
shuffle = True
)
ValueError: could not broadcast input array from shape (512,512) into shape
(512,512,1)..... It's what i get from the above code.
However, if i used the pre_process method below, there is no error, but my loss is always NAN while training.
def pre_process(img):
ret, mask = cv2. threshold(img, 100, 255, cv2.THRESH_BINARY_INV)
mask_inv = cv2.bitwise_not(mask)
img_expanded = tf.expand_dims(mask_inv, 2)
return img_expanded

Related

The val_loss is nan, but loss is printing. Both train and validation losses are nan in model.evaluate(), and the acc improves during training

There is a 2-class classification problem, and my loss function is custom. The labels are categorical, and the final activation function is Softmax. During the training, the loss is printed, but the val_loss is nan(inf). Using model.evaluate(X_train,Y_train) at the end of training, the train loss is the same as the vaidation loss, and both are nan. 
This is my custom loss function.
def custom_loss(y_true, y_pred):
import tensorflow as tf
bce = tf.keras.losses.BinaryCrossentropy(
from_logits=False,
label_smoothing=0.0,
axis=-1,
reduction="none",
name="binary_crossentropy",
)
intra = tf.constant(1, dtype=tf.float64)
inter = tf.constant(0.01, dtype=tf.float64)
zeros = tf.gather_nd(y_pred,tf.where(tf.argmin(y_true, axis = 1)))
ones = tf.gather_nd(y_pred,tf.where(tf.argmax(y_true, axis = 1)))
centroid_zero = tf.reduce_mean(zeros,0)
centroid_one = tf.reduce_mean(ones,0)
loss_zero_intra = tf.math.squared_difference(zeros,centroid_zero)
loss_one_intra = tf.math.squared_difference(ones,centroid_zero)
loss_zero_intra = tf.cast(loss_zero_intra, tf.float64)
loss_one_intra = tf.cast(loss_one_intra, tf.float64)
loss_intra = tf.zeros_like(y_pred, tf.float64)
loss_intra = tf.tensor_scatter_nd_update(loss_intra,tf.where(tf.argmin(y_true, axis = 1)),loss_zero_intra)
loss_intra = tf.tensor_scatter_nd_update(loss_intra,tf.where(tf.argmax(y_true, axis = 1)),loss_one_intra)
loss_inter_value = tf.math.sqrt(tf.math.squared_difference(centroid_zero[0],centroid_one[0]) +
tf.math.squared_difference(centroid_zero[1],centroid_one[1]))
loss_inter = tf.fill(tf.shape(y_pred),loss_inter_value)
binary_cross_entropy= tf.tile(tf.expand_dims(bce(y_true,y_pred),axis=1),
tf.constant([1,2],tf.int32))
loss_intra = tf.cast(loss_intra, tf.float64)
loss_inter = tf.cast(loss_inter, tf.float64)
binary_cross_entropy= tf.cast(binary_cross_entropy, tf.float64)
loss = tf.math.multiply(intra, loss_intra) - tf.math.multiply(inter, loss_inter) + binary_cross_entropy
return loss
And Also you can see my model code here:
def create_model(kernelLength = 32, nb_classes = 2, Chans = 19, Samples = 512,
dropoutRate = 0.5 , F1 = 8, D = 2, F2 = 16, norm_rate = 0.25,
dropoutType = 'Dropout', optimizer_type = 'Adam', lr=0.0005, **kwargs):
K.clear_session()
gc.collect()
if dropoutType == 'SpatialDropout2D':
dropoutType = SpatialDropout2D
elif dropoutType == 'Dropout':
dropoutType = Dropout
else:
raise ValueError('dropoutType must be one of SpatialDropout2D '
'or Dropout, passed as a string.')
input1 = Input(shape = (1, Chans, Samples))
block1 = Conv2D(F1, (1, kernelLength), padding = 'same',
input_shape = (1, Chans, Samples),
use_bias = False)(input1)
block1 = BatchNormalization(axis = 1)(block1)
block1 = DepthwiseConv2D((Chans, 1), use_bias = False,
depth_multiplier = D,
depthwise_constraint = max_norm(1.))(block1)
block1 = BatchNormalization(axis = 1)(block1)
block1 = Activation('elu')(block1)
block1 = AveragePooling2D((1, 4))(block1)
block1 = dropoutType(dropoutRate)(block1)
block2 = SeparableConv2D(F2, (1, 16),
use_bias = False, padding = 'same')(block1)
block2 = BatchNormalization(axis = 1)(block2)
block2 = Activation('elu')(block2)
block2 = AveragePooling2D((1, 8))(block2)
block2 = dropoutType(dropoutRate)(block2)
flatten = Flatten(name = 'flatten')(block2)
dense = Dense(nb_classes, name = 'dense',
kernel_constraint = max_norm(norm_rate))(flatten)
softmax = Activation('softmax', name = 'softmax')(dense)
model = Model(inputs=input1, outputs=softmax)
if optimizer_type == 'Adam':
optimizer = Adam(learning_rate = lr)
if optimizer_type == 'Adamax':
optimizer = Adamax(learning_rate = lr)
if optimizer_type == 'AdamW':
optimizer = AdamW(learning_rate = lr)
model.compile(loss=custom_loss, optimizer=optimizer, metrics = ['accuracy'])
return model
The custom_loss function returns three distinct terms. One of them is the binary_cross_entropy. The model works fine with this term, which works the same as binary_cross_entropy in Keras. Therefore, there is no problem with the data. The train and validation accuracy improves throughout training, and the train loss decreases. The number of validation samples is the same as the number of train samples.
After the training was accomplished, by using the model.evaluation(X,Y) function, the loss was shown as "nan," however calculating the loss using the custom loss function, resulting in a "number" not a "nan".
Increasing the batch size, scaling the data, and using clipnorm or clipvalue within the optimizer all had no effect. Furthermore, no nan appears in the model predictions (y_pred).I suspect that the problem is caused by the below extreme value inside the model prediction: An example of model prediction with extremes:
Can anyone suggest a solution to this problem?
Thanks in advance.

Multiple predicted values with tensorflow Bidirectional LSTM

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)```

Batch size has been changed after multiplying input with a matrix

I am writing a custom layer in TensorFlow to calculate PCA. When I feed input with shape(None, 150, 300) to this layer, I receive output with shape (150, 150, 100) with n_components=100.
How can I keep the batch size = None? The output I want is: (None, 150, 100).
def call(self, input_data):
covariance_matrix = tfp.stats.covariance(input_data)
self.eigen_values, self.eigen_vectors = tf.linalg.eig(covariance_matrix)
self.eigen_values = tf.cast(self.eigen_values, dtype=tf.float32)
self.eigen_vectors = tf.cast(self.eigen_vectors, dtype=tf.float32)
self.projection_matrix = tf.transpose(tf.transpose(self.eigen_vectors)[:][-self.n_components:])
output_data = tf.matmul(input_data, self.projection_matrix)
return output_data

How to create a bi-input TPU model for images?

I want to convert my GPU model to TPU model. My GPU model takes two input image and has the same output for both images. I use custom data generator for this. There are two parallel networks; one for each input.
From this StackOverflow question, I tried to solve this but I failed.
Here is what I tried
dataset_12 = tf.data.Dataset.from_tensor_slices((left_train_paths, right_train_paths))
dataset_label = tf.data.Dataset.from_tensor_slices(train_labels)
dataset = tf.data.Dataset.zip((dataset_12, dataset_label)).batch(2).repeat()
Problem I am facing is that I am unable to decode the bi-input images.
Here is the decoder function
def decode_image(filename, label=None, image_size=(IMG_SIZE_h, IMG_SIZE_w)):
bits = tf.io.read_file(filename)
image = tf.image.decode_jpeg(bits, channels=3)
image = tf.cast(image, tf.float32) / 255.0
image = tf.image.resize(image, image_size)
#convert to numpy and do some cv2 staff mb?
if label is None:
return image
else:
return image, label
The issue is that I am unable to pass both images to the decoder function at the same time. How can I resolve this?
I also try to decode the image in following way
def decode(img,image_size=(IMG_SIZE_h, IMG_SIZE_w)):
bits = tf.io.read_file(img)
image = tf.image.decode_jpeg(bits, channels=3)
image = tf.cast(image, tf.float32) / 255.0
image = tf.image.resize(image, image_size)
return image
def decode_image(left, right,labels=None ):
if labels is None:
return decode(left),decode(right)
else:
return decode(left),decode(right),labels
image=tf.data.Dataset.from_tensor_slices((left_train_paths,right_train_paths,train_labels ))
dataset=image.map(decode_image, num_parallel_calls=AUTO).repeat().shuffle(512).batch(BATCH_SIZE).prefetch(AUTO)
dataset
The output is of dataset variable is now as
<PrefetchDataset shapes: ((None, 760, 760, 3), (None, 760, 760, 3), (None, 8)), types: (tf.float32, tf.float32, tf.int64)>
How can I pass it to the model now?
Model
def get_model():
left_tensor = Input(shape=(IMG_SIZE_h,IMG_SIZE_w,3))
right_tensor = Input(shape=(IMG_SIZE_h,IMG_SIZE_w,3))
left_model = EfficientNetB3(input_shape = (img_shape,img_shape,3), include_top = False, weights = 'imagenet',input_tensor=left_tensor)
right_model = EfficientNetB3(input_shape = (img_shape,img_shape,3), include_top = False, weights = 'imagenet',input_tensor=right_tensor)
con = concatenate([left_model.output, right_model.output])
GAP= GlobalAveragePooling2D()(con)
out = Dense(8, activation = 'sigmoid')(GAP)
model =Model(inputs=[left_input, right_input], outputs=out)
return model
I found a pretty elegant solution. I will explain step by step since may be a bit different of what you thought:
When decoding the images stack both images in a single tensor so the input tensor will be of shape [2, IMAGE_H, IMAGE_W, 3]
def decode_single(im_path, image_size):
bits = tf.io.read_file(im_path)
image = tf.image.decode_jpeg(bits, channels=3)
image = tf.cast(image, tf.float32) / 255.0
image = tf.image.resize(image, image_size)
return image
# Note that the image paths are packed in a tuple, and we unpack them inside the function
def decode(paths, label=None, image_size=(128, 128)):
image_path1, image_path2 = paths
im1 = decode_single(image_path1, image_size)
im2 = decode_single(image_path2, image_size)
images = tf.stack([im1, im2])
if label is not None:
return images, label
return images
I declare the data pipeline so the paths are packed in a tuple.
label_ds = ...
ds = tf.data.Dataset.from_tensor_slices((left_paths, right_paths))
ds = tf.data.Dataset.zip((ds, label_ds)) # returns as ((im_path1, im_path2), label)) not (im_path1, im_path2, label)
ds = ds.map(decode).batch(4)
print(ds)
# Out: <BatchDataset shapes: ((None, 2, 128, 128, 3), ((None,),)), types: (tf.float32, (tf.int32,))>
Since we are feeding batches of two images (None, 2, 128, 128, 3). Declare the model with a single input of shape (2, HEIGHT, WIDTH, 3) and then we split the input in the two images:
def get_model():
input_layer = Input(shape=(2, IMAGE_H,IMAGE_W,3))
# Split into two images
right_image, left_image = Lambda(lambda x: tf.split(x, 2, axis=1))(input_layer)
right_image = Reshape([IMAGE_H, IMAGE_W, 3])(right_image)
left_image = Reshape([IMAGE_H, IMAGE_W, 3])(left_image)
# Replace by EfficientNets
left_model = Conv2D(64, 3)(left_image)
right_model = Conv2D(64, 3)(right_image)
con = Concatenate(-1)([left_model, right_model])
GAP = GlobalAveragePooling2D()(con)
out = Dense(8, activation = 'sigmoid')(GAP)
model = tf.keras.Model(inputs=input_layer, outputs=out)
return model
Finally compile and train the model as usual:
model = get_model()
model.compile(...)
model.fit(ds, epochs=10)

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)