import { Recorder, SingleRecord } from "./recording";
/**
* Data Property, parameter of constructor describing the number of
* classes the model should have.
*/
export interface DataProperties {
/**
* The number of class for labels and model output, 1 or 2 for binary classification.
*/
numClasses?: 1 | 2;
}
/**
* An abstract class that extracts some mouse features from {@link recording!Recorder}
* and format them with {@link loadDataSet} to create an input of a tf.js model.
* This input is an array, but you can call {@link tf.tensor3d} and {@link tf.reshape}
* to get the tensor. It is always a 3D tensor, each element of the dataset being a matrix
* {@link xSize} x {@link ySize}.
*
* You can also specify an integer `userIndex` to work with labels for training.
* While dataset is a 3D array with the first dimension representing the size of the dataset,
* labels are represented by a 2D array with the same first dimension and the second one
* is the label of the corresponding sample.
*
* The field {@link numClasses} can be 1 or 2. You can ignore it and let the default value to 2.
* If you want more details: as 1, if a model is constructed with `delbot-training`, it
* will have a single neuron as output and `binaryCrossentropy` loss function, each label
* during the training will be a singleton [0] or [1] for respectively human and bot, the
* model then outputs the probability [p] for the sample to be a bot. If there are two classes,
* the loss function is `categoricalCrossentropy` for two neurons, the labels are [1,0] or
* [0,1] for respectively human and bot samples and outputs from the model are [1-p,p] where p
* is the probability to be a bot.
*
* Extend this class and implement the method {@link loadDataSet} to create your own logic and
* data format. Your implementation has to look something like 1. empty data and label
* arrays, 2. iterate through {@link recording!Recorder.getRecords} and 3. add labels userIndex is positive.
* You can also check if {@link recording!SingleRecord.type} is null or includes "Move" to filter only
* move actions.
*/
export declare abstract class Data {
/**
* The number of class for labels and model output, 1 or 2 for binary classification.
*/
readonly numClasses: 1 | 2;
/**
* The second shape of all 3d tensors (or first in case we ignore the batch size), defined in subclasses.
* @protected
*/
protected xSize: number;
/**
* The third shape of 3d tensor (or second in case we ignore the batch size), defined in subclasses.
* @protected
*/
protected ySize: number;
/**
* Boolean to know if we may normalize data. If false, then
* data must not be normalized, otherwise some operations
* of the model will fail.
*/
protected mayNormalizeData: boolean;
protected constructor(args?: DataProperties);
/**
* Gets the current array of labels from a dataset and append a new
* label according to the number of classes {@link numClasses}.
* If there is one class, [0] means human and [1] bot while with
* two classes, [1,0] means human and [0,1] bot.
* @param datasetLabels The current dataset label array, we add an element to it.
* @param userIndex The index of the class, 0 for human and 1 for bot.
* @protected
*/
protected addLabel(datasetLabels: number[][], userIndex: number): void;
/**
* This method gets a recorder object and loads it as a Dataset object
* with the right format. The return value might contain empty arrays if the
* recorder as too few elements. The userIndex is an integer that says what is the
* class index for the label, in our case of binary classifier human-bot, 0 means
* human and 1 means bot.
* @param recorder The recorder containing loaded records and features.
* @param userIndex The index of the class from record, if unspecified or negative,
* the label array of the return object is empty.
*/
abstract loadDataSet(recorder: Recorder, userIndex?: number): {
datasetData: number[][][];
datasetLabels: number[][];
};
getXSize(): number;
getYSize(): number;
mayNormalize(): boolean;
}
/**
* Properties for {@link DataMovementMatrix} constructor, containing all
* previous features of {@link DataProperties} and six new parameters.
*/
export interface DataMovementMatrixProperties extends DataProperties {
xMinMov?: number;
xMaxMov?: number;
yMinMov?: number;
yMaxMov?: number;
neighbourRange?: number;
steps?: number[];
}
/**
* A Data class that represents a movement matrix. For each step N of {@link steps}
* we create a 0-matrix {@link xMaxMov}-{@link xMinMov} x {@link yMaxMov}-{@link yMinMov}
* and add a small number at position (dx,dy) for at most N trajectories, where
* dx = x(n) - x(n-1) is the pixel offset in x coordinate between two recorded movements
* in the trajectory. We repeat that until there are no sample left, then for the next N.
*
* If a value should be outside the matrix, we put it on the edge. The default size
* is 50x50 (range -25 to 25) and default steps are [25, 50, 100, 150, 200, 250].
* @see Data
*/
export declare class DataMovementMatrix extends Data {
protected readonly xMinMov: number;
protected readonly xMaxMov: number;
protected readonly yMinMov: number;
protected readonly yMaxMov: number;
protected readonly neighbourRange: number;
protected readonly steps: number[];
constructor(args?: DataMovementMatrixProperties);
/**
* Create a new empty 0-matrix of size xSize times ySize.
* @private
*/
private newEmptyData;
/**
* Force the value to stand in `[0, max-min[` for index of matrix, so
* min is the first index 0 and max the last index. If the value is
* greater than max or less than min, we consider the bound.
* @param min An integer, lower bound of initial domain.
* @param max An integer, upper bound of initial domain.
* @param value An integer, the value to constraint.
* @return The value in the new integer domain starting from 0.
* @private
*/
private getInRangeForArray;
/**
* Get integer neighbours of the given value within a distance of range and
* return a list of unique elements of this neighbourhood (in case the value
* is on an edge, there will be less than range squared values).
* @private
*/
private getNeighbour;
loadDataSet(recorder: Recorder, userIndex?: number): {
datasetData: number[][][];
datasetLabels: number[][];
};
}
/**
* Properties for {@link DataFeatures} constructor, containing all
* previous features of {@link DataProperties} and two new parameters.
*/
export interface DataFeaturesProperties extends DataProperties {
/**
* The second shape of all 3d tensors (or first in case we ignore the batch size), representing
* here the chunk length. The last shape is arbitrary, given by the number of mouse features
* for each chunk.
*/
xSize?: number;
/**
* In case that a chunk is not fully complete after reading the
* record, this field describes whether we should complete it manually
* with trailing zeros.
*/
shouldCompleteXSize?: boolean;
}
/**
* A Data class that represents chunks of mouse features selected from
* the {@link recording!Recorder} object. The field {@link xSize} is the chunk size,
* default to 24, and {@link ySize} the number of extracted features.
*
* The dataset there is a list of chunks of mouse features.
*
* It can be the case that a chunk is not fully complete after reading the
* record, if the field {@link shouldCompleteXSize} is set to true, we complete
* it with trailing zeros.
*
* This class takes 8 features :
*