# Error while adding a new metric

``````import tensorflow as tf

LABELS = list(fnamelabels.label.unique())

def apk(actual:Tensor, predicted:Tensor, k=10):
"""
Computes the average precision at k.
This function computes the average prescision at k between two lists of
items.
Parameters
----------
actual : Tensor
A Tensor of elements that are to be predicted (order doesn't matter)
predicted : Tensor
A Tensor of predicted elements (order does matter)
k : int, optional
The maximum number of predicted elements
Returns
-------
score : double
The average precision at k over the input lists
"""
if len(predicted)>k:
predicted = predicted[:k]

score = 0.0
num_hits = 0.0

for i,p in enumerate(predicted):
if p in actual and p not in predicted[:i]:
num_hits += 1.0
score += num_hits / (i+1.0)

if not actual:
return 0.0

return score / min(len(actual), k)

def mapk(input:Tensor, targs:Tensor, k=10)->Rank0Tensor:
"""
Computes the mean average precision at k.
This function computes the mean average prescision at k between two lists
of lists of items.
Parameters
----------
input : Tensor - bs * n_classes
targs : Tensor
k : int, optional
The maximum number of predicted elements
Returns
-------
score : double
The mean average precision at k over the input lists
"""
n = targs.shape[0]
predicted = input.argsort(dim=1).view(n,-1)
actual = targs.view(n, -1)

return np.mean([apk(a,p,k) for a,p in zip(actual, predicted)])

learn = create_cnn(data, models.resnet50, metrics=[mapk])
``````

After running the previous code, I ran ‘learn.fit_one_cycle(1)’ and I got the following error:

``````---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-36-4dfb24161c57> in <module>
----> 1 learn.fit_one_cycle(1)

/anaconda/envs/fastai/lib/python3.6/site-packages/fastai/train.py in fit_one_cycle(learn, cyc_len, max_lr, moms, div_factor, pct_start, wd, callbacks, **kwargs)
18     callbacks.append(OneCycleScheduler(learn, max_lr, moms=moms, div_factor=div_factor,
19                                         pct_start=pct_start, **kwargs))
---> 20     learn.fit(cyc_len, max_lr, wd=wd, callbacks=callbacks)
21
22 def lr_find(learn:Learner, start_lr:Floats=1e-7, end_lr:Floats=10, num_it:int=100, stop_div:bool=True, **kwargs:Any):

/anaconda/envs/fastai/lib/python3.6/site-packages/fastai/basic_train.py in fit(self, epochs, lr, wd, callbacks)
160         callbacks = [cb(self) for cb in self.callback_fns] + listify(callbacks)
161         fit(epochs, self.model, self.loss_func, opt=self.opt, data=self.data, metrics=self.metrics,
--> 162             callbacks=self.callbacks+callbacks)
163
164     def create_opt(self, lr:Floats, wd:Floats=0.)->None:

/anaconda/envs/fastai/lib/python3.6/site-packages/fastai/basic_train.py in fit(epochs, model, loss_func, opt, data, callbacks, metrics)
92     except Exception as e:
93         exception = e
---> 94         raise e
95     finally: cb_handler.on_train_end(exception)
96

/anaconda/envs/fastai/lib/python3.6/site-packages/fastai/basic_train.py in fit(epochs, model, loss_func, opt, data, callbacks, metrics)
87             if hasattr(data,'valid_dl') and data.valid_dl is not None:
88                 val_loss = validate(model, data.valid_dl, loss_func=loss_func,
---> 89                                        cb_handler=cb_handler, pbar=pbar)
90             else: val_loss=None
91             if cb_handler.on_epoch_end(val_loss): break

/anaconda/envs/fastai/lib/python3.6/site-packages/fastai/basic_train.py in validate(model, dl, loss_func, cb_handler, pbar, average, n_batch)
52             if not is_listy(yb): yb = [yb]
53             nums.append(yb[0].shape[0])
---> 54             if cb_handler and cb_handler.on_batch_end(val_losses[-1]): break
55             if n_batch and (len(nums)>=n_batch): break
56         nums = np.array(nums, dtype=np.float32)

/anaconda/envs/fastai/lib/python3.6/site-packages/fastai/callback.py in on_batch_end(self, loss)
236         "Handle end of processing one batch with `loss`."
237         self.state_dict['last_loss'] = loss
--> 238         stop = np.any(self('batch_end', not self.state_dict['train']))
239         if self.state_dict['train']:
240             self.state_dict['iteration'] += 1

/anaconda/envs/fastai/lib/python3.6/site-packages/fastai/callback.py in __call__(self, cb_name, call_mets, **kwargs)
184     def __call__(self, cb_name, call_mets=True, **kwargs)->None:
185         "Call through to all of the `CallbakHandler` functions."
--> 186         if call_mets: [getattr(met, f'on_{cb_name}')(**self.state_dict, **kwargs) for met in self.metrics]
187         return [getattr(cb, f'on_{cb_name}')(**self.state_dict, **kwargs) for cb in self.callbacks]
188

/anaconda/envs/fastai/lib/python3.6/site-packages/fastai/callback.py in <listcomp>(.0)
184     def __call__(self, cb_name, call_mets=True, **kwargs)->None:
185         "Call through to all of the `CallbakHandler` functions."
--> 186         if call_mets: [getattr(met, f'on_{cb_name}')(**self.state_dict, **kwargs) for met in self.metrics]
187         return [getattr(cb, f'on_{cb_name}')(**self.state_dict, **kwargs) for cb in self.callbacks]
188

/anaconda/envs/fastai/lib/python3.6/site-packages/fastai/callback.py in on_batch_end(self, last_output, last_target, train, **kwargs)
269         if not is_listy(last_target): last_target=[last_target]
270         self.count += last_target[0].size(0)
--> 271         self.val += last_target[0].size(0) * self.func(last_output, *last_target).detach().cpu()
272
273     def on_epoch_end(self, **kwargs):

AttributeError: 'numpy.float64' object has no attribute 'detach'
``````

Any help would be appreciated?

Metrics are supposed to return rank0 torch tensor. You have the error because you return a numpy float.

I changed the return statement of the mapk function to the following:

return tf.convert_to_tensor(np.mean([apk(a,p,k) for a,p in zip(actual, predicted)]), dtype=np.float64)

When I ran 'learn.fit_one_cycle(1), I got the following error:

AttributeError Traceback (most recent call last)
in
----> 1 learn.fit_one_cycle(1)

/anaconda/envs/fastai/lib/python3.6/site-packages/fastai/train.py in fit_one_cycle(learn, cyc_len, max_lr, moms, div_factor, pct_start, wd, callbacks, **kwargs)
18 callbacks.append(OneCycleScheduler(learn, max_lr, moms=moms, div_factor=div_factor,
19 pct_start=pct_start, **kwargs))
—> 20 learn.fit(cyc_len, max_lr, wd=wd, callbacks=callbacks)
21
22 def lr_find(learn:Learner, start_lr:Floats=1e-7, end_lr:Floats=10, num_it:int=100, stop_div:bool=True, **kwargs:Any):

/anaconda/envs/fastai/lib/python3.6/site-packages/fastai/basic_train.py in fit(self, epochs, lr, wd, callbacks)
160 callbacks = [cb(self) for cb in self.callback_fns] + listify(callbacks)
161 fit(epochs, self.model, self.loss_func, opt=self.opt, data=self.data, metrics=self.metrics,
–> 162 callbacks=self.callbacks+callbacks)
163
164 def create_opt(self, lr:Floats, wd:Floats=0.)->None:

/anaconda/envs/fastai/lib/python3.6/site-packages/fastai/basic_train.py in fit(epochs, model, loss_func, opt, data, callbacks, metrics)
92 except Exception as e:
93 exception = e
—> 94 raise e
95 finally: cb_handler.on_train_end(exception)
96

/anaconda/envs/fastai/lib/python3.6/site-packages/fastai/basic_train.py in fit(epochs, model, loss_func, opt, data, callbacks, metrics)
87 if hasattr(data,‘valid_dl’) and data.valid_dl is not None:
88 val_loss = validate(model, data.valid_dl, loss_func=loss_func,
—> 89 cb_handler=cb_handler, pbar=pbar)
90 else: val_loss=None
91 if cb_handler.on_epoch_end(val_loss): break

/anaconda/envs/fastai/lib/python3.6/site-packages/fastai/basic_train.py in validate(model, dl, loss_func, cb_handler, pbar, average, n_batch)
52 if not is_listy(yb): yb = [yb]
53 nums.append(yb[0].shape[0])
—> 54 if cb_handler and cb_handler.on_batch_end(val_losses[-1]): break
55 if n_batch and (len(nums)>=n_batch): break
56 nums = np.array(nums, dtype=np.float32)

/anaconda/envs/fastai/lib/python3.6/site-packages/fastai/callback.py in on_batch_end(self, loss)
236 “Handle end of processing one batch with `loss`.”
237 self.state_dict[‘last_loss’] = loss
–> 238 stop = np.any(self(‘batch_end’, not self.state_dict[‘train’]))
239 if self.state_dict[‘train’]:
240 self.state_dict[‘iteration’] += 1

/anaconda/envs/fastai/lib/python3.6/site-packages/fastai/callback.py in call(self, cb_name, call_mets, **kwargs)
184 def call(self, cb_name, call_mets=True, **kwargs)->None:
185 “Call through to all of the `CallbakHandler` functions.”
–> 186 if call_mets: [getattr(met, f’on_{cb_name}’)(**self.state_dict, **kwargs) for met in self.metrics]
187 return [getattr(cb, f’on_{cb_name}’)(**self.state_dict, **kwargs) for cb in self.callbacks]
188

/anaconda/envs/fastai/lib/python3.6/site-packages/fastai/callback.py in (.0)
184 def call(self, cb_name, call_mets=True, **kwargs)->None:
185 “Call through to all of the `CallbakHandler` functions.”
–> 186 if call_mets: [getattr(met, f’on_{cb_name}’)(**self.state_dict, **kwargs) for met in self.metrics]
187 return [getattr(cb, f’on_{cb_name}’)(**self.state_dict, **kwargs) for cb in self.callbacks]
188

/anaconda/envs/fastai/lib/python3.6/site-packages/fastai/callback.py in on_batch_end(self, last_output, last_target, train, **kwargs)
269 if not is_listy(last_target): last_target=[last_target]
270 self.count += last_target[0].size(0)
–> 271 self.val += last_target[0].size(0) * self.func(last_output, *last_target).detach().cpu()
272
273 def on_epoch_end(self, **kwargs):

AttributeError: ‘Tensor’ object has no attribute ‘detach’