15
15
class MiniRocket (BaseCollectionTransformer ):
16
16
"""MINImally RandOm Convolutional KErnel Transform (MiniRocket).
17
17
18
- MiniRocket [1]_ is an almost deterministic version of Rocket. It creates
19
- convolutions of length 9 with weights restricted to two values, and uses 84 fixed
20
- convolutions with six of one weight, three of the second weight to seed dilations.
18
+ MiniRocket [1]_ is an almost deterministic version of Rocket. It creates
19
+ convolutions of length 9 with weights restricted to two values, and uses 84 fixed
20
+ convolutions with six of one weight, three of the second weight to seed dilations.
21
21
22
22
23
23
Parameters
24
24
----------
25
- num_kernels : int, default=10,000
26
- Number of random convolutional kernels.
27
- max_dilations_per_kernel : int, default=32
28
- Maximum number of dilations per kernel.
29
- n_jobs : int, default=1
30
- The number of jobs to run in parallel for `transform`. ``-1`` means using all
31
- processors.
32
- random_state : None or int, default = None
33
- Seed for random number generation.
25
+ num_kernels : int, default=10,000
26
+ Number of random convolutional kernels. The number of kernels used is rounded
27
+ down to the nearest multiple of 84, unless a value of less than 84 is passec,
28
+ in which case it is set to 84.
29
+ max_dilations_per_kernel : int, default=32
30
+ Maximum number of dilations per kernel.
31
+ n_jobs : int, default=1
32
+ The number of jobs to run in parallel for `transform`. ``-1`` means using all
33
+ processors.
34
+ random_state : None or int, default = None
35
+ Seed for random number generation.
36
+
37
+ Attributes
38
+ ----------
39
+ self.parameters : Tuple (int32[:], int32[:], int32[:], int32[:], float32[:])
40
+ n_channels_per_comb, channel_indices, dilations, n_features_per_dilation,
41
+ biases
34
42
35
43
See Also
36
44
--------
37
- MiniRocket, Rocket
45
+ Rocket, MultiRocket, Hydra
38
46
39
47
References
40
48
----------
41
- .. [1] Dempster, Angus and Schmidt, Daniel F and Webb, Geoffrey I,
42
- "MINIROCKET: A Very Fast (Almost) Deterministic Transform for Time Series
43
- Classification",2020,
44
- https://dl.acm.org/doi/abs/10.1145/3447548.3467231,
45
- https://arxiv.org/abs/2012.08791
49
+ .. [1] Dempster, Angus and Schmidt, Daniel F and Webb, Geoffrey I,
50
+ "MINIROCKET: A Very Fast (Almost) Deterministic Transform for Time Series
51
+ Classification",2020,
52
+ https://dl.acm.org/doi/abs/10.1145/3447548.3467231,
53
+ https://arxiv.org/abs/2012.08791
54
+
55
+ Notes
56
+ -----
57
+ Directly adapted from the original implementation
58
+ https://github.com/angus924/minirocket.
46
59
47
60
Examples
48
61
--------
@@ -101,8 +114,12 @@ def _fit(self, X, y=None):
101
114
" zero pad shorter series so that n_timepoints == 9"
102
115
)
103
116
X = X .astype (np .float32 )
117
+ if self .num_kernels < 84 :
118
+ self .num_kernels_ = 84
119
+ else :
120
+ self .num_kernels_ = self .num_kernels
104
121
self .parameters = _static_fit (
105
- X , self .num_kernels , self .max_dilations_per_kernel , random_state
122
+ X , self .num_kernels_ , self .max_dilations_per_kernel , random_state
106
123
)
107
124
return self
108
125
@@ -128,7 +145,11 @@ def _transform(self, X, y=None):
128
145
else :
129
146
n_jobs = self .n_jobs
130
147
set_num_threads (n_jobs )
131
- X_ = _static_transform (X , self .parameters , MiniRocket ._indices )
148
+ if n_channels == 1 :
149
+ X = X .squeeze (1 )
150
+ X_ = _static_transform_uni (X , self .parameters , MiniRocket ._indices )
151
+ else :
152
+ X_ = _static_transform_multi (X , self .parameters , MiniRocket ._indices )
132
153
set_num_threads (prev_threads )
133
154
return X_
134
155
@@ -215,15 +236,82 @@ def _PPV(a, b):
215
236
return 0
216
237
217
238
239
+ @njit (
240
+ "float32[:,:](float32[:,:],Tuple((int32[:],int32[:],int32[:],int32[:],float32["
241
+ ":])), int32[:,:])" ,
242
+ fastmath = True ,
243
+ parallel = True ,
244
+ cache = True ,
245
+ )
246
+ def _static_transform_uni (X , parameters , indices ):
247
+ """Transform a 2D collection of univariate time series.
248
+
249
+ Implemented separately to the multivariate version for numba efficiency reasons.
250
+ See issue #1778.
251
+ """
252
+ n_cases , n_timepoints = X .shape
253
+ (
254
+ _ ,
255
+ _ ,
256
+ dilations ,
257
+ n_features_per_dilation ,
258
+ biases ,
259
+ ) = parameters
260
+ n_kernels = len (indices )
261
+ n_dilations = len (dilations )
262
+ f = n_kernels * np .sum (n_features_per_dilation )
263
+ features = np .zeros ((n_cases , f ), dtype = np .float32 )
264
+ for i in prange (n_cases ):
265
+ _X = X [i ]
266
+ A = - _X
267
+ G = 3 * _X
268
+ f_start = 0
269
+ for j in range (n_dilations ):
270
+ _padding0 = j % 2
271
+ dilation = dilations [j ]
272
+ padding = (8 * dilation ) // 2
273
+ n_features = n_features_per_dilation [j ]
274
+ C_alpha = np .zeros (n_timepoints , dtype = np .float32 )
275
+ C_alpha [:] = A
276
+ C_gamma = np .zeros ((9 , n_timepoints ), dtype = np .float32 )
277
+ C_gamma [4 ] = G
278
+ start = dilation
279
+ end = n_timepoints - padding
280
+ for gamma_index in range (4 ):
281
+ C_alpha [- end :] = C_alpha [- end :] + A [:end ]
282
+ C_gamma [gamma_index , - end :] = G [:end ]
283
+ end += dilation
284
+ for gamma_index in range (5 , 9 ):
285
+ C_alpha [:- start ] = C_alpha [:- start ] + A [start :]
286
+ C_gamma [gamma_index , :- start ] = G [start :]
287
+ start += dilation
288
+ for k in range (n_kernels ):
289
+ f_end = f_start + n_features
290
+ _padding1 = (_padding0 + k ) % 2
291
+ a , b , c = indices [k ]
292
+ C = C_alpha + C_gamma [a ] + C_gamma [b ] + C_gamma [c ]
293
+ if _padding1 == 0 :
294
+ for f in range (n_features ):
295
+ features [i , f_start + f ] = _PPV (C , biases [f_start + f ]).mean ()
296
+ else :
297
+ for f in range (n_features ):
298
+ features [i , f_start + f ] = _PPV (
299
+ C [padding :- padding ], biases [f_start + f ]
300
+ ).mean ()
301
+
302
+ f_start = f_end
303
+ return features
304
+
305
+
218
306
@njit (
219
307
"float32[:,:](float32[:,:,:],Tuple((int32[:],int32[:],int32[:],int32[:],float32["
220
308
":])), int32[:,:])" ,
221
309
fastmath = True ,
222
310
parallel = True ,
223
311
cache = True ,
224
312
)
225
- def _static_transform (X , parameters , indices ):
226
- n_cases , n_columns , n_timepoints = X .shape
313
+ def _static_transform_multi (X , parameters , indices ):
314
+ n_cases , n_channels , n_timepoints = X .shape
227
315
(
228
316
n_channels_per_combination ,
229
317
channel_indices ,
@@ -235,68 +323,62 @@ def _static_transform(X, parameters, indices):
235
323
n_dilations = len (dilations )
236
324
n_features = n_kernels * np .sum (n_features_per_dilation )
237
325
features = np .zeros ((n_cases , n_features ), dtype = np .float32 )
238
- for example_index in prange (n_cases ):
239
- _X = X [example_index ]
240
- A = - _X # A = alpha * X = -X
241
- G = _X + _X + _X # G = gamma * X = 3X
242
- feature_index_start = 0
243
- combination_index = 0
326
+ for i in prange (n_cases ):
327
+ _X = X [i ]
328
+ A = - _X
329
+ G = 3 * _X
330
+ f_start = 0
331
+ comb = 0
244
332
n_channels_start = 0
245
- for dilation_index in range (n_dilations ):
246
- _padding0 = dilation_index % 2
247
- dilation = dilations [dilation_index ]
248
- padding = (( 9 - 1 ) * dilation ) // 2
249
- n_features_this_dilation = n_features_per_dilation [dilation_index ]
250
- C_alpha = np .zeros ((n_columns , n_timepoints ), dtype = np .float32 )
333
+ for j in range (n_dilations ):
334
+ _padding0 = j % 2
335
+ dilation = dilations [j ]
336
+ padding = (8 * dilation ) // 2
337
+ n_features_this_dilation = n_features_per_dilation [j ]
338
+ C_alpha = np .zeros ((n_channels , n_timepoints ), dtype = np .float32 )
251
339
C_alpha [:] = A
252
- C_gamma = np .zeros ((9 , n_columns , n_timepoints ), dtype = np .float32 )
253
- C_gamma [9 // 2 ] = G
340
+ C_gamma = np .zeros ((9 , n_channels , n_timepoints ), dtype = np .float32 )
341
+ C_gamma [4 ] = G
254
342
start = dilation
255
343
end = n_timepoints - padding
256
- for gamma_index in range (9 // 2 ):
344
+ for gamma_index in range (4 ):
257
345
C_alpha [:, - end :] = C_alpha [:, - end :] + A [:, :end ]
258
346
C_gamma [gamma_index , :, - end :] = G [:, :end ]
259
347
end += dilation
260
348
261
- for gamma_index in range (9 // 2 + 1 , 9 ):
349
+ for gamma_index in range (5 , 9 ):
262
350
C_alpha [:, :- start ] = C_alpha [:, :- start ] + A [:, start :]
263
351
C_gamma [gamma_index , :, :- start ] = G [:, start :]
264
352
start += dilation
265
353
266
354
for kernel_index in range (n_kernels ):
267
- feature_index_end = feature_index_start + n_features_this_dilation
268
- n_channels_this_combination = n_channels_per_combination [
269
- combination_index
270
- ]
271
- num_channels_end = n_channels_start + n_channels_this_combination
272
- channels_this_combination = channel_indices [
273
- n_channels_start :num_channels_end
274
- ]
355
+ f_end = f_start + n_features_this_dilation
356
+ n_channels_this_combo = n_channels_per_combination [comb ]
357
+ n_channels_end = n_channels_start + n_channels_this_combo
358
+ channels_this_combo = channel_indices [n_channels_start :n_channels_end ]
275
359
_padding1 = (_padding0 + kernel_index ) % 2
276
360
index_0 , index_1 , index_2 = indices [kernel_index ]
277
361
C = (
278
- C_alpha [channels_this_combination ]
279
- + C_gamma [index_0 ][channels_this_combination ]
280
- + C_gamma [index_1 ][channels_this_combination ]
281
- + C_gamma [index_2 ][channels_this_combination ]
362
+ C_alpha [channels_this_combo ]
363
+ + C_gamma [index_0 ][channels_this_combo ]
364
+ + C_gamma [index_1 ][channels_this_combo ]
365
+ + C_gamma [index_2 ][channels_this_combo ]
282
366
)
283
367
C = np .sum (C , axis = 0 )
284
368
if _padding1 == 0 :
285
369
for feature_count in range (n_features_this_dilation ):
286
- features [example_index , feature_index_start + feature_count ] = (
287
- _PPV ( C , biases [feature_index_start + feature_count ]). mean ()
288
- )
370
+ features [i , f_start + feature_count ] = _PPV (
371
+ C , biases [f_start + feature_count ]
372
+ ). mean ()
289
373
else :
290
374
for feature_count in range (n_features_this_dilation ):
291
- features [example_index , feature_index_start + feature_count ] = (
292
- _PPV (
293
- C [padding :- padding ],
294
- biases [feature_index_start + feature_count ],
295
- ).mean ()
296
- )
297
- feature_index_start = feature_index_end
298
- combination_index += 1
299
- n_channels_start = num_channels_end
375
+ features [i , f_start + feature_count ] = _PPV (
376
+ C [padding :- padding ],
377
+ biases [f_start + feature_count ],
378
+ ).mean ()
379
+ f_start = f_end
380
+ comb += 1
381
+ n_channels_start = n_channels_end
300
382
return features
301
383
302
384
0 commit comments