nrn-ml
Version:
Core ML library for the NRN ecosystem
418 lines (402 loc) • 19 kB
text/typescript
/** 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 };