--- title: Callback keywords: fastai sidebar: home_sidebar summary: "Miscellaneous callbacks for timeseriesAI." description: "Miscellaneous callbacks for timeseriesAI." nb_path: "nbs/060_callback.core.ipynb" ---
A callback can implement actions on the following events:
When writing a callback, the following attributes of Learner are available:
The following attributes are added by TrainEvalCallback and should be available unless you went out of your way to remove that callback:
The following attribute is added by Recorder and should be available unless you went out of your way to remove that callback:
from tsai.data.all import *
from tsai.models.InceptionTime import *
from tsai.models.layers import *
dsid = 'NATOPS'
X, y, splits = get_UCR_data(dsid, return_split=False)
tfms = [None, Categorize()]
dsets = TSDatasets(X, y, tfms=tfms, splits=splits)
dls = TSDataLoaders.from_dsets(dsets.train, dsets.valid, bs=[64, 128])
loss_func = gambler_loss()
learn = Learner(dls, InceptionTime(dls.vars, dls.c + 1), loss_func=loss_func, cbs=GamblersCallback, metrics=[accuracy])
learn.fit_one_cycle(1)
TransformScheduler(SchedCos(1, 0))
p = torch.linspace(0.,1,100)
f = combine_scheds([0.3, 0.4, 0.3], [SchedLin(1.,1.), SchedCos(1.,0.), SchedLin(0.,.0), ])
plt.plot(p, [f(o) for o in p]);
p = torch.linspace(0.,1,100)
f = combine_scheds([0.3, 0.7], [SchedCos(0.,1.), SchedCos(1.,0.)])
plt.plot(p, [f(o) for o in p]);
from tsai.data.all import *
from tsai.models.all import *
dsid = 'NATOPS'
X, y, splits = get_UCR_data(dsid, return_split=False)
tfms = [None, Categorize()]
dsets = TSDatasets(X, y, tfms=tfms, splits=splits)
dls = TSDataLoaders.from_dsets(dsets.train, dsets.valid, batch_tfms=[TSStandardize()])
model = create_model(InceptionTime, dls=dls)
TS_tfms = [TSMagScale(.75, p=.5), TSMagWarp(.1, p=0.5), TSWindowWarp(.25, p=.5),
TSSmooth(p=0.5), TSRandomResizedCrop(.1, p=.5),
TSRandomCropPad(.3, p=0.5),
TSMagAddNoise(.5, p=.5)]
ubda_cb = UBDAug(TS_tfms, N=2, C=4, S=2)
learn = Learner(dls, model, cbs=ubda_cb, metrics=accuracy)
learn.fit_one_cycle(1)
This process shows an example of how the weights could be calculated. This particular regression method was published in:
Yang, Y., Zha, K., Chen, Y. C., Wang, H., & Katabi, D. (2021). Delving into Deep Imbalanced Regression. arXiv preprint arXiv:2102.09554.
(https://arxiv.org/pdf/2102.09554.pdf)
def _prepare_weights(self, reweight, max_target=51, lds=False, lds_kernel='gaussian', lds_ks=5, lds_sigma=2):
assert reweight in {'none', 'inverse', 'sqrt_inv'}
assert reweight != 'none' if lds else True, \
"Set reweight to \'sqrt_inv\' (default) or \'inverse\' when using LDS"
value_dict = {x: 0 for x in range(max_target)}
labels = self.data[:, -1].tolist()
# mbr
for label in labels:
value_dict[min(max_target - 1, int(label))] += 1
if reweight == 'sqrt_inv':
value_dict = {k: np.sqrt(v) for k, v in value_dict.items()}
elif reweight == 'inverse':
value_dict = {k: np.clip(v, 5, 1000) for k, v in value_dict.items()} # clip weights for inverse re-weight
num_per_label = [value_dict[min(max_target - 1, int(label))] for label in labels]
if not len(num_per_label) or reweight == 'none':
return None
print(f"Using re-weighting: [{reweight.upper()}]")
if lds:
lds_kernel_window = get_lds_kernel_window(lds_kernel, lds_ks, lds_sigma)
print(f'Using LDS: [{lds_kernel.upper()}] ({lds_ks}/{lds_sigma})')
smoothed_value = convolve1d(
np.asarray([v for _, v in value_dict.items()]), weights=lds_kernel_window, mode='constant')
num_per_label = [smoothed_value[min(max_target - 1, int(label))] for label in labels]
weights = [np.float32(1 / x) for x in num_per_label]
scaling = len(weights) / np.sum(weights)
weights = [scaling * x for x in weights]
print(weights)
return weights
labels = np.concatenate([np.random.normal(-20, 1, 10), np.random.normal(0, 2, 100), np.random.normal(12, 2, 300)], -1)
labels[(-1<labels) & (labels<1)] = 0 # This is done to create some 'gaps' for demo purposes
labels[(10<labels) & (labels<12)] = 0 # This is done to create some 'gaps' for demo purposes
n_bins = 50
label_range=None
reweight = 'inv'
lds_kernel='gaussian'
lds_ks=5
lds_sigma=2
weights_per_sample = prepare_weights(labels, n_bins, label_range=label_range, reweight=reweight,
lds_kernel=lds_kernel, lds_ks=lds_ks, lds_sigma=lds_sigma, show_plot=True)
n_bins = 50
label_range=None
reweight = 'sqrt_inv'
lds_kernel='gaussian'
lds_ks=5
lds_sigma=2
weights_per_sample = prepare_weights(labels, n_bins, label_range=label_range, reweight=reweight,
lds_kernel=lds_kernel, lds_ks=lds_ks, lds_sigma=lds_sigma, show_plot=True)
n_bins = None
label_range=None
reweight = 'sqrt_inv'
lds_kernel='triang'
lds_ks=9
lds_sigma=1
weights_per_sample = prepare_weights(labels, n_bins, label_range=label_range, reweight=reweight,
lds_kernel=lds_kernel, lds_ks=lds_ks, lds_sigma=lds_sigma, show_plot=True)
This loss will allow you to pass a different weight per individual sample.