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 : *
    *
  1. {@link recording!SingleRecord.dx}
  2. *
  3. {@link recording!SingleRecord.dy}
  4. *
  5. {@link recording!SingleRecord.speedX}
  6. *
  7. {@link recording!SingleRecord.speedY}
  8. *
  9. {@link recording!SingleRecord.speed}
  10. *
  11. {@link recording!SingleRecord.accel}
  12. *
  13. {@link recording!SingleRecord.distance}
  14. *
  15. {@link recording!SingleRecord.timeDiff}
  16. *
* @see Data */ export declare class DataFeatures extends Data { protected readonly shouldCompleteXSize: boolean; constructor(args?: DataFeaturesProperties); /** * Return a new chunk element with arbitrary chosen mouse features from * the record. * @param line The line of the record with calculated mouse features. * @protected */ protected getChunkElement(line: SingleRecord): number[]; loadDataSet(recorder: Recorder, userIndex?: number): { datasetData: number[][][]; datasetLabels: number[][]; }; } /** * This class extends {@link DataFeatures} and takes 10 features : *
    *
  1. {@link recording!SingleRecord.dx}
  2. *
  3. {@link recording!SingleRecord.dy}
  4. *
  5. {@link recording!SingleRecord.speedX}
  6. *
  7. {@link recording!SingleRecord.speedY}
  8. *
  9. {@link recording!SingleRecord.speed}
  10. *
  11. {@link recording!SingleRecord.accel}
  12. *
  13. {@link recording!SingleRecord.distance}
  14. *
  15. {@link recording!SingleRecord.timeDiff}
  16. *
  17. {@link recording!SingleRecord.jerk}
  18. *
  19. {@link recording!SingleRecord.angle}
  20. *
* @see DataFeatures */ export declare class DataFeatures2 extends DataFeatures { constructor(args?: DataFeaturesProperties); protected getChunkElement(line: SingleRecord): number[]; } /** * This class extends {@link DataFeatures} and takes 2 features : *
    *
  1. {@link recording!SingleRecord.x}
  2. *
  3. {@link recording!SingleRecord.y}
  4. *
* @see DataFeatures */ export declare class DataSimplePosition extends DataFeatures { constructor(args?: DataFeaturesProperties); protected getChunkElement(line: SingleRecord): number[]; } /** * This class extends {@link DataFeatures} and takes 2 features : *
    *
  1. {@link recording!SingleRecord.dx}
  2. *
  3. {@link recording!SingleRecord.dy}
  4. *
* @see DataFeatures */ export declare class DataOffsetPosition extends DataFeatures { constructor(args?: DataFeaturesProperties); protected getChunkElement(line: SingleRecord): number[]; }