how to write a custom loss function in keras? - python

Here is the model I am writing the custom loss function for:
model = Sequential()
model.add(Conv2D(2,2,padding="same", activation="relu", input_shape=(8,8,1)))
model.add(Dropout(0.2))
model.add(Dropout(0.2))
model.add(Flatten())
model.add(Dropout(0.2))
model.add(Dense(1, activation="sigmoid"))
model.compile(optimizer='Adam', loss=custom_loss1, metrics=['accuracy'])
Here is the custom_loss1 function I wrote:
import keras.backend as kb
def custom_loss1(y_actual, y_predicted):
value = kb.mean(kb.sum(kb.square((y_actual-y_predict)/10)))
return value
But I am getting this error:
ValueError: No gradients provided for any variable: ['conv2d_45/kernel:0', 'conv2d_45/bias:0', 'dense_45/kernel:0', 'dense_45/bias:0'].
What to do?

I am unsure without actually running the code itself but did you try in tensorflow:
adj_diff = (y_actual - y_pred)/10
diff_squared = tf.math.square(adj_diff)
sum_diff = tf.math.add(diff_squared) ## or tf.math.reduce_sum depending on your dimensions
return tf.math.reduce_mean(sum_diff)

Related

OperatorNotAllowedInGraphError: iterating over `tf.Tensor` is not allowed: AutoGraph did convert this function

I'm making a model for binary sentiment analysis, I already made the pre-processing and the model works well. I am trying to create an initial Input Layer and later a Lambda layer, this in order to have inputs when I save my model and upload it to Docker to get predictions by Tensorflow Serving.
Create a function for pre-processing the model input:
#tf.function
def serving(input_serving: tf.string)-> tf.Tensor:
X = []
sentences = list(input_serving)
for sen in sentences:
X.append(preprocess_text(sen))
X = tokenizer.texts_to_sequences([input_serving])
X = pad_sequences(X, padding='post', maxlen=100)
rtn = tf.convert_to_tensor(X)
return rtn
And this is the structure of my model:
model = Sequential()
model.add(Input(shape=(),dtype="string"))
model.add(Lambda(serving))
embedding_layer = Embedding(vocab_size, 300, weights=[embedding_matrix], input_length=100 , trainable=False)
model.add(embedding_layer)
model.add(Dense(256, activation='relu'))
model.add(Dropout(rate=0.5))
model.add(Dense(128, activation='relu'))
model.add(Dropout(rate=0.5))
model.add(Dense(64, activation='relu'))
model.add(Dropout(rate=0.5))
model.add(Flatten())
model.add(Dense(1, activation='sigmoid'))
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['acc'])
Trying to compile the model gives this error:
OperatorNotAllowedInGraphError: iterating over tf.Tensor is not allowed: AutoGraph did convert this function. This might indicate you are trying to use an unsupported feature.
What should I modify to fix this? Or some other way to be able to add these inputs for the predictions?
Thanks.

Problem with set_weights function tensorflow

I've built a Sequential model like this:
model=Sequential()
model.add(Dense(40, activation='relu',input_dim=12))
model.add(Dense(60, activation='relu'))
model.add(Dense(units=3, activation='softmax'))
opt=tf.keras.optimizers.Adam(lr=0.001)
model.compile(loss="mse", optimizer=opt)
model.summary()
I would like to create a second model and then change its weights according to a rule made by me, so I''ve written this code
model2=model
w1=model.get_weights()
w2=model2.get_weights()
for i in range(len(w1)):
j=np.random.random(1)
w1[i]=w2[i]*j
model.set_weights(w1)
model2.set_weights(w2)
After the for cycle w1 is different from w2, but after I set the weights of both models and then recall the get_weights() functions, they are still the same. Why this happens?
create a copy of your model with tf.keras.models.clone_model
model=Sequential()
model.add(Dense(40, activation='relu',input_dim=12))
model.add(Dense(60, activation='relu'))
model.add(Dense(units=3, activation='softmax'))
opt=tf.keras.optimizers.Adam(lr=0.001)
model.compile(loss="mse", optimizer=opt)
model.summary()
model2 = tf.keras.models.clone_model(model) # make a copy
w1 = model.get_weights()
w2 = model2.get_weights()
for i in range(len(w1)):
j=np.random.random(1)
w1[i]=w2[i]*j
model.set_weights(w1)
model2.set_weights(w2)

how to visualize the DNN or CNN model with the values of the input and output layers?

I have applied visualization to the DNN model, but the image just contains a dense layer Without the value of the input and output layers!
The code below explains the visualization process without any error, I tried to show the values of the input and output layers in image.
import pandas as pd
.
.
tf.keras.utils.plot_model
.
.
def create_model():
model = Sequential()
model.add(Input(n_features))
model.add(BatchNormalization())
model.add(Dense(51, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(68, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(85, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(85, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(68, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(51, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(n_outputs, activation='sigmoid'))
model.compile(loss='binary_crossentropy',
optimizer='Adam',
metrics=['accuracy'])
tf.keras.utils.plot_model(model, to_file='model_combined.png')
#model.summary()
return model
#I have tried to use
#from keras.utils.vis_utils import plot_model
# but i found this error : TypeError: 'InputLayer' object is not iterable
# so i use the above library to implement visualization without any error.
Please note that I have downloaded all of these libraries: Graphviz, pydot, pydotplus, python-graphviz
Have you tried Netron app?
It can be used to visualize the DNN or CNN model with the values of the input and output layers.
Here you can find all the details

error when making my own activation function

I am trying to test an activation function on MNIST data
but it gave an error:
TypeError: Using a `tf.Tensor` as a Python `bool` is not allowed. Use `if t is not None:` instead of `if t:` to test if a tensor is defined, and use TensorFlow ops such as tf.cond to execute subgraphs conditioned on the value of a tensor.
Here is my activation function :
def fun1(x):
return np.sqrt(x) if x>=0 else (-(np.sqrt(-x)))
and here is the model:
model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3), kernel_regularizer=regularizers.l2(w_l2),
input_shape=input_shape))
model.add(BatchNormalization())
model.add(Activation(fun1))
model.add(Conv2D(64, (3, 3), kernel_regularizer=regularizers.l2(w_l2)))
model.add(BatchNormalization())
model.add(Activation(fun1))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(128, kernel_regularizer=regularizers.l2(w_l2)))
model.add(BatchNormalization())
model.add(Activation(fun1))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))
model.compile(loss=keras.losses.categorical_crossentropy,
optimizer=keras.optimizers.Adam(),
metrics=['accuracy'])
model.summary()
In the custom activation function, x is a tensor, so Keras backend methods need to be used instead of numpy. Your implementation could be changed to something like this:
from keras import backend as K
def fun1(x):
return K.sqrt(K.abs(x))
For more examples, look at Keras defined activations:
https://github.com/keras-team/keras/blob/master/keras/activations.py

Passing input_dim to KerasClassifier (sklearn wrapper/interface)

I originally tried the same approach and ran into the same error as this SO questioner. However, using the accepted (and only) answer there gave me another error: "input_dim is not a legal parameter."
I then tried to use the solution ("add an input_dim keyarg to the KerasClassifier constructor") on the original question, and got the same error again. Am I doing something wrong, or is there a new way to pass a first layer's input_dim through the sklearn wrapper KerasClassifier now?
Minimal code example below:
from keras.models import Sequential
from keras.layers import Dense
from sklearn import datasets
from keras.wrappers.scikit_learn import KerasClassifier
import numpy as np
def create_model():
# create model
model = Sequential()
model.add(Dense(12, input_dim=4, init='uniform', activation='relu'))
model.add(Dense(6, init='uniform', activation='relu'))
model.add(Dense(1, init='uniform', activation='sigmoid'))
# Compile model
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
return model
#Error thrown here:
model = KerasClassifier(build_fn=create_model, input_dim=5, nb_epoch=150, batch_size=10, verbose=0)
ValueError: input_dim is not a legal parameter
You need to pass the input_dim as one of the parameters to create_model()
def create_model(input_dim):
# create model
model = Sequential()
# model.add(Dense(12, input_dim=4, init='uniform', activation='relu'))
model.add(Dense(12, input_dim=input_dim, init='uniform', activation='relu'))
Though you need not use input_dim inside create_model for the sake of just removing the error.

Categories

Resources