I'm trying to implement a Fully Convolutional Neural Network and can successfully test the accuracy of the model on the test set after training. However, I'd like to use the model to make a prediction on a single sample only. Training was in batches. I believe what I'm missing is related to batch size and input shape. Here is the configuration for the network:
def read(file_name):
data = np.loadtxt(file_name, delimiter="\t")
y = data[:, 0]
x = data[:, 1:]
return x, y.astype(int)
train_data, train_labels = read("FordA_TRAIN.tsv")
test_data, test_labels = read("FordA_TEST.tsv")
train_data = train_data.reshape((train_data.shape[0], train_data.shape[1], 1))
test_data = test_data.reshape((test_data.shape[0], test_data.shape[1], 1))
num_classes = len(np.unique(train_labels))
#print(train_data[0])
# Shuffle the data to prepare for validation_split (and prevent overfitting for class order)
idx = np.random.permutation(len(train_data))
train_data = train_data[idx]
train_labels = train_labels[idx]
#Standardize labels to have a value between 0 and 1 rather than -1 and 1.
train_labels[train_labels == -1] = 0
test_labels[test_labels == -1] = 0
def make_model(input_shape):
input_layer = keras.layers.Input(input_shape)
conv1 = keras.layers.Conv1D(filters=64, kernel_size=3, padding="same")(input_layer)
conv1 = keras.layers.BatchNormalization()(conv1)
conv1 = keras.layers.ReLU()(conv1)
conv2 = keras.layers.Conv1D(filters=64, kernel_size=3, padding="same")(conv1)
conv2 = keras.layers.BatchNormalization()(conv2)
conv2 = keras.layers.ReLU()(conv2)
conv3 = keras.layers.Conv1D(filters=64, kernel_size=3, padding="same")(conv2)
conv3 = keras.layers.BatchNormalization()(conv3)
conv3 = keras.layers.ReLU()(conv3)
gap = keras.layers.GlobalAveragePooling1D()(conv3)
output_layer = keras.layers.Dense(num_classes, activation="softmax")(gap)
return keras.models.Model(inputs=input_layer, outputs=output_layer)
model = make_model(input_shape=train_data.shape[1:])
keras.utils.plot_model(model, show_shapes=True)
epochs = 500
batch_size = 32
callbacks = [
keras.callbacks.ModelCheckpoint(
"best_model.h5", save_best_only=True, monitor="val_loss"
),
keras.callbacks.ReduceLROnPlateau(
monitor="val_loss", factor=0.5, patience=20, min_lr=0.0001
),
keras.callbacks.EarlyStopping(monitor="val_loss", mode = 'min', patience=50, verbose=1),
]
model.compile(
optimizer="adam",
loss="sparse_categorical_crossentropy",
metrics=["sparse_categorical_accuracy"],
)
history = model.fit(
train_data,
train_labels,
batch_size=batch_size,
epochs=epochs,
callbacks=callbacks,
validation_split=0.2,
verbose=1,
)
model = keras.models.load_model("best_model.h5")
test_loss, test_acc = model.evaluate(test_data, test_labels)
print("Test accuracy", test_acc)
print("Test loss", test_loss)
The above code can successfully display where the accuracy converged. Now, I'd like to make predictions on single samples. So far I have:
def read(file_name):
data = np.loadtxt(file_name, delimiter="\t")
y = data[:, 0]
x = data[:, 1:]
return x, y.astype(int)
test_data, test_labels = read("FordA_TEST_B.tsv")
test_data = test_data.reshape((test_data.shape[0], test_data.shape[1], 1))
test_labels[test_labels == -1] = 0
print(test_data)
model = keras.models.load_model("forda_original_model.h5")
q = model.predict(test_data[0])
This raises the error: ValueError: Error when checking input: expected input_1 to have 3 dimensions, but got array with shape (500, 1)
How does the input have to be reshaped and what is the rule to go by? Any help is much appreciated!
Copied from a comment:
The model expects a batch dimension. Thus, to predict for a single model, just expand the dimensions to create a single-sized batch by running:
q = model.predict(test_data[0][None,...])
or
q = model.predict(test_data[0][np.newaxis,...])
Related
I have a pandas dataframe of features and samples, and a single series with binary category (0 or 1) values. With that I'm trying to train a neural network, but I am getting the error:
TensorFlow incompatible shapes binary classification
Here is a summary of the code:
X_train, X_test, y_train, y_test = train_test_split(df_x, series_y, random_state=1, test_size=0.25)
best_weight_path = 'best_weights.hdf5'
x = df_x.to_numpy()
y = series_y.to_numpy()
numpy_x_train = X_train.to_numpy()
numpy_y_train = y_train.to_numpy()
numpy_x_test = X_test.to_numpy()
numpy_y_test = y_test.to_numpy()
model = Sequential()
model.add(Dense(20, input_dim=x.shape[1], activation='relu'))
model.add(Dense(10, activation='relu'))
model.add(Dense(2, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam')
monitor = EarlyStopping(monitor='val_loss', min_delta=1e-3, patience=5, verbose=1, mode='auto')
checkpointer = ModelCheckpoint(filepath=best_weight_path, verbose=0, save_best_only=True)
model.fit(x, y, validation_data=(numpy_x_test, numpy_y_test), callbacks=[monitor, checkpointer], verbose=0, epochs=1000)
ValueError: Shapes (None, 1) and (None, 2) are incompatible
Shouldn't the last dense layer have 2 units as there are two possible outcomes, so where is the shape (None, 1) coming from?
The problem is related to the correct choice of an appropriate loss function according to the format of your labels. you have 2 possibilities when using softmax in classification task:
1 possibility: if you have 1D integer encoded target, you can use sparse_categorical_crossentropy as loss function (this seems to be your case)
n_class = 2
n_features = 100
n_sample = 1000
X = np.random.randint(0,10, (n_sample,n_features))
y = np.random.randint(0,n_class, n_sample)
inp = Input((n_features,))
x = Dense(128, activation='relu')(inp)
out = Dense(n_class, activation='softmax')(x)
model = Model(inp, out)
model.compile(loss='sparse_categorical_crossentropy',optimizer='adam',metrics=['accuracy'])
history = model.fit(X, y, epochs=3)
2 possibility: if you have one-hot encoded your target in order to have 2D shape (n_samples, n_class), you can use categorical_crossentropy
n_class = 2
n_features = 100
n_sample = 1000
X = np.random.randint(0,10, (n_sample,n_features))
y = pd.get_dummies(np.random.randint(0,n_class, n_sample)).values
inp = Input((n_features,))
x = Dense(128, activation='relu')(inp)
out = Dense(n_class, activation='softmax')(x)
model = Model(inp, out)
model.compile(loss='categorical_crossentropy',optimizer='adam',metrics=['accuracy'])
history = model.fit(X, y, epochs=3)
I'm new to Keras. With transfer learning following an online tutorial, I tried to train a model for my custom dataset and below is my code. Now how should I perform classification given an image?
Here is the training code:
def build_finetune_model(base_model, dropout, fc_layers, num_classes):
for layer in base_model.layers:
layer.trainable = False
x = base_model.output
x = Flatten()(x)
for fc in fc_layers:
# New FC layer, random init
x = Dense(fc, activation='relu')(x)
x = Dropout(dropout)(x)
# New softmax layer
predictions = Dense(num_classes, activation='softmax')(x)
finetune_model = Model(inputs=base_model.input, outputs=predictions)
return finetune_model
train_datagen = ImageDataGenerator(preprocessing_function=preprocess_input)
train_generator = train_datagen.flow_from_directory(TRAIN_DIR,
target_size=(HEIGHT, WIDTH),
batch_size=BATCH_SIZE)
base_model = MobileNetV2(weights='imagenet', include_top=False, input_shape=(HEIGHT, WIDTH, 3))
root=TRAIN_DIR
class_list = [ item for item in os.listdir(root) if os.path.isdir(os.path.join(root, item)) ]
print (class_list)
FC_LAYERS = [1024, 1024]
dropout = 0.5
finetune_model = build_finetune_model(base_model, dropout=dropout, fc_layers=FC_LAYERS, num_classes=len(class_list))
adam = Adam(lr=0.00001)
finetune_model.compile(adam, loss='categorical_crossentropy', metrics=['accuracy'])
filepath="./checkpoints/" + "MobileNetV2_{epoch:02d}_{acc:.2f}" +"_model_weights.h5"
checkpoint = ModelCheckpoint(filepath, monitor=["acc"], verbose=1, mode='max', save_weights_only=True)
callbacks_list = [checkpoint]
history = finetune_model.fit_generator(train_generator, epochs=NUM_EPOCHS, workers=8,
steps_per_epoch=steps_per_epoch,
shuffle=True, callbacks=callbacks_list)
And here is my classify code, which only returns an array of float numbers!
if __name__ == '__main__':
model = load_model('ResNet50_model_weights.h5')
img_path = 'test.jpg'
img = image.load_img(img_path, target_size=(300, 300))
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
print('Input image shape:', x.shape)
results = model.predict(x)
print('Predicted:', results)
Your models' last layer is softmax, which means that it outputs probabilities for each class between 0 and 1. In order to tell which class the input image is predicted to be, take the argmax of results. argmax returns the index of the maximum element in the array.
predicted_class_label = np.argmax(results)
print("network predicted input image is class {}".format(predicted_class_label))
I have a CSV file with 2 columns of data. I built a regression approach model to make predictions. But currently, I can only get 1 prediction, what can I do to get 2 predictions. I previously used the following model
def build_model():
model = keras.Sequential([
layers.Dense(64, activation=tf.nn.relu, input_shape=[len(train_dataset.keys())]),
layers.Dense(64, activation=tf.nn.relu),
layers.Dense(1)
])
But I found a new model, so I used that one as shown below.
This is how I'm loading the data
column_names = ['longitude', 'Latitude']
raw_dataset = pd.read_csv('loglat.csv', names=column_names)
train_dataset = dataset.sample(random_state=0)
test_dataset = dataset.drop(train_dataset.index)
train_stats = train_dataset.describe()
train_stats = train_stats.transpose()
train_stats
train_labels = train_dataset.pop('longitude')
test_labels = test_dataset.pop('longitude')
normed_train_data = train_dataset
normed_test_data = test_dataset
The new model
from tf.keras.layers import Input, Dense
from tf.keras.models import Model
def build_model():
X = Input(shape=[len(train_dataset.keys())])
hidden_1 = Dense(64, activation=tf.nn.relu)(X)
hidden_2 = Dense(64, activation=tf.nn.relu)(hidden_1)
out_1 = Dense(1)(hidden_2)
out_2 = Dense(1)(hidden_2)
model = Model(inputs=[X], outputs=[out_1, out_2])
optimizer = tf.keras.optimizers.RMSprop(0.001)
model.compile(loss='mean_squared_error',
optimizer=optimizer,
metrics=['mean_absolute_error', 'mean_squared_error'])
return model
model = build_model()
linreg = model.fit(normed_train_data, train_labels, epochs=1000, verbose=0)
test_predictions = model.predict(normed_test_data).flatten()
The error with this is:
ValueError: Error when checking model target: the list of Numpy arrays that you are passing to your model is not the size the model expected. Expected to see 2 array(s), but instead got the following list of 1 arrays: [array([[130.4998]])]...
I want to make a model with following inputs & output.
- Input : images & values
- Output : value (regression)
Input image is read with flow_from_dataframe for augmentation.
And the input value is loaded from csv file to dataframe.
I'm trying to make it 2 input -> Concatenate -> 1 output.
But I have problems to make it work with 2 different types of inputs.
Maybe I should make a new generator.. but i can not find a way.
I appreciate any advice or help.
Here are some of my code.
train_df = pd.read_csv("train.csv")
test_df = pd.read_csv("test.csv")
file_num = train_df.loc[:,'NUM']
value = train_df.loc[:,'VALUE']
# ------------------------------------------
train_datagen=ImageDataGenerator(rescale=1./255.,
rotation_range=90,
validation_split=0.1)
test_datagen=ImageDataGenerator(rescale=1./255.)
train_img=train_datagen.flow_from_dataframe(
dataframe=train_df,
directory="./DATA_train/",
x_col='NUM',
y_col='VALUE',
subset="training",
batch_size=16,
seed=4,
shuffle=True,
class_mode="other",
target_size=TARGET_SIZE)
valid_img=train_datagen.flow_from_dataframe(
dataframe=train_df,
directory="./DATA_train/",
x_col='NUM',
y_col='VALUE',
subset="validation",
batch_size=4,
seed=4,
shuffle=True,
class_mode="other",
target_size=TARGET_SIZE)
test_img=test_datagen.flow_from_dataframe(
dataframe=test_df,
directory="./DATA_test/",
x_col='NUM',
y_col='VALUE',
batch_size=1,
shuffle=False,
class_mode=None,
target_size=TARGET_SIZE)
max_val = train_df.loc[:,'VALUE'].max()
min_val = train_df.loc[:,'VALUE'].min()
train_val = (train_df.loc[:,'VALUE']-min_val) / (max_val - min_val)
# ------------------------------------------
inputs_image = Input(shape=(64,64,1))
inputs_val = Input(shape=(1,))
x1 = Conv2D(32, (3,3), activation='relu')(inputs_image)
x1 = BatchNormalization()(x1)
x1 = Flatten()(x1)
x1 = Dense(64, activation='relu')(x1)
x1 = Model(inputs=inputs_image, outputs=x1)
x2 = Dense(256, activation='relu')(inputs_mass)
x2 = Dense(64, activation='relu')(x2)
x2 = Model(inputs=inputs_mass, outputs=x2)
combined = layers.concatenate([x1.output,x2.output], axis=-1)
combined = Dense(128, activation='relu')(combined)
outputs = Dense(1, activation='linear')(combined)
model = Model([inputs_image, inputs_val], outputs)
model.compile(optimizer='adam', loss='mean_squared_error', metrics = ['mae'])
# ------------------------------------------
hist = model.fit_generator(generator=train_img, ## This should be modified..??
steps_per_epoch=STEP_SIZE_TRAIN*1,
validation_data=valid_img,
validation_steps=STEP_SIZE_VALID,
epochs = EPOCHS,
verbose=1
)
I'm pretty new to Keras and LSTMs. I've been trying to train my model of sequences to predict the future price of a stock with the code below but the error above kept popping up.
I have tried changing the dtypes of both x_data, y_data with .astype(np.float16). However, all times I am returned with the TypeError stating that I have a float32 type.
If it helps, here are the shapes of my data:
xtrain.shape : (32, 24, 67), ytrain.shape : (32, 24, 1), xtest.shape
: (38, 67), ytest.shape : (38, 1)
Does anyone have any idea on what might be wrong? I've been stuck at this for awhile. It would be great if someone could give me a hint.
y_data = y_data.to_numpy().astype(np.float32)
x_data = main_df.to_numpy().astype(np.float32)
num_x_signals = x_data.shape[1]
num_y_signals = y_data.shape[1]
# SPLIT TRAIN TEST DATA
ratio = 0.85
train_ratio = int(ratio * len(x_data))
x_train = x_data[0:train_ratio]
x_test = x_data[train_ratio:]
y_train = y_data[0:train_ratio]
y_test = y_data[train_ratio:]
# GENERATE RANDOM SEQUENCES
batch_size = 32
sequence_length = 24
EPOCHS = 50
def batch_generator(x_train, y_train, batch_size, sequence_length, num_x_signals, num_y_signals, num_train):
while True:
x_shape = (batch_size, sequence_length, num_x_signals)
x_batch = np.zeros(shape = x_shape).astype(np.float32)
y_shape = (batch_size, sequence_length, num_y_signals)
y_batch = np.zeros(shape = y_shape).astype(np.float32)
for i in range(batch_size):
idx = np.random.randint(num_train - sequence_length)
x_batch[i] = x_train[idx:idx+sequence_length]
y_batch[i] = y_train[idx:idx+sequence_length]
yield (x_batch, y_batch)
generator = batch_generator(x_train, y_train, batch_size, sequence_length, num_x_signals, num_y_signals, train_ratio)
xtrain, ytrain = next(generator)
xtest, ytest = (np.expand_dims(x_test, axis=0),
np.expand_dims(y_test, axis=0))
# LSTM MODEL
model = Sequential()
model.add(LSTM(32, input_shape = (None, num_x_signals,), return_sequences = True))
model.add(Dropout(0.2))
model.add(BatchNormalization())
model.add(LSTM(128, return_sequences = True))
model.add(Dropout(0.15))
model.add(BatchNormalization())
model.add(LSTM(128))
model.add(Dropout(0.18))
model.add(BatchNormalization())
model.add(Dense(32, activation = 'relu'))
model.add(Dropout(0.2))
model.add(Dense(1, activation = 'softmax'))
opt = tf.keras.optimizers.Adam(lr = 0.001, decay = 1e-6)
model.compile(
loss = 'sparse_categorical_crossentropy',
optimizer = opt,
metrics = ['accuracy']
)
name_of_file = f"{to_predict}-{sequence_length}-{future_predict}-{int(time.time())}"
tensorboard = TensorBoard(log_dir = "logs/{}".format(name_of_file))
filepath = "LSTM_Final-{epoch:02d}-{val_acc:.3f}"
checkpoint = ModelCheckpoint("models/{}.model".format(filepath, monitor = 'val_acc', verbose = 1, save_best_only = True, mode = 'max')) # saves only the best ones
history = model.fit(
xtrain, ytrain,
epochs = EPOCHS,
validation_data = (xtest, ytest),
callbacks = [tensorboard, checkpoint]
)
score = model.evaluate(xtest, ytest, verbose = 0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])
model.save("models/{}".format(name_of_file))
I found this issue had to do with the loss function specified.
My code:
import tensorflow as tf
from tensorflow import keras
model = tf.keras.Sequential([
keras.layers.Dense(64, activation=tf.nn.relu, input_shape=[3]),
keras.layers.Dense(64, activation=tf.nn.relu),
keras.layers.Dense(1)
])
#I changed the loss function from 'sparse_categorical_crossentropy' to 'mean_squared error'
model.compile(optimizer='adam',loss='mean_squared_error',metrics=['accuracy'])
X = train_dataset.to_numpy()
y = train_labels.to_numpy()
model.fit(X,y, epochs=5)
X shape was (920,3) and dtype = float64
y shape was (920,1) and dtype = float64
My problem was in the model.fit method. I took the 'sparse_categorical_crossentropy' function from an image recognition example and what I was trying here is a neural network for house prices prediction.