warner-benjamin / fastxtend

Train fastai models faster (and other useful tools)

Home Page:https://fastxtend.benjaminwarner.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

deepcopy exception occurred while running lr_find

csaroff opened this issue · comments

Great library! I had actually independently implemented some of the loss utilities that you wrote. Glad to see them in a public repo with better names.

Unfortunately, when I try to load the packages with from fastxtend.vision.all import *, running learn.lr_find fails because it attempts to deepcopy learn.dls.

Here's the headline of the stacktrace:

RuntimeError: Exception occured in `LRFinder` when calling event `before_fit`:
        The default implementation of __deepcopy__() for non-wrapper subclasses only works for subclass types that 
implement new_empty() and for which that function returns another instance of the same subclass. You should either 
properly implement new_empty() for your subclass or override __deepcopy__() if it is intended behavior for 
new_empty() to return an instance of a different type.
> /home/csaroff/.miniconda3/lib/python3.9/site-packages/torch/_tensor.py(185)__deepcopy__()
    183                     new_tensor = self.new_empty([])
    184                     if type(new_tensor) is not type(self):
--> 185                         raise RuntimeError(
    186                             "The default implementation of __deepcopy__() for non-wrapper subclasses "
    187                             "only works for subclass types that implement new_empty() and for which "

I tried opening the debugger and it seems like targ_pts is unable to be deepcopied.

I wasn't sure if you've run into this before and might have some insight. In case it's helpful, I'm running fastai version 2.7.11 and fastxtend version 0.0.18.

>>> fastai.__version__
'2.7.11'
tor>>> torch.__version__
'1.13.1+cu116'
>>> fastxtend.__version__
'0.0.18'

I also tried downgrading to 2.7.10, but had the same issue.

Full Stacktrace

╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ <ipython-input-19-c2db1576f5af>:14 in <cell line: 14>                                            │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/site-packages/fastxtend/callback/lr_finder.py:81 in      │
│ lr_find                                                                                          │
│                                                                                                  │
│    78 │   """                                                                                    │
│    79 │   n_epoch = num_it//len(self.dls.train) + 1                                              │
│    80 │   cb=LRFinder(start_lr=start_lr, end_lr=end_lr, num_it=num_it, stop_div=stop_div,resto   │
│ ❱  81 │   with self.no_logging(): self.fit(n_epoch, cbs=cb)                                      │
│    82 │   if suggest_funcs is not None:                                                          │
│    83 │   │   lrs, losses = tensor(self.recorder.lrs[num_it//10:-5]), tensor(self.recorder.los   │
│    84 │   │   nan_idxs = torch.nonzero(torch.isnan(losses.view(-1)))                             │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/site-packages/fastai/learner.py:264 in fit               │
│                                                                                                  │
│   261 │   │   │   if wd is not None: self.opt.set_hypers(wd=wd)                                  │
│   262 │   │   │   self.opt.set_hypers(lr=self.lr if lr is None else lr)                          │
│   263 │   │   │   self.n_epoch = n_epoch                                                         │
│ ❱ 264 │   │   │   self._with_events(self._do_fit, 'fit', CancelFitException, self._end_cleanup   │
│   265 │                                                                                          │
│   266 │   def _end_cleanup(self): self.dl,self.xb,self.yb,self.pred,self.loss = None,(None,),(   │
│   267 │   def __enter__(self): self(_before_epoch); return self                                  │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/site-packages/fastai/learner.py:199 in _with_events      │
│                                                                                                  │
│   196 │   │   self.xb,self.yb = b[:i],b[i:]                                                      │
│   197 │                                                                                          │
│   198 │   def _with_events(self, f, event_type, ex, final=noop):                                 │
│ ❱ 199 │   │   try: self(f'before_{event_type}');  f()                                            │
│   200 │   │   except ex: self(f'after_cancel_{event_type}')                                      │
│   201 │   │   self(f'after_{event_type}');  final()                                              │
│   202                                                                                            │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/site-packages/fastai/learner.py:172 in __call__          │
│                                                                                                  │
│   169 │   │   finally: self.add_cbs(cbs)                                                         │
│   170 │                                                                                          │
│   171 │   def ordered_cbs(self, event): return [cb for cb in self.cbs.sorted('order') if hasat   │
│ ❱ 172 │   def __call__(self, event_name): L(event_name).map(self._call_one)                      │
│   173 │                                                                                          │
│   174 │   def _call_one(self, event_name):                                                       │
│   175 │   │   if not hasattr(event, event_name): raise Exception(f'missing {event_name}')        │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/site-packages/fastcore/foundation.py:156 in map          │
│                                                                                                  │
│   153 │   @classmethod                                                                           │
│   154 │   def range(cls, a, b=None, step=None): return cls(range_of(a, b=b, step=step))          │
│   155 │                                                                                          │
│ ❱ 156 │   def map(self, f, *args, gen=False, **kwargs): return self._new(map_ex(self, f, *args   │
│   157 │   def argwhere(self, f, negate=False, **kwargs): return self._new(argwhere(self, f, ne   │
│   158 │   def argfirst(self, f, negate=False): return first(i for i,o in self.enumerate() if f   │
│   159 │   def filter(self, f=noop, negate=False, gen=False, **kwargs):                           │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/site-packages/fastcore/basics.py:840 in map_ex           │
│                                                                                                  │
│    837 │   │    else f.__getitem__)                                                              │
│    838 │   res = map(g, iterable)                                                                │
│    839 │   if gen: return res                                                                    │
│ ❱  840 │   return list(res)                                                                      │
│    841                                                                                           │
│    842 # %% ../nbs/01_basics.ipynb 336                                                           │
│    843 def compose(*funcs, order=None):                                                          │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/site-packages/fastcore/basics.py:825 in __call__         │
│                                                                                                  │
│    822 │   │   for k,v in kwargs.items():                                                        │
│    823 │   │   │   if isinstance(v,_Arg): kwargs[k] = args.pop(v.i)                              │
│    824 │   │   fargs = [args[x.i] if isinstance(x, _Arg) else x for x in self.pargs] + args[sel  │
│ ❱  825 │   │   return self.func(*fargs, **kwargs)                                                │
│    826                                                                                           │
│    827 # %% ../nbs/01_basics.ipynb 326                                                           │
│    828 def mapt(func, *iterables):                                                               │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/site-packages/fastai/learner.py:176 in _call_one         │
│                                                                                                  │
│   173 │                                                                                          │
│   174 │   def _call_one(self, event_name):                                                       │
│   175 │   │   if not hasattr(event, event_name): raise Exception(f'missing {event_name}')        │
│ ❱ 176 │   │   for cb in self.cbs.sorted('order'): cb(event_name)                                 │
│   177 │                                                                                          │
│   178 │   def _bn_bias_state(self, with_bias): return norm_bias_params(self.model, with_bias).   │
│   179                                                                                            │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/site-packages/fastai/callback/core.py:62 in __call__     │
│                                                                                                  │
│    59 │   │   if self.run and _run:                                                              │
│    60 │   │   │   try: res = getcallable(self, event_name)()                                     │
│    61 │   │   │   except (CancelBatchException, CancelBackwardException, CancelEpochException,   │
│ ❱  62 │   │   │   except Exception as e: raise modify_exception(e, f'Exception occured in `{se   │
│    63 │   │   if event_name=='after_fit': self.run=True #Reset self.run to True at each end of   │
│    64 │   │   return res                                                                         │
│    65                                                                                            │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/site-packages/fastai/callback/core.py:60 in __call__     │
│                                                                                                  │
│    57 │   │   │      (self.run_valid and not getattr(self, 'training', False)))                  │
│    58 │   │   res = None                                                                         │
│    59 │   │   if self.run and _run:                                                              │
│ ❱  60 │   │   │   try: res = getcallable(self, event_name)()                                     │
│    61 │   │   │   except (CancelBatchException, CancelBackwardException, CancelEpochException,   │
│    62 │   │   │   except Exception as e: raise modify_exception(e, f'Exception occured in `{se   │
│    63 │   │   if event_name=='after_fit': self.run=True #Reset self.run to True at each end of   │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/site-packages/fastxtend/callback/lr_finder.py:36 in      │
│ before_fit                                                                                       │
│                                                                                                  │
│    33 │   │   "Initialize container for hyper-parameters and save the model & optimizer, optio   │
│    34 │   │   super().before_fit()                                                               │
│    35 │   │   if self.restore_state:                                                             │
│ ❱  36 │   │   │   self.old_dls = deepcopy(self.learn.dls)                                        │
│    37 │   │   │   self.states = get_random_states()                                              │
│    38 │   │   path = self.path/self.model_dir                                                    │
│    39 │   │   path.mkdir(parents=True, exist_ok=True)                                            │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/copy.py:172 in deepcopy                                  │
│                                                                                                  │
│   169 │   │   │   │   if isinstance(rv, str):                                                    │
│   170 │   │   │   │   │   y = x                                                                  │
│   171 │   │   │   │   else:                                                                      │
│ ❱ 172 │   │   │   │   │   y = _reconstruct(x, memo, *rv)                                         │
│   173 │                                                                                          │
│   174 │   # If is its own copy, don't memoize.                                                   │
│   175 │   if y is not x:                                                                         │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/copy.py:270 in _reconstruct                              │
│                                                                                                  │
│   267 │                                                                                          │
│   268 │   if state is not None:                                                                  │
│   269 │   │   if deep:                                                                           │
│ ❱ 270 │   │   │   state = deepcopy(state, memo)                                                  │
│   271 │   │   if hasattr(y, '__setstate__'):                                                     │
│   272 │   │   │   y.__setstate__(state)                                                          │
│   273 │   │   else:                                                                              │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/copy.py:146 in deepcopy                                  │
│                                                                                                  │
│   143 │                                                                                          │
│   144 │   copier = _deepcopy_dispatch.get(cls)                                                   │
│   145 │   if copier is not None:                                                                 │
│ ❱ 146 │   │   y = copier(x, memo)                                                                │
│   147 │   else:                                                                                  │
│   148 │   │   if issubclass(cls, type):                                                          │
│   149 │   │   │   y = _deepcopy_atomic(x, memo)                                                  │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/copy.py:230 in _deepcopy_dict                            │
│                                                                                                  │
│   227 │   y = {}                                                                                 │
│   228 │   memo[id(x)] = y                                                                        │
│   229 │   for key, value in x.items():                                                           │
│ ❱ 230 │   │   y[deepcopy(key, memo)] = deepcopy(value, memo)                                     │
│   231 │   return y                                                                               │
│   232 d[dict] = _deepcopy_dict                                                                   │
│   233 if PyStringMap is not None:                                                                │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/copy.py:146 in deepcopy                                  │
│                                                                                                  │
│   143 │                                                                                          │
│   144 │   copier = _deepcopy_dispatch.get(cls)                                                   │
│   145 │   if copier is not None:                                                                 │
│ ❱ 146 │   │   y = copier(x, memo)                                                                │
│   147 │   else:                                                                                  │
│   148 │   │   if issubclass(cls, type):                                                          │
│   149 │   │   │   y = _deepcopy_atomic(x, memo)                                                  │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/copy.py:205 in _deepcopy_list                            │
│                                                                                                  │
│   202 │   memo[id(x)] = y                                                                        │
│   203 │   append = y.append                                                                      │
│   204 │   for a in x:                                                                            │
│ ❱ 205 │   │   append(deepcopy(a, memo))                                                          │
│   206 │   return y                                                                               │
│   207 d[list] = _deepcopy_list                                                                   │
│   208                                                                                            │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/copy.py:172 in deepcopy                                  │
│                                                                                                  │
│   169 │   │   │   │   if isinstance(rv, str):                                                    │
│   170 │   │   │   │   │   y = x                                                                  │
│   171 │   │   │   │   else:                                                                      │
│ ❱ 172 │   │   │   │   │   y = _reconstruct(x, memo, *rv)                                         │
│   173 │                                                                                          │
│   174 │   # If is its own copy, don't memoize.                                                   │
│   175 │   if y is not x:                                                                         │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/copy.py:270 in _reconstruct                              │
│                                                                                                  │
│   267 │                                                                                          │
│   268 │   if state is not None:                                                                  │
│   269 │   │   if deep:                                                                           │
│ ❱ 270 │   │   │   state = deepcopy(state, memo)                                                  │
│   271 │   │   if hasattr(y, '__setstate__'):                                                     │
│   272 │   │   │   y.__setstate__(state)                                                          │
│   273 │   │   else:                                                                              │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/copy.py:146 in deepcopy                                  │
│                                                                                                  │
│   143 │                                                                                          │
│   144 │   copier = _deepcopy_dispatch.get(cls)                                                   │
│   145 │   if copier is not None:                                                                 │
│ ❱ 146 │   │   y = copier(x, memo)                                                                │
│   147 │   else:                                                                                  │
│   148 │   │   if issubclass(cls, type):                                                          │
│   149 │   │   │   y = _deepcopy_atomic(x, memo)                                                  │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/copy.py:230 in _deepcopy_dict                            │
│                                                                                                  │
│   227 │   y = {}                                                                                 │
│   228 │   memo[id(x)] = y                                                                        │
│   229 │   for key, value in x.items():                                                           │
│ ❱ 230 │   │   y[deepcopy(key, memo)] = deepcopy(value, memo)                                     │
│   231 │   return y                                                                               │
│   232 d[dict] = _deepcopy_dict                                                                   │
│   233 if PyStringMap is not None:                                                                │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/copy.py:172 in deepcopy                                  │
│                                                                                                  │
│   169 │   │   │   │   if isinstance(rv, str):                                                    │
│   170 │   │   │   │   │   y = x                                                                  │
│   171 │   │   │   │   else:                                                                      │
│ ❱ 172 │   │   │   │   │   y = _reconstruct(x, memo, *rv)                                         │
│   173 │                                                                                          │
│   174 │   # If is its own copy, don't memoize.                                                   │
│   175 │   if y is not x:                                                                         │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/copy.py:270 in _reconstruct                              │
│                                                                                                  │
│   267 │                                                                                          │
│   268 │   if state is not None:                                                                  │
│   269 │   │   if deep:                                                                           │
│ ❱ 270 │   │   │   state = deepcopy(state, memo)                                                  │
│   271 │   │   if hasattr(y, '__setstate__'):                                                     │
│   272 │   │   │   y.__setstate__(state)                                                          │
│   273 │   │   else:                                                                              │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/copy.py:146 in deepcopy                                  │
│                                                                                                  │
│   143 │                                                                                          │
│   144 │   copier = _deepcopy_dispatch.get(cls)                                                   │
│   145 │   if copier is not None:                                                                 │
│ ❱ 146 │   │   y = copier(x, memo)                                                                │
│   147 │   else:                                                                                  │
│   148 │   │   if issubclass(cls, type):                                                          │
│   149 │   │   │   y = _deepcopy_atomic(x, memo)                                                  │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/copy.py:230 in _deepcopy_dict                            │
│                                                                                                  │
│   227 │   y = {}                                                                                 │
│   228 │   memo[id(x)] = y                                                                        │
│   229 │   for key, value in x.items():                                                           │
│ ❱ 230 │   │   y[deepcopy(key, memo)] = deepcopy(value, memo)                                     │
│   231 │   return y                                                                               │
│   232 d[dict] = _deepcopy_dict                                                                   │
│   233 if PyStringMap is not None:                                                                │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/copy.py:172 in deepcopy                                  │
│                                                                                                  │
│   169 │   │   │   │   if isinstance(rv, str):                                                    │
│   170 │   │   │   │   │   y = x                                                                  │
│   171 │   │   │   │   else:                                                                      │
│ ❱ 172 │   │   │   │   │   y = _reconstruct(x, memo, *rv)                                         │
│   173 │                                                                                          │
│   174 │   # If is its own copy, don't memoize.                                                   │
│   175 │   if y is not x:                                                                         │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/copy.py:270 in _reconstruct                              │
│                                                                                                  │
│   267 │                                                                                          │
│   268 │   if state is not None:                                                                  │
│   269 │   │   if deep:                                                                           │
│ ❱ 270 │   │   │   state = deepcopy(state, memo)                                                  │
│   271 │   │   if hasattr(y, '__setstate__'):                                                     │
│   272 │   │   │   y.__setstate__(state)                                                          │
│   273 │   │   else:                                                                              │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/copy.py:146 in deepcopy                                  │
│                                                                                                  │
│   143 │                                                                                          │
│   144 │   copier = _deepcopy_dispatch.get(cls)                                                   │
│   145 │   if copier is not None:                                                                 │
│ ❱ 146 │   │   y = copier(x, memo)                                                                │
│   147 │   else:                                                                                  │
│   148 │   │   if issubclass(cls, type):                                                          │
│   149 │   │   │   y = _deepcopy_atomic(x, memo)                                                  │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/copy.py:230 in _deepcopy_dict                            │
│                                                                                                  │
│   227 │   y = {}                                                                                 │
│   228 │   memo[id(x)] = y                                                                        │
│   229 │   for key, value in x.items():                                                           │
│ ❱ 230 │   │   y[deepcopy(key, memo)] = deepcopy(value, memo)                                     │
│   231 │   return y                                                                               │
│   232 d[dict] = _deepcopy_dict                                                                   │
│   233 if PyStringMap is not None:                                                                │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/copy.py:146 in deepcopy                                  │
│                                                                                                  │
│   143 │                                                                                          │
│   144 │   copier = _deepcopy_dispatch.get(cls)                                                   │
│   145 │   if copier is not None:                                                                 │
│ ❱ 146 │   │   y = copier(x, memo)                                                                │
│   147 │   else:                                                                                  │
│   148 │   │   if issubclass(cls, type):                                                          │
│   149 │   │   │   y = _deepcopy_atomic(x, memo)                                                  │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/copy.py:205 in _deepcopy_list                            │
│                                                                                                  │
│   202 │   memo[id(x)] = y                                                                        │
│   203 │   append = y.append                                                                      │
│   204 │   for a in x:                                                                            │
│ ❱ 205 │   │   append(deepcopy(a, memo))                                                          │
│   206 │   return y                                                                               │
│   207 d[list] = _deepcopy_list                                                                   │
│   208                                                                                            │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/copy.py:172 in deepcopy                                  │
│                                                                                                  │
│   169 │   │   │   │   if isinstance(rv, str):                                                    │
│   170 │   │   │   │   │   y = x                                                                  │
│   171 │   │   │   │   else:                                                                      │
│ ❱ 172 │   │   │   │   │   y = _reconstruct(x, memo, *rv)                                         │
│   173 │                                                                                          │
│   174 │   # If is its own copy, don't memoize.                                                   │
│   175 │   if y is not x:                                                                         │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/copy.py:270 in _reconstruct                              │
│                                                                                                  │
│   267 │                                                                                          │
│   268 │   if state is not None:                                                                  │
│   269 │   │   if deep:                                                                           │
│ ❱ 270 │   │   │   state = deepcopy(state, memo)                                                  │
│   271 │   │   if hasattr(y, '__setstate__'):                                                     │
│   272 │   │   │   y.__setstate__(state)                                                          │
│   273 │   │   else:                                                                              │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/copy.py:146 in deepcopy                                  │
│                                                                                                  │
│   143 │                                                                                          │
│   144 │   copier = _deepcopy_dispatch.get(cls)                                                   │
│   145 │   if copier is not None:                                                                 │
│ ❱ 146 │   │   y = copier(x, memo)                                                                │
│   147 │   else:                                                                                  │
│   148 │   │   if issubclass(cls, type):                                                          │
│   149 │   │   │   y = _deepcopy_atomic(x, memo)                                                  │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/copy.py:230 in _deepcopy_dict                            │
│                                                                                                  │
│   227 │   y = {}                                                                                 │
│   228 │   memo[id(x)] = y                                                                        │
│   229 │   for key, value in x.items():                                                           │
│ ❱ 230 │   │   y[deepcopy(key, memo)] = deepcopy(value, memo)                                     │
│   231 │   return y                                                                               │
│   232 d[dict] = _deepcopy_dict                                                                   │
│   233 if PyStringMap is not None:                                                                │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/copy.py:172 in deepcopy                                  │
│                                                                                                  │
│   169 │   │   │   │   if isinstance(rv, str):                                                    │
│   170 │   │   │   │   │   y = x                                                                  │
│   171 │   │   │   │   else:                                                                      │
│ ❱ 172 │   │   │   │   │   y = _reconstruct(x, memo, *rv)                                         │
│   173 │                                                                                          │
│   174 │   # If is its own copy, don't memoize.                                                   │
│   175 │   if y is not x:                                                                         │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/copy.py:270 in _reconstruct                              │
│                                                                                                  │
│   267 │                                                                                          │
│   268 │   if state is not None:                                                                  │
│   269 │   │   if deep:                                                                           │
│ ❱ 270 │   │   │   state = deepcopy(state, memo)                                                  │
│   271 │   │   if hasattr(y, '__setstate__'):                                                     │
│   272 │   │   │   y.__setstate__(state)                                                          │
│   273 │   │   else:                                                                              │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/copy.py:146 in deepcopy                                  │
│                                                                                                  │
│   143 │                                                                                          │
│   144 │   copier = _deepcopy_dispatch.get(cls)                                                   │
│   145 │   if copier is not None:                                                                 │
│ ❱ 146 │   │   y = copier(x, memo)                                                                │
│   147 │   else:                                                                                  │
│   148 │   │   if issubclass(cls, type):                                                          │
│   149 │   │   │   y = _deepcopy_atomic(x, memo)                                                  │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/copy.py:230 in _deepcopy_dict                            │
│                                                                                                  │
│   227 │   y = {}                                                                                 │
│   228 │   memo[id(x)] = y                                                                        │
│   229 │   for key, value in x.items():                                                           │
│ ❱ 230 │   │   y[deepcopy(key, memo)] = deepcopy(value, memo)                                     │
│   231 │   return y                                                                               │
│   232 d[dict] = _deepcopy_dict                                                                   │
│   233 if PyStringMap is not None:                                                                │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/copy.py:146 in deepcopy                                  │
│                                                                                                  │
│   143 │                                                                                          │
│   144 │   copier = _deepcopy_dispatch.get(cls)                                                   │
│   145 │   if copier is not None:                                                                 │
│ ❱ 146 │   │   y = copier(x, memo)                                                                │
│   147 │   else:                                                                                  │
│   148 │   │   if issubclass(cls, type):                                                          │
│   149 │   │   │   y = _deepcopy_atomic(x, memo)                                                  │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/copy.py:205 in _deepcopy_list                            │
│                                                                                                  │
│   202 │   memo[id(x)] = y                                                                        │
│   203 │   append = y.append                                                                      │
│   204 │   for a in x:                                                                            │
│ ❱ 205 │   │   append(deepcopy(a, memo))                                                          │
│   206 │   return y                                                                               │
│   207 d[list] = _deepcopy_list                                                                   │
│   208                                                                                            │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/copy.py:172 in deepcopy                                  │
│                                                                                                  │
│   169 │   │   │   │   if isinstance(rv, str):                                                    │
│   170 │   │   │   │   │   y = x                                                                  │
│   171 │   │   │   │   else:                                                                      │
│ ❱ 172 │   │   │   │   │   y = _reconstruct(x, memo, *rv)                                         │
│   173 │                                                                                          │
│   174 │   # If is its own copy, don't memoize.                                                   │
│   175 │   if y is not x:                                                                         │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/copy.py:270 in _reconstruct                              │
│                                                                                                  │
│   267 │                                                                                          │
│   268 │   if state is not None:                                                                  │
│   269 │   │   if deep:                                                                           │
│ ❱ 270 │   │   │   state = deepcopy(state, memo)                                                  │
│   271 │   │   if hasattr(y, '__setstate__'):                                                     │
│   272 │   │   │   y.__setstate__(state)                                                          │
│   273 │   │   else:                                                                              │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/copy.py:146 in deepcopy                                  │
│                                                                                                  │
│   143 │                                                                                          │
│   144 │   copier = _deepcopy_dispatch.get(cls)                                                   │
│   145 │   if copier is not None:                                                                 │
│ ❱ 146 │   │   y = copier(x, memo)                                                                │
│   147 │   else:                                                                                  │
│   148 │   │   if issubclass(cls, type):                                                          │
│   149 │   │   │   y = _deepcopy_atomic(x, memo)                                                  │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/copy.py:230 in _deepcopy_dict                            │
│                                                                                                  │
│   227 │   y = {}                                                                                 │
│   228 │   memo[id(x)] = y                                                                        │
│   229 │   for key, value in x.items():                                                           │
│ ❱ 230 │   │   y[deepcopy(key, memo)] = deepcopy(value, memo)                                     │
│   231 │   return y                                                                               │
│   232 d[dict] = _deepcopy_dict                                                                   │
│   233 if PyStringMap is not None:                                                                │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/copy.py:153 in deepcopy                                  │
│                                                                                                  │
│   150 │   │   else:                                                                              │
│   151 │   │   │   copier = getattr(x, "__deepcopy__", None)                                      │
│   152 │   │   │   if copier is not None:                                                         │
│ ❱ 153 │   │   │   │   y = copier(memo)                                                           │
│   154 │   │   │   else:                                                                          │
│   155 │   │   │   │   reductor = dispatch_table.get(cls)                                         │
│   156 │   │   │   │   if reductor:                                                               │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/site-packages/torch/_tensor.py:100 in __deepcopy__       │
│                                                                                                  │
│     97 class Tensor(torch._C._TensorBase):                                                       │
│     98 │   def __deepcopy__(self, memo):                                                         │
│     99 │   │   if has_torch_function_unary(self):                                                │
│ ❱  100 │   │   │   return handle_torch_function(Tensor.__deepcopy__, (self,), self, memo)        │
│    101 │   │   if not self.is_leaf:                                                              │
│    102 │   │   │   raise RuntimeError(                                                           │
│    103 │   │   │   │   "Only Tensors created explicitly by the user "                            │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/site-packages/torch/overrides.py:1534 in                 │
│ handle_torch_function                                                                            │
│                                                                                                  │
│   1531 │   │                                                                                     │
│   1532 │   │   # Use `public_api` instead of `implementation` so __torch_function__              │
│   1533 │   │   # implementations can do equality/identity comparisons.                           │
│ ❱ 1534 │   │   result = torch_func_method(public_api, types, args, kwargs)                       │
│   1535 │   │                                                                                     │
│   1536 │   │   if result is not NotImplemented:                                                  │
│   1537 │   │   │   return result                                                                 │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/site-packages/fastai/torch_core.py:372 in                │
│ __torch_function__                                                                               │
│                                                                                                  │
│   369 │   def __torch_function__(cls, func, types, args=(), kwargs=None):                        │
│   370 │   │   if cls.debug and func.__name__ not in ('__str__','__repr__'): print(func, types,   │
│   371 │   │   if _torch_handled(args, cls._opt, func): types = (torch.Tensor,)                   │
│ ❱ 372 │   │   res = super().__torch_function__(func, types, args, ifnone(kwargs, {}))            │
│   373 │   │   dict_objs = _find_args(args) if args else _find_args(list(kwargs.values()))        │
│   374 │   │   if issubclass(type(res),TensorBase) and dict_objs: res.set_meta(dict_objs[0],as_   │
│   375 │   │   elif dict_objs and is_listy(res): [r.set_meta(dict_objs[0],as_copy=True) for r i   │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/site-packages/torch/_tensor.py:1279 in                   │
│ __torch_function__                                                                               │
│                                                                                                  │
│   1276 │   │   │   return NotImplemented                                                         │
│   1277 │   │                                                                                     │
│   1278 │   │   with _C.DisableTorchFunction():                                                   │
│ ❱ 1279 │   │   │   ret = func(*args, **kwargs)                                                   │
│   1280 │   │   │   if func in get_default_nowrap_functions():                                    │
│   1281 │   │   │   │   return ret                                                                │
│   1282 │   │   │   else:                                                                         │
│                                                                                                  │
│ /home/csaroff/.miniconda3/lib/python3.9/site-packages/torch/_tensor.py:185 in __deepcopy__       │
│                                                                                                  │
│    182 │   │   │   │   else:                                                                     │
│    183 │   │   │   │   │   new_tensor = self.new_empty([])                                       │
│    184 │   │   │   │   │   if type(new_tensor) is not type(self):                                │
│ ❱  185 │   │   │   │   │   │   raise RuntimeError(                                               │
│    186 │   │   │   │   │   │   │   "The default implementation of __deepcopy__() for non-wrappe  │
│    187 │   │   │   │   │   │   │   "only works for subclass types that implement new_empty() an  │
│    188 │   │   │   │   │   │   │   "that function returns another instance of the same subclass  │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
RuntimeError: Exception occured in `LRFinder` when calling event `before_fit`:
        The default implementation of __deepcopy__() for non-wrapper subclasses only works for subclass types that 
implement new_empty() and for which that function returns another instance of the same subclass. You should either 
properly implement new_empty() for your subclass or override __deepcopy__() if it is intended behavior for 
new_empty() to return an instance of a different type.
> /home/csaroff/.miniconda3/lib/python3.9/site-packages/torch/_tensor.py(185)__deepcopy__()
    183                     new_tensor = self.new_empty([])
    184                     if type(new_tensor) is not type(self):
--> 185                         raise RuntimeError(
    186                             "The default implementation of __deepcopy__() for non-wrapper subclasses "
    187                             "only works for subclass types that implement new_empty() and for which "

PDB Debugger Session

ipdb> up
> /home/csaroff/.miniconda3/lib/python3.9/site-packages/torch/_tensor.py(1279)__torch_function__()
   1277 
   1278         with _C.DisableTorchFunction():
-> 1279             ret = func(*args, **kwargs)
   1280             if func in get_default_nowrap_functions():
   1281                 return ret

ipdb> up
> /home/csaroff/.miniconda3/lib/python3.9/site-packages/fastai/torch_core.py(372)__torch_function__()
    370         if cls.debug and func.__name__ not in ('__str__','__repr__'): print(func, types, args, kwargs)
    371         if _torch_handled(args, cls._opt, func): types = (torch.Tensor,)
--> 372         res = super().__torch_function__(func, types, args, ifnone(kwargs, {}))
    373         dict_objs = _find_args(args) if args else _find_args(list(kwargs.values()))
    374         if issubclass(type(res),TensorBase) and dict_objs: res.set_meta(dict_objs[0],as_copy=True)

ipdb> up
> /home/csaroff/.miniconda3/lib/python3.9/site-packages/torch/overrides.py(1534)handle_torch_function()
   1532         # Use `public_api` instead of `implementation` so __torch_function__
   1533         # implementations can do equality/identity comparisons.
-> 1534         result = torch_func_method(public_api, types, args, kwargs)
   1535 
   1536         if result is not NotImplemented:

ipdb> p result
*** NameError: name 'result' is not defined
ipdb> up
> /home/csaroff/.miniconda3/lib/python3.9/site-packages/torch/_tensor.py(100)__deepcopy__()
     98     def __deepcopy__(self, memo):
     99         if has_torch_function_unary(self):
--> 100             return handle_torch_function(Tensor.__deepcopy__, (self,), self, memo)
    101         if not self.is_leaf:
    102             raise RuntimeError(

ipdb> p self
TensorBase([[[-1., -1.],
             [-1.,  1.],
             [ 1., -1.],
             [ 1.,  1.]]], device='cuda:0')
ipdb> p self.name
None
ipdb> up
> /home/csaroff/.miniconda3/lib/python3.9/copy.py(153)deepcopy()
    151             copier = getattr(x, "__deepcopy__", None)
    152             if copier is not None:
--> 153                 y = copier(memo)
    154             else:
    155                 reductor = dispatch_table.get(cls)

ipdb> p memo
*** AttributeError: fs
ipdb> p copier
<bound method Tensor.__deepcopy__ of TensorBase([[[-1., -1.],
             [-1.,  1.],
             [ 1., -1.],
             [ 1.,  1.]]], device='cuda:0')>
ipdb> up
> /home/csaroff/.miniconda3/lib/python3.9/copy.py(230)_deepcopy_dict()
    228     memo[id(x)] = y
    229     for key, value in x.items():
--> 230         y[deepcopy(key, memo)] = deepcopy(value, memo)
    231     return y
    232 d[dict] = _deepcopy_dict

ipdb> p key
'targ_pts'
ipdb> p value
TensorBase([[[-1., -1.],
             [-1.,  1.],
             [ 1., -1.],
             [ 1.,  1.]]], device='cuda:0')
ipdb> 

Thanks for the kind words.

If you pass restore_state=False to fastxtend's Learner.lr_find, it should behave exactly like the fastai version of lr_find and skip the deepcopy (and also skip restoring the random state).

I was able to recreate the error if I pass aug_transforms to a fastai DataLoader's batch_tfms. The PyTorch error message and related code suggests that the issue might be with fastai's TensorBase not correctly implementing required methods for deepcopy to work, but I need to investigate further.

Perfect! Now I can import * again. Thanks!

fastai/fastai#3882 should resolve this issue in the next release of fastai.