I am having some newbie struggles with DataBlock, Learner, and .predict
for a model that has multiple inputs. Basically, my model takes a few (3) different multi-dimensional tensors as inputs and I pass them in as a tuple, so I have something like:
db = DataBlock(blocks = (RegressionBlock(3),RegressionBlock(1)),
get_items=get_files,
get_x=get_x,
splitter=RandomSplitter(valid_pct=0.2, seed=42),
get_y=get_y)
get_x
returns a tuple with with the 3 tensors. get_y
returns a single tensor. Training works fine (it runs), but when I try to predict, e.g. with something like:
testpath = Path.home()/"simdata"/"simple_dataset"/"000352.pkl"
testx = get_x(testpath)
rec = learn.predict(testx)
I get an error:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-19-0af0ad1a70d0> in <module>
----> 1 rec = learn.predict(testx)
~/.conda/envs/ai/lib/python3.8/site-packages/fastai/learner.py in predict(self, item, rm_type_tfms, with_input)
249 i = getattr(self.dls, 'n_inp', -1)
250 inp = (inp,) if i==1 else tuplify(inp)
--> 251 dec = self.dls.decode_batch(inp + tuplify(dec_preds))[0]
252 dec_inp,dec_targ = map(detuplify, [dec[:i],dec[i:]])
253 res = dec_targ,dec_preds[0],preds[0]
~/.conda/envs/ai/lib/python3.8/site-packages/fastai/data/core.py in decode_batch(self, b, max_n, full)
79
80 def decode(self, b): return self.before_batch.decode(to_cpu(self.after_batch.decode(self._retain_dl(b))))
---> 81 def decode_batch(self, b, max_n=9, full=True): return self._decode_batch(self.decode(b), max_n, full)
82
83 def _decode_batch(self, b, max_n=9, full=True):
~/.conda/envs/ai/lib/python3.8/site-packages/fastai/data/core.py in _decode_batch(self, b, max_n, full)
84 f = self.after_item.decode
85 f = compose(f, partial(getattr(self.dataset,'decode',noop), full = full))
---> 86 return L(batch_to_samples(b, max_n=max_n)).map(f)
87
88 def _pre_show_batch(self, b, max_n=9):
~/.conda/envs/ai/lib/python3.8/site-packages/fastcore/foundation.py in map(self, f, *args, **kwargs)
394 else f.format if isinstance(f,str)
395 else f.__getitem__)
--> 396 return self._new(map(g, self))
397
398 def filter(self, f, negate=False, **kwargs):
~/.conda/envs/ai/lib/python3.8/site-packages/fastcore/foundation.py in _new(self, items, *args, **kwargs)
340 @property
341 def _xtra(self): return None
--> 342 def _new(self, items, *args, **kwargs): return type(self)(items, *args, use_list=None, **kwargs)
343 def __getitem__(self, idx): return self._get(idx) if is_indexer(idx) else L(self._get(idx), use_list=None)
344 def copy(self): return self._new(self.items.copy())
~/.conda/envs/ai/lib/python3.8/site-packages/fastcore/foundation.py in __call__(cls, x, *args, **kwargs)
49 return x
50
---> 51 res = super().__call__(*((x,) + args), **kwargs)
52 res._newchk = 0
53 return res
~/.conda/envs/ai/lib/python3.8/site-packages/fastcore/foundation.py in __init__(self, items, use_list, match, *rest)
331 if items is None: items = []
332 if (use_list is not None) or not _is_array(items):
--> 333 items = list(items) if use_list else _listify(items)
334 if match is not None:
335 if is_coll(match): match = len(match)
~/.conda/envs/ai/lib/python3.8/site-packages/fastcore/foundation.py in _listify(o)
244 if isinstance(o, list): return o
245 if isinstance(o, str) or _is_array(o): return [o]
--> 246 if is_iter(o): return list(o)
247 return [o]
248
~/.conda/envs/ai/lib/python3.8/site-packages/fastcore/foundation.py in __call__(self, *args, **kwargs)
307 if isinstance(v,_Arg): kwargs[k] = args.pop(v.i)
308 fargs = [args[x.i] if isinstance(x, _Arg) else x for x in self.pargs] + args[self.maxi+1:]
--> 309 return self.fn(*fargs, **kwargs)
310
311 # Cell
~/.conda/envs/ai/lib/python3.8/site-packages/fastcore/utils.py in _inner(x, *args, **kwargs)
389 if order is not None: funcs = funcs.sorted(order)
390 def _inner(x, *args, **kwargs):
--> 391 for f in L(funcs): x = f(x, *args, **kwargs)
392 return x
393 return _inner
~/.conda/envs/ai/lib/python3.8/site-packages/fastai/data/core.py in decode(self, o, full)
320 def __iter__(self): return (self[i] for i in range(len(self)))
321 def __repr__(self): return coll_repr(self)
--> 322 def decode(self, o, full=True): return tuple(tl.decode(o_, full=full) for o_,tl in zip(o,tuplify(self.tls, match=o)))
323 def subset(self, i): return type(self)(tls=L(tl.subset(i) for tl in self.tls), n_inp=self.n_inp)
324 def _new(self, items, *args, **kwargs): return super()._new(items, tfms=self.tfms, do_setup=False, **kwargs)
~/.conda/envs/ai/lib/python3.8/site-packages/fastai/data/core.py in <genexpr>(.0)
320 def __iter__(self): return (self[i] for i in range(len(self)))
321 def __repr__(self): return coll_repr(self)
--> 322 def decode(self, o, full=True): return tuple(tl.decode(o_, full=full) for o_,tl in zip(o,tuplify(self.tls, match=o)))
323 def subset(self, i): return type(self)(tls=L(tl.subset(i) for tl in self.tls), n_inp=self.n_inp)
324 def _new(self, items, *args, **kwargs): return super()._new(items, tfms=self.tfms, do_setup=False, **kwargs)
~/.conda/envs/ai/lib/python3.8/site-packages/fastai/data/core.py in decode(self, o, **kwargs)
244 def __iter__(self): return (self[i] for i in range(len(self)))
245 def show(self, o, **kwargs): return self.tfms.show(o, **kwargs)
--> 246 def decode(self, o, **kwargs): return self.tfms.decode(o, **kwargs)
247 def __call__(self, o, **kwargs): return self.tfms.__call__(o, **kwargs)
248 def overlapping_splits(self): return L(Counter(self.splits.concat()).values()).filter(gt(1))
~/.conda/envs/ai/lib/python3.8/site-packages/fastcore/transform.py in decode(self, o, full)
203
204 def decode (self, o, full=True):
--> 205 if full: return compose_tfms(o, tfms=self.fs, is_enc=False, reverse=True, split_idx=self.split_idx)
206 #Not full means we decode up to the point the item knows how to show itself.
207 for f in reversed(self.fs):
~/.conda/envs/ai/lib/python3.8/site-packages/fastcore/transform.py in compose_tfms(x, tfms, is_enc, reverse, **kwargs)
147 for f in tfms:
148 if not is_enc: f = f.decode
--> 149 x = f(x, **kwargs)
150 return x
151
~/.conda/envs/ai/lib/python3.8/site-packages/fastcore/transform.py in decode(self, x, **kwargs)
71 def name(self): return getattr(self, '_name', _get_name(self))
72 def __call__(self, x, **kwargs): return self._call('encodes', x, **kwargs)
---> 73 def decode (self, x, **kwargs): return self._call('decodes', x, **kwargs)
74 def __repr__(self): return f'{self.name}:\nencodes: {self.encodes}decodes: {self.decodes}'
75
~/.conda/envs/ai/lib/python3.8/site-packages/fastcore/transform.py in _call(self, fn, x, split_idx, **kwargs)
80 def _call(self, fn, x, split_idx=None, **kwargs):
81 if split_idx!=self.split_idx and self.split_idx is not None: return x
---> 82 return self._do_call(getattr(self, fn), x, **kwargs)
83
84 def _do_call(self, f, x, **kwargs):
~/.conda/envs/ai/lib/python3.8/site-packages/fastcore/transform.py in _do_call(self, f, x, **kwargs)
87 ret = f.returns_none(x) if hasattr(f,'returns_none') else None
88 return retain_type(f(x, **kwargs), x, ret)
---> 89 res = tuple(self._do_call(f, x_, **kwargs) for x_ in x)
90 return retain_type(res, x)
91
~/.conda/envs/ai/lib/python3.8/site-packages/fastcore/transform.py in <genexpr>(.0)
87 ret = f.returns_none(x) if hasattr(f,'returns_none') else None
88 return retain_type(f(x, **kwargs), x, ret)
---> 89 res = tuple(self._do_call(f, x_, **kwargs) for x_ in x)
90 return retain_type(res, x)
91
~/.conda/envs/ai/lib/python3.8/site-packages/fastcore/transform.py in _do_call(self, f, x, **kwargs)
86 if f is None: return x
87 ret = f.returns_none(x) if hasattr(f,'returns_none') else None
---> 88 return retain_type(f(x, **kwargs), x, ret)
89 res = tuple(self._do_call(f, x_, **kwargs) for x_ in x)
90 return retain_type(res, x)
~/.conda/envs/ai/lib/python3.8/site-packages/fastcore/dispatch.py in __call__(self, *args, **kwargs)
108 if not f: return args[0]
109 if self.inst is not None: f = MethodType(f, self.inst)
--> 110 return f(*args, **kwargs)
111
112 def __get__(self, inst, owner):
~/.conda/envs/ai/lib/python3.8/site-packages/fastai/data/transforms.py in decodes(self, o)
295
296 def encodes(self, o): return tensor(o).float()
--> 297 def decodes(self, o): return TitledFloat(o) if o.ndim==0 else TitledTuple(o_.item() for o_ in o)
298 def setups(self, dsets):
299 if self.c is not None: return
~/.conda/envs/ai/lib/python3.8/site-packages/fastcore/utils.py in __new__(cls, x, *rest)
276 if len(rest): x = (x,)
277 else:
--> 278 try: x = tuple(iter(x))
279 except TypeError: x = (x,)
280 return super().__new__(cls, x+rest if rest else x)
~/.conda/envs/ai/lib/python3.8/site-packages/fastai/data/transforms.py in <genexpr>(.0)
295
296 def encodes(self, o): return tensor(o).float()
--> 297 def decodes(self, o): return TitledFloat(o) if o.ndim==0 else TitledTuple(o_.item() for o_ in o)
298 def setups(self, dsets):
299 if self.c is not None: return
ValueError: only one element tensors can be converted to Python scalars
I’m struggling to make sense of the error, so I am hoping somebody else might make sense of it.