AttributeError: 'function' object has no attribute 'predict'. Keras - python-3.x

I am working on an RL problem and I created a class to initialize the model and other parameters. The code is as follows:
class Agent:
def __init__(self, state_size, is_eval=False, model_name=""):
self.state_size = state_size
self.action_size = 20 # measurement, CNOT, bit-flip
self.memory = deque(maxlen=1000)
self.inventory = []
self.model_name = model_name
self.is_eval = is_eval
self.done = False
self.gamma = 0.95
self.epsilon = 1.0
self.epsilon_min = 0.01
self.epsilon_decay = 0.995
def model(self):
model = Sequential()
model.add(Dense(units=16, input_dim=self.state_size, activation="relu"))
model.add(Dense(units=32, activation="relu"))
model.add(Dense(units=8, activation="relu"))
model.add(Dense(self.action_size, activation="softmax"))
model.compile(loss="categorical_crossentropy", optimizer=Adam(lr=0.003))
return model
def act(self, state):
options = self.model.predict(state)
return np.argmax(options[0]), options
I want to run it for only one iteration, hence I create an object and I pass a vector of length 16 like this:
agent = Agent(density.flatten().shape)
state = density.flatten()
action, probs = agent.act(state)
However, I get the following error:
AttributeError Traceback (most recent call last) <ipython-input-14-4f0ff0c40f49> in <module>
----> 1 action, probs = agent.act(state)
<ipython-input-10-562aaf040521> in act(self, state)
39 # return random.randrange(self.action_size)
40 # model = self.model()
---> 41 options = self.model.predict(state)
42 return np.argmax(options[0]), options
43
AttributeError: 'function' object has no attribute 'predict'
What's the issue? I checked some other people's codes as well, like this and I think mine is also very similar.
Let me know.
EDIT:
I changed the argument in Dense from input_dim to input_shape and self.model.predict(state) to self.model().predict(state).
Now when I run the NN for one input data of shape (16,1), I get the following error:
ValueError: Error when checking input: expected dense_1_input to have
3 dimensions, but got array with shape (16, 1)
And when I run it with shape (1,16), I get the following error:
ValueError: Error when checking input: expected dense_1_input to have
3 dimensions, but got array with shape (1, 16)
What should I do in this case?

in last code block,
def act(self, state):
options = self.model.predict(state)
return np.argmax(options[0]), options
self.model is a function which is returning a model, it should be self.model().predict(state)

I used np.reshape. So in this case, I did
density_test = np.reshape(density.flatten(), (1,1,16))
and the network gave the output.

Related

Issue implementing InceptionV3 with binary classifier - transfer learning with Pytorch

I'm having an issue getting Inception V3 to work as the feature extractor with a binary classifier in Pytorch. I update the primary and auxiliary nets in Inception to have the binary class (as done in https://pytorch.org/tutorials/beginner/finetuning_torchvision_models_tutorial.html)
but I'm getting an error
#Parameters for Inception V3
num_classes= 2
model_ft = models.inception_v3(pretrained=True)
# set_parameter_requires_grad(model_ft, feature_extract)
#handle auxilliary net
num_ftrs = model_ft.AuxLogits.fc.in_features
model_ft.AuxLogits.fc = nn.Linear(num_ftrs, num_classes)
#handle primary net
num_ftrs = model_ft.fc.in_features
model_ft.fc = nn.Linear(num_ftrs,num_classes)
# input_size = 299
#simulate data input
x = torch.rand([64, 3, 299, 299])
#create model with inception backbone
backbone = model_ft
num_filters = backbone.fc.in_features
layers = list(backbone.children())[:-1]
feature_extractor = nn.Sequential(*layers)
# use the pretrained model to classify damage 2 classes
num_target_classes = 2
classifier = nn.Linear(num_filters, num_target_classes)
feature_extractor.eval()
with torch.no_grad():
representations = feature_extractor(x).flatten(1)
x = classifier(representations)
But Im getting the error
RuntimeError Traceback (most recent call last)
<ipython-input-54-c2be64b8a99e> in <module>()
11 feature_extractor.eval()
12 with torch.no_grad():
---> 13 representations = feature_extractor(x)
14 x = classifier(representations)
9 frames
/usr/local/lib/python3.7/dist-packages/torch/nn/modules/conv.py in _conv_forward(self, input, weight, bias)
442 _pair(0), self.dilation, self.groups)
443 return F.conv2d(input, weight, bias, self.stride,
--> 444 self.padding, self.dilation, self.groups)
445
446 def forward(self, input: Tensor) -> Tensor:
RuntimeError: Expected 3D (unbatched) or 4D (batched) input to conv2d, but got input of size: [64, 2]
before I updated the class to 2 (when it was 1000) I was getting the same error but with [64, 1000]. This method of creating a backbone and adding a classifier worked for Resnet but not here. I think it's because of the auxiliary net structure but not sure how to update it to deal with the dual output? Thanks
Inheriting feature_extracture by children function at line layers = list(backbone.children())[:-1] will bring the module from backbone to feature_extracture only, not the operation in forward function.
Let's take a look at the code below:
class Example(torch.nn.Module):
def __init__(self):
super().__init__()
self.avg = torch.nn.AdaptiveAvgPool2d((1,1))
self.linear = torch.nn.Linear(10, 1)
def forward(self, x):
out = self.avg(x)
out = out.squeeze()
out = self.linear(out)
return out
x = torch.randn(5, 10, 12, 12)
model = Example()
y = model(x) # work well
new_model = torch.nn.Sequential(*list(model.children()))
y = new_model(x) # error
Module model and new_model have the same blocks but not the same way of working. In new_module, the output from the pooling layer is not squeezed yet, so the shape of linear input is violate its assumption which causes the error.
In your case, the last two comments are redundant and that's why it returns the error, you did create a new fc in the InceptionV3 module at line model_ft.fc = nn.Linear(num_ftrs,num_classes). Therefore, replace the last one as the code below should work fine:
with torch.no_grad():
x = model_ft(x)

Bidirectional RNN - 'NoneType' object has no attribute '_inbound_nodes' error

I wanna build a Recurrence model which do POS(Part Of Speech tagging) task.
It gets input sentence and outputs tags of each words:
DT NN VBD DT NN
the dog ate the cat
I wanna use 'bidirectional convolution' idea:
input(forward way) -> Recurrence layer -> Conv layer
input(backward way) -> Recurrence layer -> Conv layer
and then do concatenate both,
get the output through the Dense and Time-Distributed layer:
Here's the main.
I wrote the code like:
def make_model(input):
Embeded_input = L.Embedding(len(all_words),32,name='a')(input) # batch, 10002, 32
RNN = keras.models.Sequential()
RNN.add(L.GRU(64, return_sequences=True, recurrent_dropout=0.3,name='b'))
RNN.add(L.LSTM(64, return_sequences=True, recurrent_dropout=0.1,name='c'))
forward1 = RNN(Embeded_input)
backward1 = RNN(Embeded_input[:,::-1,:])
CNN = keras.models.Sequential()
CNN.add(L.Conv1D(32, 3, padding='same', activation='relu',name='d'))
CNN.add(L.Conv1D(32, 3, padding='same', activation='relu',name='e'))
forward2 = CNN(forward1)
backward2 = CNN(backward1)
concat = L.concatenate([forward2, backward2],name='f')
stepwise_dense = L.Dense(len(all_tags),activation='softmax',name='g')
stepwise_dense = L.TimeDistributed(stepwise_dense,name='h')
OUTPUT = stepwise_dense(concat)
return OUTPUT
inputs = L.Input((None,), dtype='int32', name='input')
outputs = make_model(inputs)
model = keras.models.Model(inputs=inputs, outputs=outputs, name='POS_improved_07')
model.summary()
and get the Error from the second latest line:
AttributeError Traceback (most recent call last)
<ipython-input-76-cf1cead269f5> in <module>()
27 outputs = BIRNN(input)
28
---> 29 model = keras.models.Model(inputs=inputs, outputs=outputs, name='POS_improved_07')
30
31 model.summary()
8 frames
/tensorflow-1.15.2/python3.7/keras/engine/network.py in build_map(tensor, finished_nodes, nodes_in_progress, layer, node_index, tensor_index)
1391 ValueError: if a cycle is detected.
1392 """
-> 1393 node = layer._inbound_nodes[node_index]
1394
1395 # Prevent cycles.
AttributeError: 'NoneType' object has no attribute '_inbound_nodes'
ps.
where input comes from
import nltk
import numpy as np
nltk.download('brown')
nltk.download('universal_tagset')
data = nltk.corpus.brwon.tagged_sents(tagset='universal')
all_tags = ['#EOS#','#UNK#','ADV', 'NOUN', 'ADP', 'PRON', 'DET', '.', 'PRT', 'VERB', 'X', 'NUM', 'CONJ', 'ADJ']
data = np.array([[(word.lower(),tag) for word,tag in sentence] for sentence in data ])
and then
from collections import Counter
word_counts = Counter()
for sentence in data:
words,tags = zip(*sentence)
word_counts.update(words)
all_words = ['#EOS#','#UNK#']+list(list(zip(*word_counts.most_common(10000)))[0]) # len=10002
with generate_batches:
def to_matrix(lines,token_to_id,max_len=None,pad=0,dtype='int32',time_major=False):
"""Converts a list of names into rnn-digestable matrix with paddings added after the end"""
max_len = max_len or max(map(len,lines))
matrix = np.empty([len(lines),max_len],dtype)
matrix.fill(pad)
for i in range(len(lines)):
line_ix = list(map(token_to_id.__getitem__,lines[i]))[:max_len]
matrix[i,:len(line_ix)] = line_ix
return matrix.T if time_major else matrix
from keras.utils.np_utils import to_categorical
BATCH_SIZE=32
def generate_batches(sentences,batch_size=BATCH_SIZE,max_len=None,pad=0):
assert isinstance(sentences,np.ndarray),"Make sure sentences is a numpy array"
while True:
indices = np.random.permutation(np.arange(len(sentences)))
for start in range(0,len(indices)-1,batch_size):
batch_indices = indices[start:start+batch_size]
batch_words,batch_tags = [],[]
for sent in sentences[batch_indices]:
words,tags = zip(*sent)
batch_words.append(words)
batch_tags.append(tags)
batch_words = to_matrix(batch_words,word_to_id,max_len,pad)
batch_tags = to_matrix(batch_tags,tag_to_id,max_len,pad)
batch_tags_1hot = to_categorical(batch_tags,len(all_tags)).reshape(batch_tags.shape+(-1,))
yield batch_words,batch_tags_1hot
the model will be trained as:
model.compile('adam','categorical_crossentropy')
model.fit_generator(generate_batches(train_data),
len(train_data)/BATCH_SIZE,
callbacks=[
EvaluateAccuracy(),
save_in_drive(model_filename, MODEL_SAVE_FOLDER_PATH)
],
epochs=5)

How to fix 'No gradients provided for any variable' error when using ctc_loss in Tensorflow

I am trying to make Baidu's Deep Speech 2 model in Tensorflow 2.0.0alpha0. I am having trouble optimizing the Tensorflow ctc_loss using a tf.GradientTape() object for calculating the gradients.
I am currently passing a tensor of shape (batch_size, max_step, feats) to my model and then passing the computed logits to the loss function. I have also tried passing a sparse tensor but this also does not work.
Here is the code for creating my model
import tensorflow as tf
class DeepSpeech2(tf.keras.Model):
def __init__(self, vocab_size, conv_filters=[11], conv_kernel_sizes=[1280], conv_strides=[2],
recur_sizes=[100], rnn_type='gru', bidirect_rnn=False, batch_norm=True,
learning_rate=1e-3, name='DeepSpeech2'):
super(DeepSpeech2, self).__init__()
self._vocab_size = vocab_size
self._conv_filters = conv_filters
self._conv_kernel_sizes = conv_kernel_sizes
self._conv_strides = conv_strides
self._recur_sizes = recur_sizes
self._rnn_type = rnn_type
self._bidirect_rnn = bidirect_rnn
self._batch_norm = batch_norm
self._learning_rate = learning_rate
self._name = name
self._conv_batch_norm = None
with tf.name_scope(self._name):
self._convolution = [tf.keras.layers.Conv1D(filters=conv_filters[i],
kernel_size=conv_kernel_sizes[i], strides=conv_strides[i],
padding='valid', activation='relu',
name='conv1d_{}'.format(i)) for i in range(len(self._conv_filters))]
if self._batch_norm:
self._conv_batch_norm = tf.keras.layers.BatchNormalization(name='bn_conv_1d')
if self._rnn_type == 'gru':
rnn_init = tf.keras.layers.GRU
elif self._rnn_type == 'lstm':
rnn_init = tf.keras.layers.LSTM
else:
raise Exception("Invalid rnn_type: '{}' (must be 'lstm' or 'gru')"
.format(self._rnn_type))
self._rnn = []
for i, r in enumerate(self._recur_sizes):
layer = rnn_init(r, activation='relu', return_sequences=True,
name='{}_{}'.format(self._rnn_type, i))
if self._bidirect_rnn:
layer = tf.keras.layers.Bidirectional(layer)
self._rnn.append(layer)
if self._batch_norm:
self._rnn.append(tf.keras.layers.BatchNormalization())
self._fc = tf.keras.layers.TimeDistributed(tf.keras.layers.Dense(
self._vocab_size, name='fc', activation='linear'))
self._optimizer = tf.keras.optimizers.Adam(lr=self._learning_rate)
def __call__(self, specs):
with tf.name_scope(self._name):
feats = specs
for layer in self._convolution:
feats = layer(feats)
if self._conv_batch_norm:
feats = self._conv_batch_norm(feats)
rnn_outputs = feats
for layer in self._rnn:
rnn_outputs = layer(rnn_outputs)
outputs = self._fc(rnn_outputs)
return tf.transpose(outputs, (1, 0, 2))
#tf.function
def train_step(self, specs, spec_lengths, labels, label_lengths):
with tf.GradientTape() as tape:
logits = self.__call__(specs)
loss = tf.nn.ctc_loss(labels=labels, logits=logits,
label_length=label_lengths, logit_length=spec_lengths)
cost = tf.reduce_sum(loss)
decoded, neg_sum_logits = tf.nn.ctc_greedy_decoder(logits, label_lengths)
gradients = tape.gradient(cost, self.trainable_variables)
self._optimizer.apply_gradients(zip(gradients, self.trainable_variables))
return (decoded[0].indices, decoded[0].values, decoded[0].dense_shape), cost
I am currently getting the following error
ValueError: No gradients provided for any variable: ['DeepSpeech2/conv1d_0/kernel:0', 'DeepSpeech2/conv1d_0/bias:0', 'DeepSpeech2/bn_conv_1d/gamma:0', 'DeepSpeech2/bn_conv_1d/beta:0', 'DeepSpeech2/gru_0/kernel:0', 'DeepSpeech2/gru_0/recurrent_kernel:0', 'DeepSpeech2/gru_0/bias:0', 'DeepSpeech2/batch_normalization_v2/gamma:0', 'DeepSpeech2/batch_normalization_v2/beta:0', 'DeepSpeech2/time_distributed/kernel:0', 'DeepSpeech2/time_distributed/bias:0'].
The error occurs at the line where the gradients are applied to the optimizer. When I print out my gradients variable, it is just a list of None
From what I understand, this error is indicating that there is no path from the variables to the loss in the graph but I'm not sure why I am getting this. Any help would be greatly appreciated!

initialising and accessing an array of weights in a custom keras layer

I am writing a custom keras layer for convolution in a cnn architecture in fourier domain:
class Fourier_Conv2D(Layer):
def __init__(self, no_of_kernels, **kwargs):
self.no_of_kernels = no_of_kernels
super(Fourier_Conv2D, self).__init__(**kwargs)
def build(self, input_shape):
self.kernel = self.add_weight(name = 'kernel',
shape = input_shape + (self.no_of_kernels,),
initializer = 'uniform', trainable = True)
super(Fourier_Conv2D, self).build(input_shape)
def call(self, x):
return K.dot(x, self.kernel[0])
In the call function, I need to do pointwise multiplication of the fft of input with fft of each kernel (according to the convolution theorem) and add the products before passing this sum to activation function. But how can I access each weight separately in the call function, as using array index to do so is giving the following attribute error -
AttributeError Traceback (most recent call last)
<ipython-input-71-9617a8e7ab2e> in <module>()
1 x = Fourier_Conv2D(5)
----> 2 x.call((2,2,1))
<ipython-input-70-02ded53b8f6f> in call(self, x)
11
12 def call(self, x):
---> 13 return K.dot(x, self.kernel[0])
14
AttributeError: 'Fourier_Conv2D' object has no attribute 'kernel'
Thanks in advance for any help in solving the error.
You are not using your layer correctly. The line x.call((2,2,1)) makes no sense since you need to pass a tensor to the layer. You should instead do something like this:
x = Input((3,4))
custom_layer = Fourier_Conv2D(10)
output = custom_layer(x)
Moreover, there are some errors in the definition of your layer. The following should work:
class Fourier_Conv2D(Layer):
def __init__(self, no_of_kernels, **kwargs):
self.no_of_kernels = no_of_kernels
super(Fourier_Conv2D, self).__init__(**kwargs)
def build(self, input_shape):
# Note the changes to the shape parameter
self.kernel = self.add_weight(name = 'kernel',
shape = (int(input_shape[-1]), self.no_of_kernels),
initializer = 'uniform', trainable = True)
super(Fourier_Conv2D, self).build(input_shape)
def call(self, x):
return K.dot(x, self.kernel) # kernel[0] --> kernel

How to find out specific python error?

I am writing the following classifier to check out sci-kit.
...
class MyClassifier():
def fit(self, x_train, y_train):
self.x_train = x_train
self.y_train = y_train
return
def predict(self, x_test):
prediction = []
for row in x_test:
label = self.closest(row)
prediction.append(label)
return prediction
def closest(self, row):
best_dist = euc(row, self.x_train[0])
best_index = 0
for i in range(1, len(self.x_train)):
dist = euc(row, self.x_train[0])
if dist < best_dist:
best_dist = dist
best_index = i
return self.y_train[best_index]
And later, I want to use my own classifier:
# Use my own Classifier
classifer = MyClassifier()
print(classifer)
classifer = classifer.fit(x_train, y_train)
prediction = classifer.predict(x_test)
print(prediction)
print(y_test)
When I run it, I am getting the following error:
<__main__.MyClassifier object at 0x103ec5668>
Traceback (most recent call last):
File "/.../NewClassifier.py", line 72, in <module>
prediction = classifer.predict(x_test)
AttributeError: 'NoneType' object has no attribute 'predict'
What's wrong with predict() function?
Your classmethod
def fit(self, x_train, y_train):
self.x_train = x_train
self.y_train = y_train
return
returns nothing, so it implicitly returns None.
Therefor classifer = classifer.fit(x_train, y_train) is overwrites the variable named classifer of type MyClassifier wiht a None.
A None has not method that you can call - thats the exact error message you got.
You should change classifer = classifer.fit(x_train, y_train) to simply
classifer.fit(x_train, y_train)
so you keep the variable named classifer as your Class-Instance instead of "overwriting" it with None.
This should fix it:
# Use my own Classifier
classifer = MyClassifier()
print(classifer)
classifer.fit(x_train, y_train)
prediction = classifer.predict(x_test)
print(prediction)
print(y_test)
I recommend using Python's built in debugger, pdb. If you add import pdb;pdb.set_trace() before your classifer = MyClassifier() statement, you can see every variable and interact with your code.
Now, you are overwriting your class instantiation.
-> print(classifer)
(Pdb) n
<__main__.MyClassifier object at 0x7f7fe2f139e8> // This is your classifer object
-> classifer = classifer.fit("test", "test2")
(Pdb) classifer
-> prediction = classifier.predict(x_test)
(Pdb) classifer
(Pdb)
So, because you are naming the variable the same thing, it's overwriting your previous class.
You have classifer = MyClassifier() and then classifer = classifer.foo so, it loses it's orginal reference to MyClassifier().
Secondly, your fit(x_train, y_train) function doesn't return anything.
Having:
def fit(self, x_train, y_train):
self.x_train = x_train
self.y_train = y_train
return
Is the same as:
def fit(self, x_train, y_train):
self.x_train = x_train
self.y_train = y_train
return None
Which is what your getting:
(Pdb) print(classifer)
None
And thus, that's why your receiving AttributeError: 'NoneType' object has no attribute 'predict' because classifer is None.
I'm not sure what the fit function is supposed to return, but I imagine it's self. So, the following code works for me in getting past your error, but since i don't know what x_train, y_train, x_test, and y_test are supposed to be, I couldn't run all of your code. Still, it fixes the problem you asked the question about.
class MyClassifier():
def fit(self, x_train, y_train):
self.x_train = x_train
self.y_train = y_train
return self // Must return something, and from context, this
// seems to be your intention.
def predict(self, x_test):
prediction = []
for row in x_test:
label = self.closest(row)
prediction.append(label)
return prediction
def closest(self, row):
best_dist = euc(row, self.x_train[0])
best_index = 0
for i in range(1, len(self.x_train)):
dist = euc(row, self.x_train)
if dist < best_dist:
best_dist = dist
best_index = i
return self.y_train[best_index]
classifier = MyClassifier()
print(classifier)
classifier2 = classifier.fit("test", "test2")
prediction = classifier2.predict(x_test)
print(prediction)
print(y_test)

Resources