A tutorial that can be run in Google Colab or on a local machine

Open In Colab

Install fastai2 and timeseries

# Run this cell to install the latest version of fastai shared on github
!pip install git+https://github.com/fastai/fastai2.git
# Run this cell to install the latest version of fastcore shared on github
!pip install git+https://github.com/fastai/fastcore.git
!pip install git+https://github.com/ai-fast-track/timeseries.git
%reload_ext autoreload
%autoreload 2
%matplotlib inline
from fastai2.basics import *
from timeseries.all import *

Downloading and unzipping a time series dataset

dsname =  'NATOPS' #'NATOPS', 'LSST', 'Wine', 'Epilepsy', 'HandMovementDirection'
# url = 'http://www.timeseriesclassification.com/Downloads/NATOPS.zip'
path = unzip_data(URLs_TS.NATOPS)
path
Path('/home/farid/.fastai/data/NATOPS')
fname_train = f'{dsname}_TRAIN.arff'
fname_test = f'{dsname}_TEST.arff'
fnames = [path/fname_train, path/fname_test]
fnames
[Path('/home/farid/.fastai/data/NATOPS/NATOPS_TRAIN.arff'),
 Path('/home/farid/.fastai/data/NATOPS/NATOPS_TEST.arff')]
data = TSData.from_arff(fnames)
print(data)
TSData:
 Datasets names (concatenated): ['NATOPS_TRAIN', 'NATOPS_TEST']
 Filenames:                     [Path('/home/farid/.fastai/data/NATOPS/NATOPS_TRAIN.arff'), Path('/home/farid/.fastai/data/NATOPS/NATOPS_TEST.arff')]
 Data shape: (360, 24, 51)
 Targets shape: (360,)
 Nb Samples: 360
 Nb Channels:           24
 Sequence Length: 51
items = data.get_items()

Creating Dataloaders object

seed = 42
splits = RandomSplitter(seed=seed)(range_of(items)) #by default 80% for train split and 20% for valid split are chosen 
splits
((#288) [304,281,114,329,115,130,338,294,94,310...],
 (#72) [222,27,96,253,274,35,160,172,302,146...])
bs = 128                            
# Normalize at batch time
tfm_norm = Normalize(scale_subtype = 'per_sample_per_channel', scale_range=(0, 1)) # per_sample , per_sample_per_channel
# tfm_norm = Standardize(scale_subtype = 'per_sample')
batch_tfms = [tfm_norm]
default_device()
device(type='cpu')
dls = TSDataLoaders.from_files(fnames=fnames, batch_tfms=batch_tfms, num_workers=0, device=default_device())
dls.show_batch(max_n=9, chs=range(0,12,3))
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-15-3b151a50b534> in <module>
----> 1 dls.show_batch(max_n=9, chs=range(0,12,3))

~/fastai2/fastai2/fastai2/data/core.py in show_batch(self, b, max_n, ctxs, show, **kwargs)
     90         if b is None: b = self.one_batch()
     91         if not show: return self._pre_show_batch(b, max_n=max_n)
---> 92         show_batch(*self._pre_show_batch(b, max_n=max_n), ctxs=ctxs, max_n=max_n, **kwargs)
     93 
     94     def show_results(self, b, out, max_n=9, ctxs=None, show=True, **kwargs):

~/fastai2/fastcore/fastcore/dispatch.py in __call__(self, *args, **kwargs)
     96         if not f: return args[0]
     97         if self.inst is not None: f = MethodType(f, self.inst)
---> 98         return f(*args, **kwargs)
     99 
    100     def __get__(self, inst, owner):

~/fastai2/timeseries/nbs/timeseries/core.py in show_batch(x, y, samples, ctxs, max_n, rows, cols, figsize, title, **kwargs)
    206 @typedispatch
    207 def show_batch(x:TensorTS, y, samples, ctxs=None, max_n=9, rows=None, cols=None, figsize=None, title=None, **kwargs):
--> 208     if ctxs is None: ctxs = get_grid(max_n, rows=rows, cols=cols, figsize=figsize)
    209 
    210     ctxs = default_show_batch(x, y, samples, ctxs=ctxs, max_n=max_n, **kwargs)

~/fastai2/fastai2/fastai2/vision/data.py in get_grid(n, nrows, ncols, add_vert, figsize, double, title, return_fig, **kwargs)
     16     ncols = ncols or int(np.ceil(n/nrows))
     17     if double: ncols*=2 ; n*=2
---> 18     fig,axs = subplots(nrows, ncols, figsize=figsize, **kwargs)
     19     axs = [ax if i<n else ax.set_axis_off() for i, ax in enumerate(axs.flatten())][:n]
     20     if title is not None: fig.suptitle(title, weight='bold', size=14)

~/fastai2/fastai2/fastai2/torch_core.py in subplots(nrows, ncols, figsize, imsize, add_vert, **kwargs)
     29 def subplots(nrows=1, ncols=1, figsize=None, imsize=3, add_vert=0, **kwargs):
     30     if figsize is None: figsize=(ncols*imsize, nrows*imsize+add_vert)
---> 31     fig,ax = plt.subplots(nrows, ncols, figsize=figsize, **kwargs)
     32     if nrows*ncols==1: ax = array([ax])
     33     return fig,ax

~/anaconda3/envs/fastai2_dev/lib/python3.6/site-packages/matplotlib/pyplot.py in subplots(nrows, ncols, sharex, sharey, squeeze, subplot_kw, gridspec_kw, **fig_kw)
   1207 
   1208     """
-> 1209     fig = figure(**fig_kw)
   1210     axs = fig.subplots(nrows=nrows, ncols=ncols, sharex=sharex, sharey=sharey,
   1211                        squeeze=squeeze, subplot_kw=subplot_kw,

~/anaconda3/envs/fastai2_dev/lib/python3.6/site-packages/matplotlib/pyplot.py in figure(num, figsize, dpi, facecolor, edgecolor, frameon, FigureClass, clear, **kwargs)
    543                                         frameon=frameon,
    544                                         FigureClass=FigureClass,
--> 545                                         **kwargs)
    546 
    547         if figLabel:

~/anaconda3/envs/fastai2_dev/lib/python3.6/site-packages/matplotlib/backend_bases.py in new_figure_manager(cls, num, *args, **kwargs)
   3249         from matplotlib.figure import Figure
   3250         fig_cls = kwargs.pop('FigureClass', Figure)
-> 3251         fig = fig_cls(*args, **kwargs)
   3252         return cls.new_figure_manager_given_figure(num, fig)
   3253 

TypeError: __init__() got an unexpected keyword argument 'rows'

Training Model

# Number of channels (i.e. dimensions in ARFF and TS files jargon)
c_in = get_n_channels(dls.train) # data.n_channels
# Number of classes
c_out= dls.c 
c_in,c_out
model = inception_time(c_in, c_out).to(device=default_device())
model
Learner
loss_func = LabelSmoothingCrossEntropy() 
learn = Learner(dls, model, opt_func=Ranger, loss_func=loss_func, metrics=accuracy)

# Or just using default settings thanks to ts_learner()
# learn = ts_learner(dls)

print(learn.summary())
lr_min, lr_steep = learn.lr_find()
lr_min, lr_steep
#lr_max=1e-3
epochs=30; lr_max=lr_steep;  pct_start=.7; moms=(0.95,0.85,0.95); wd=1e-2
learn.fit_one_cycle(epochs, lr_max=lr_max, pct_start=pct_start,  moms=moms, wd=wd)
# learn.fit_one_cycle(epochs, lr_max=lr_steep)

Graphs

learn.recorder.plot_loss()
learn.show_results(max_n=9, chs=range(0,12,3))
interp = ClassificationInterpretation.from_learner(learn)
interp.plot_confusion_matrix()
interp.most_confused()
[('2.0', '3.0', 2), ('2.0', '1.0', 1), ('3.0', '2.0', 1)]