I’m trying to break captcha with fastai. The images contains 4 digits, so I’d like to encoding the target with onehot:
encoding_dict = {l:e for e,l in enumerate("0123456789")}
decoding_dict = {e:l for l,e in encoding_dict.items()}
code_dimension=10 #10=>0-9
captcha_dimension=4 # because we have 5 length captcha
def to_onehot(filepath):
code = filepath.parts[-1].split("_")[0]
onehot = np.zeros((code_dimension, captcha_dimension))
for column, letter in enumerate(code):
onehot[encoding_dict[letter], column] = 1
return onehot.reshape(-1)
and construct datablock this way:
path = "/kaggle/working/sample/"
bearer = DataBlock(blocks=(ImageBlock, RegressionBlock), get_items=get_image_files,get_y=to_onehot)
dls = bearer.dataloaders(source=path)
the learner is:
learner = cnn_learner(dls, resnet18, metrics=error_rate)
learner.fine_tune(1)
However, this will cause the following error:
/opt/conda/lib/python3.7/site-packages/fastai/learner.py in _with_events(self, f, event_type, ex, final)
158
159 def _with_events(self, f, event_type, ex, final=noop):
--> 160 try: self(f'before_{event_type}'); f()
161 except ex: self(f'after_cancel_{event_type}')
162 self(f'after_{event_type}'); final()
/opt/conda/lib/python3.7/site-packages/fastai/learner.py in _do_fit(self)
201 for epoch in range(self.n_epoch):
202 self.epoch=epoch
--> 203 self._with_events(self._do_epoch, 'epoch', CancelEpochException)
204
205 def fit(self, n_epoch, lr=None, wd=None, cbs=None, reset_opt=False):
/opt/conda/lib/python3.7/site-packages/fastai/learner.py in _with_events(self, f, event_type, ex, final)
158
159 def _with_events(self, f, event_type, ex, final=noop):
--> 160 try: self(f'before_{event_type}'); f()
161 except ex: self(f'after_cancel_{event_type}')
162 self(f'after_{event_type}'); final()
/opt/conda/lib/python3.7/site-packages/fastai/learner.py in _do_epoch(self)
196 def _do_epoch(self):
197 self._do_epoch_train()
--> 198 self._do_epoch_validate()
199
200 def _do_fit(self):
/opt/conda/lib/python3.7/site-packages/fastai/learner.py in _do_epoch_validate(self, ds_idx, dl)
192 if dl is None: dl = self.dls[ds_idx]
193 self.dl = dl
--> 194 with torch.no_grad(): self._with_events(self.all_batches, 'validate', CancelValidException)
195
196 def _do_epoch(self):
/opt/conda/lib/python3.7/site-packages/fastai/learner.py in _with_events(self, f, event_type, ex, final)
158
159 def _with_events(self, f, event_type, ex, final=noop):
--> 160 try: self(f'before_{event_type}'); f()
161 except ex: self(f'after_cancel_{event_type}')
162 self(f'after_{event_type}'); final()
/opt/conda/lib/python3.7/site-packages/fastai/learner.py in all_batches(self)
164 def all_batches(self):
165 self.n_iter = len(self.dl)
--> 166 for o in enumerate(self.dl): self.one_batch(*o)
167
168 def _do_one_batch(self):
/opt/conda/lib/python3.7/site-packages/fastai/learner.py in one_batch(self, i, b)
183 b_on_device = tuple( e.to(device=self.dls.device) for e in b if hasattr(e, "to")) if self.dls.device is not None else b
184 self._split(b_on_device)
--> 185 self._with_events(self._do_one_batch, 'batch', CancelBatchException)
186
187 def _do_epoch_train(self):
/opt/conda/lib/python3.7/site-packages/fastai/learner.py in _with_events(self, f, event_type, ex, final)
160 try: self(f'before_{event_type}'); f()
161 except ex: self(f'after_cancel_{event_type}')
--> 162 self(f'after_{event_type}'); final()
163
164 def all_batches(self):
/opt/conda/lib/python3.7/site-packages/fastai/learner.py in __call__(self, event_name)
139
140 def ordered_cbs(self, event): return [cb for cb in self.cbs.sorted('order') if hasattr(cb, event)]
--> 141 def __call__(self, event_name): L(event_name).map(self._call_one)
142
143 def _call_one(self, event_name):
/opt/conda/lib/python3.7/site-packages/fastcore/foundation.py in map(self, f, gen, *args, **kwargs)
152 def range(cls, a, b=None, step=None): return cls(range_of(a, b=b, step=step))
153
--> 154 def map(self, f, *args, gen=False, **kwargs): return self._new(map_ex(self, f, *args, gen=gen, **kwargs))
155 def argwhere(self, f, negate=False, **kwargs): return self._new(argwhere(self, f, negate, **kwargs))
156 def filter(self, f=noop, negate=False, gen=False, **kwargs):
/opt/conda/lib/python3.7/site-packages/fastcore/basics.py in map_ex(iterable, f, gen, *args, **kwargs)
664 res = map(g, iterable)
665 if gen: return res
--> 666 return list(res)
667
668 # Cell
/opt/conda/lib/python3.7/site-packages/fastcore/basics.py in __call__(self, *args, **kwargs)
649 if isinstance(v,_Arg): kwargs[k] = args.pop(v.i)
650 fargs = [args[x.i] if isinstance(x, _Arg) else x for x in self.pargs] + args[self.maxi+1:]
--> 651 return self.func(*fargs, **kwargs)
652
653 # Cell
/opt/conda/lib/python3.7/site-packages/fastai/learner.py in _call_one(self, event_name)
143 def _call_one(self, event_name):
144 if not hasattr(event, event_name): raise Exception(f'missing {event_name}')
--> 145 for cb in self.cbs.sorted('order'): cb(event_name)
146
147 def _bn_bias_state(self, with_bias): return norm_bias_params(self.model, with_bias).map(self.opt.state)
/opt/conda/lib/python3.7/site-packages/fastai/callback/core.py in __call__(self, event_name)
42 (self.run_valid and not getattr(self, 'training', False)))
43 res = None
---> 44 if self.run and _run: res = getattr(self, event_name, noop)()
45 if event_name=='after_fit': self.run=True #Reset self.run to True at each end of fit
46 return res
/opt/conda/lib/python3.7/site-packages/fastai/learner.py in after_batch(self)
493 if len(self.yb) == 0: return
494 mets = self._train_mets if self.training else self._valid_mets
--> 495 for met in mets: met.accumulate(self.learn)
496 if not self.training: return
497 self.lrs.append(self.opt.hypers[-1]['lr'])
/opt/conda/lib/python3.7/site-packages/fastai/learner.py in accumulate(self, learn)
415 def accumulate(self, learn):
416 bs = find_bs(learn.yb)
--> 417 self.total += learn.to_detach(self.func(learn.pred, *learn.yb))*bs
418 self.count += bs
419 @property
/opt/conda/lib/python3.7/site-packages/fastai/metrics.py in error_rate(inp, targ, axis)
103 def error_rate(inp, targ, axis=-1):
104 "1 - `accuracy`"
--> 105 return 1 - accuracy(inp, targ, axis=axis)
106
107 # Cell
/opt/conda/lib/python3.7/site-packages/fastai/metrics.py in accuracy(inp, targ, axis)
97 def accuracy(inp, targ, axis=-1):
98 "Compute accuracy with `targ` when `pred` is bs * n_classes"
---> 99 pred,targ = flatten_check(inp.argmax(dim=axis), targ)
100 return (pred == targ).float().mean()
101
/opt/conda/lib/python3.7/site-packages/fastai/torch_core.py in flatten_check(inp, targ)
799 "Check that `out` and `targ` have the same number of elements and flatten them."
800 inp,targ = TensorBase(inp.contiguous()).view(-1),TensorBase(targ.contiguous()).view(-1)
--> 801 test_eq(len(inp), len(targ))
802 return inp,targ
/opt/conda/lib/python3.7/site-packages/fastcore/test.py in test_eq(a, b)
33 def test_eq(a,b):
34 "`test` that `a==b`"
---> 35 test(a,b,equals, '==')
36
37 # Cell
/opt/conda/lib/python3.7/site-packages/fastcore/test.py in test(a, b, cmp, cname)
23 "`assert` that `cmp(a,b)`; display inputs and `cname or cmp.__name__` if it fails"
24 if cname is None: cname=cmp.__name__
---> 25 assert cmp(a,b),f"{cname}:\n{a}\n{b}"
26
27 # Cell
AssertionError: ==:
64
2560
guess 64 is the size of minibatch, and it implies it want a scalar for target, when the actual target is a 64 * 40 array. But I don’t know how to correct it.
If CategoryBlock is used, then the error will be( raised when construct dataloaders):
/opt/conda/lib/python3.7/site-packages/fastcore/transform.py in setup(self, items, train_setup)
77 def setup(self, items=None, train_setup=False):
78 train_setup = train_setup if self.train_setup is None else self.train_setup
---> 79 return self.setups(getattr(items, 'train', items) if train_setup else items)
80
81 def _call(self, fn, x, split_idx=None, **kwargs):
/opt/conda/lib/python3.7/site-packages/fastcore/dispatch.py in __call__(self, *args, **kwargs)
116 elif self.inst is not None: f = MethodType(f, self.inst)
117 elif self.owner is not None: f = MethodType(f, self.owner)
--> 118 return f(*args, **kwargs)
119
120 def __get__(self, inst, owner):
/opt/conda/lib/python3.7/site-packages/fastai/data/transforms.py in setups(self, dsets)
239
240 def setups(self, dsets):
--> 241 if self.vocab is None and dsets is not None: self.vocab = CategoryMap(dsets, sort=self.sort, add_na=self.add_na)
242 self.c = len(self.vocab)
243
/opt/conda/lib/python3.7/site-packages/fastai/data/transforms.py in __init__(self, col, sort, add_na, strict)
215 if not hasattr(col,'unique'): col = L(col, use_list=True)
216 # `o==o` is the generalized definition of non-NaN used by Pandas
--> 217 items = L(o for o in col.unique() if o==o)
218 if sort: items = items.sorted()
219 self.items = '#na#' + items if add_na else items
/opt/conda/lib/python3.7/site-packages/fastcore/foundation.py in unique(self, sort, bidir, start)
159 def enumerate(self): return L(enumerate(self))
160 def renumerate(self): return L(renumerate(self))
--> 161 def unique(self, sort=False, bidir=False, start=None): return L(uniqueify(self, sort=sort, bidir=bidir, start=start))
162 def val2idx(self): return val2idx(self)
163 def cycle(self): return cycle(self)
/opt/conda/lib/python3.7/site-packages/fastcore/basics.py in uniqueify(x, sort, bidir, start)
571 def uniqueify(x, sort=False, bidir=False, start=None):
572 "Unique elements in `x`, optionally `sort`-ed, optionally return reverse correspondence, optionally prepend with elements."
--> 573 res = list(dict.fromkeys(x))
574 if start is not None: res = listify(start)+res
575 if sort: res.sort()
TypeError: unhashable type: 'numpy.ndarray'