UNPKG

nrn-ml

Version:

Core ML library for the NRN ecosystem

418 lines (402 loc) 19 kB
/** Represents a one-dimensional numeric array. */ type Vector = number[]; /** Represents a two-dimensional numeric matrix. */ type Matrix = number[][]; /** Probability output from multi-headed models. */ type Probabilities = Record<string, Matrix>; /** Generic type for activation functions. */ type ActivationFunction = (x: Matrix, derivativeBool?: boolean) => Matrix; /** Represents the models types offered from NRN ML. */ type ModelType = "neural-network" | "simple"; /** Represents the type of actions for a model head. */ type ActionType = "discrete" | "continuous"; /** Represents the activation function for a model head. */ type ActionActivationType = "linear" | "softmax" | "tanh" | "sigmoid"; /** Represents the valid policy options. */ type Policy = "argmaxPolicy" | "probabilisticSampling"; /** Represents the configuration a model's action head */ type ActionHeadMetadata = { policyMapping: Policy; order: string[]; actionType?: ActionType; activationName?: ActionActivationType; }; /** Represents the raw configuration (when creating a new model) base for all model types */ interface RawModelConfigBase { inputDim: number; actionOrder: string[] | string[][]; actionNames?: string | string[]; actionTypes?: ActionType | ActionType[]; actionActivations?: ActionActivationType | ActionActivationType[]; actionPolicies?: Policy | Policy[]; multiheadBool?: boolean; } /** Represents the formatted configuration (when loading in a model) base for all model types */ interface FormattedModelConfigBase { inputDim?: number; actionHeads: string[]; actionMetadata: Record<string, ActionHeadMetadata>; multiheadBool?: boolean; } /** Represents a model's action metadata configuration for all heads. */ type ActionMetadata = Record<string, ActionHeadMetadata>; /** Represents the output from a discrete action head. */ type ActionOutputDiscrete = Record<string, boolean>; /** Represents the output from a continuous action head. */ type ActionOutputContinuous = Record<string, number>; /** Represents the output from a generic action head. */ type ActionOutput = ActionOutputDiscrete | ActionOutputContinuous; /** Represents the combined output from multiple action heads */ type CombinedActionOutput = Record<string, boolean | number>; /** Represents a base model type which is used in many NRN model architectures. */ interface BaseModel<T> { /** The names of the action heads. */ outputGroups: string[]; /** * Computes probabilities for each output group. * @param state - The input for the model (Matrix for neural nets | number for simple model). * @returns Probabilities mapped by action group. */ getProbabilities(state: Matrix | number): Probabilities; /** * Selects actions for one output head based on the raw output and policy (generalized for any model type). * @param actionOutput - The the output from the ML model. * @param actionMetadata - The metadata which informs what to do with the model output * @param outputName - The name of the output group. * @param row - The row to use for the model output * @returns An object representing selected actions. */ getActionHeadOutput(actionOutput: Matrix, actionMetadata: ActionMetadata, outputName: string, row?: number): ActionOutput; /** * Selects actions for one output head based on the raw output and policy. * @param rawOutput - The raw output when calculating the probabilities. * @param outputName - The name of the output group. * @param row - The row to use for the model output * @returns An object representing selected actions. */ selectActionOneHead(rawOutput: T, outputName: string, row?: number): ActionOutput; /** * Selects actions for all output groups based on inputs. * @param state - The input for the model (Matrix for neural nets | number for simple model). * @returns An object representing all selected actions. */ selectAction(state: Matrix | number): CombinedActionOutput; } declare class ModelCore { outputGroups: string[]; getActionHeadOutput(actionOutput: Matrix, actionMetadata: ActionMetadata, outputName: string, row?: number): ActionOutput; } /** The method used to initialize a new cell. */ type TabularInitializationMethod = "empty" | "random"; /** Represents the formatted configuration for tabular models */ interface FormattedModelConfigTabular extends FormattedModelConfigBase { initializationMethod: TabularInitializationMethod; numDiscreteStates: number; } /** Represents a simple model configuration (raw or formatted). */ type TabularModelConfig = RawModelConfigBase | FormattedModelConfigTabular; /** Represents the overall model data configuration. */ type TabularModelData = { config: TabularModelConfig; frequencies?: any[]; }; /** * Represents a cell of the tabular model. * Mapping from an action head to the action frequencies * */ type FrequencyCell = Record<string, number[]>; /** * TabularModel class for managing action probabilities and states. */ interface TabularModelType extends BaseModel<Record<string, Matrix>> { /** Neural network model configuration. */ config: TabularModelConfig; /** The frequencies representing the state of the table. */ frequencies: FrequencyCell[]; /** * Creates an empty cell based on action metadata. * @returns A frequency cell with empty values. */ createEmptyCell(): FrequencyCell; /** * Creates random probabilities for a given size. * @param size - The size of the probability array. * @returns An array of normalized probabilities. */ createRandomProbability(size: number): number[]; /** * Creates a random cell with probabilities for each action group. * @returns A frequency cell with random probabilities. */ createRandomCell(): FrequencyCell; /** * Initializes the tabular model based on a method. * @param initializationMethod - The initialization method ("empty" or "random"). Default = "empty" * @returns An array of frequency cells. */ initializeFrequencies(initializationMethod?: TabularInitializationMethod): FrequencyCell[]; } declare class TabularModel extends ModelCore implements TabularModelType { config: FormattedModelConfigTabular; frequencies: FrequencyCell[]; constructor(modelData: TabularModelData); createEmptyCell(): FrequencyCell; createRandomProbability(size: number): number[]; createRandomCell(): FrequencyCell; initializeFrequencies(initializationMethod?: TabularInitializationMethod): FrequencyCell[]; static convertFrequencyToProbability(output: number[]): number[]; getProbabilities(cell: number): Probabilities; selectActionOneHead(probabilities: Probabilities, outputName: string, row?: number): ActionOutput; selectAction(cell: number, row?: number): CombinedActionOutput; } /** Represents the raw configuration for neural-network models */ interface RawModelConfig extends RawModelConfigBase { neurons?: number[]; activationFunctionName?: "elu" | "relu"; } /** Represents the configuration a model's output */ type OutputConfig = { activation: ActionActivationType; outputType: "mean" | "quantileRegression"; quantiles: number; }; /** Represents the formatted configuration for neural-network models */ interface FormattedModelConfigNeuralNetwork extends FormattedModelConfigBase { nFeatures: number; neurons: number[]; activationFunctionName?: "elu" | "relu"; movingAverageType?: "Simple" | "Exponential"; decimalPrecision?: number; outputConfig?: OutputConfig; } /** Represents a neural-network model configuration (raw or formatted). */ type NeuralNetModelConfig = RawModelConfig | FormattedModelConfigNeuralNetwork; /** Represents a neural network model's parameters. */ type NeuralNetworkParameters = Record<string, Matrix>; /** Represents the neural network model data. */ type NeuralNetworkModelData = { config?: NeuralNetModelConfig; parameters?: NeuralNetworkParameters; }; /** Represents the outputs from every layer of forward prop. */ type NeuralNetworkOutputCache = Record<string, Matrix>; /** * NeuralNetworkMultihead class for managing a multihead neural network model. */ interface NeuralNetworkMultiheadType extends BaseModel<Record<string, any>> { /** Neural network model configuration. */ config: NeuralNetModelConfig; /** Model parameters such as weights and biases. */ parameters: NeuralNetworkParameters; /** * Slices the inputs to match the required number of features. * @param inputs - The input data array. * @returns The sliced input array. */ sliceInputs(inputs: Matrix): Matrix; /** * Performs computations for the next layer in the neural network. * @param currentLayer - The current layer of inputs or activations. * @param keyAppend - The key suffix for weights and biases. * @returns The output of the next layer. */ nextLayer(currentLayer: Matrix, keyAppend: string): Matrix; /** * Performs forward propagation through the neural network. * @param inputs - The input data array. * @returns A cache containing activations and raw outputs. */ forwardProp(inputs: Matrix): Record<string, any>; } declare class NeuralNetworkMultihead extends ModelCore implements NeuralNetworkMultiheadType { config: FormattedModelConfigNeuralNetwork; parameters: NeuralNetworkParameters; outputActivations: Record<string, ActivationFunction>; activationFunction: ActivationFunction; constructor(modelData: NeuralNetworkModelData); sliceInputs(inputs: Matrix): Matrix; nextLayer(currentLayer: Matrix, keyAppend: string): Matrix; forwardProp(inputs: Matrix): NeuralNetworkOutputCache; getProbabilities(inputs: Matrix): Probabilities; selectActionOneHead(cache: NeuralNetworkOutputCache, outputName: string, row?: number): ActionOutput; selectAction(inputs: Matrix, row?: number): CombinedActionOutput; selectMultipleActions(inputs: Matrix): CombinedActionOutput[]; } /** Generic model configuration for any of the available model types. */ type GenericModelConfig = NeuralNetModelConfig | TabularModelConfig; /** Represents the state for either neural-network (array or Matrix) or simple (number) models */ type ModelState = number[] | Matrix | number; /** Represents an action snapshot for all heads respectively */ type FormattedAction = Record<string, Matrix>; /** * Represents the different ways that an action can be inputted into the collect function. * number[] is only valid for models with 1 action head */ type RawAction = number[] | Matrix | FormattedAction; /** Represents a data instance containing state, reward, and additional information. */ interface DataInstanceBase { /** * The raw state before it gets formatted. * neural-network = two-dimensional numeric matrix or 1D array (unformatted). * simple = integer to indicate cell index */ state: ModelState; /** The reward given to the model for the current <s, a> pair. */ reward?: number; /** * Additional information related to the data instance. * Can contain arbitrary key-value pairs. */ info?: Record<string, any>; } /** Represents a raw data instance before the actions are properly formatted. */ interface RawDataInstance extends DataInstanceBase { /** The action taken, which can be an array of number, nested array of number, or properly formatted Record */ action: RawAction; } /** Represents a data instance containing state, action, reward, and additional information. */ interface DataInstance extends DataInstanceBase { /** The action taken, represented as a mapping of strings (action head) to matrices. */ action: FormattedAction; } /** The model configuration and model type are used to validate whether or not a data instance is valid. */ type ValidationParameters = { modelConfig?: GenericModelConfig; modelType?: ModelType; }; /** DataCollector class for managing the collection of data during gameplay. */ interface DataValidationType { /** The parameters to validate whether or not a data instance is valid. */ validationParams: ValidationParameters; /** Add the validation parameters to the data collector. */ addValidationParams(modelConfig: GenericModelConfig, modelType: ModelType): void; /** Check whether the size of an array matches the expectation. */ checkArraySizeMatch(array: number[], targetSize: number, mismatchPrepend: string): void; /** Validate the number of features */ checkFeatureSize(state1D: number[], nFeatures: number): void; /** Validate the number of actions. */ checkActionSize(action1D: number[], nActions: number): void; /** Validate that actions are numbers. */ checkValidNumber(action: number[]): void; /** Validate that the actions array is a one-hot encoded vector. */ checkOneHot(action: number[]): void; /** Validate the state based on the model type. */ validateState(state: ModelState): ModelState; /** Validate the new frame interval. */ validateFrameInterval(interval: number): void; /** Validate custom action intervals based on model config. */ validateCustomActionIntervals(customIntervals: Record<string, number>): Record<string, Record<number, number>>; /** Validate and format the action based on the action metadata in the model config. */ validateAction(action: RawAction): FormattedAction; /** Validate the data instance and reformat the action if necessary. */ validateInstance(dataInstance: RawDataInstance): DataInstance; } /** DataCollector class for managing the collection of data during gameplay. */ interface DataCollectorType extends DataValidationType { /** The interval after which frames are checked. */ frameInterval: number; /** The reward threshold used to bypass the default frame interval. */ rewardThreshold?: number; /** The custom interval associated with a specific action from a specific action head. */ customIntervalActions?: Record<string, Record<number, number>>; /** Whether or not a custom interval is used for specific actions. */ usingCustomIntervals: boolean; /** The training data collected so far. */ trainingData: DataInstance[]; /** * Sets the frame interval for collection checking. * @param interval - The interval at which we collect data. */ setFrameInterval(interval: number): void; /** * Sets the reward threshold for collection checking. * @param threshold - The absolute value reward threshold. */ setRewardThreshold(threshold: number): void; /** * Sets custom intervals for specified actions * @param customIntervals - The mapping that indicates the interval for each action. */ setCustomIntervalActions(customIntervals?: Record<string, number>): void; /** * Checks if the current frame count has reached the frame interval. * @param action - The current action object to use if a custom action interval is defined. * @returns {boolean} True if the current frame >= frame interval. */ checkFrame(action: Record<string, Matrix>): boolean; /** * Computes the dot product of two vectors. * @param v1 - The first vector as an array of numbers. * @param v2 - The second vector as an array of numbers. * @returns {number} The dot product of v1 and v2. */ dotProduct(v1: Vector, v2: Vector): number; /** * Checks if an action has changed compared to the previous action. * @param action - The current action object to compare. * @returns {boolean} True if the action has changed. */ checkAction(action: Record<string, Matrix>): boolean; /** * Checks if an action has changed compared to the previous action. * @param reward - The current reward received. * @returns {boolean} True if the action has changed. */ checkReward(reward: number): boolean; /** * Checks if the data instance is eligible for collection. * Eligibility is based on frame checks and action checks. * @param dataInstance - The current validated data instance. * @param adjustFrameBool - Whether or not to increment the frame counter. * @returns {boolean} True if the data instance is eligible. */ checkEligibility(dataInstance: DataInstance, adjustFrameBool?: boolean): boolean; /** * Collects a data instance if it is eligible. * @param dataInstance - An object with a state and action (and potentially reward and additional info). * @returns {boolean} True if the data instance was collected. */ collect(dataInstance: RawDataInstance): boolean; /** * Resets the DataCollector state. * Sets the `currentFrame` to 0, empties the `trainingData` array, and removed the previous action */ reset(): void; } declare class DataValidation implements DataValidationType { validationParams: ValidationParameters; constructor(); addValidationParams(modelConfig: GenericModelConfig, modelType: ModelType): void; checkArraySizeMatch(array: number[], targetSize: number, mismatchPrepend: string): void; checkFeatureSize(state1D: number[], nFeatures: number): void; checkActionSize(action1D: number[], nActions: number): void; checkValidNumber(action: number[]): void; checkOneHot(action: number[]): void; validateState(state: ModelState): ModelState; validateFrameInterval(interval: number): void; validateCustomActionIntervals(customIntervals: Record<string, number>): Record<string, Record<number, number>>; validateAction(action: RawAction): FormattedAction; validateInstance(dataInstance: RawDataInstance): DataInstance; } declare class DataCollector extends DataValidation implements DataCollectorType { _currentFrame: number; _prevAction: FormattedAction | null; frameInterval: number; rewardThreshold: number | undefined; customIntervalActions?: Record<string, Record<number, number>>; usingCustomIntervals: boolean; trainingData: DataInstance[]; constructor(frameInterval?: number); _incrementFrame(): void; setFrameInterval(interval: number): void; setRewardThreshold(threshold: number): void; setCustomIntervalActions(customIntervals?: Record<string, number>): void; checkFrame(action: Record<string, Matrix>): boolean; dotProduct(v1: Vector, v2: Vector): number; checkAction(action: Record<string, Matrix>): boolean; checkReward(reward: number): boolean; checkEligibility(dataInstance: DataInstance, adjustFrameBool?: boolean): boolean; collect(dataInstance: RawDataInstance): boolean; reset(): void; } export { DataCollector, type DataInstance, NeuralNetworkMultihead, type RawDataInstance, TabularModel };