@astermind/astermind-premium
Version:
Astermind Premium - Premium ML Toolkit
176 lines • 6.52 kB
JavaScript
// convolutional-elm.ts — Convolutional ELM (C-ELM)
// Convolutional layers + ELM for image/sequence processing
import { ELM } from '@astermind/astermind-elm';
import { requireLicense } from '../core/license.js';
/**
* Convolutional ELM
* Features:
* - Convolutional layers for feature extraction
* - ELM for classification
* - Translation invariance
* - Image/sequence processing
*/
export class ConvolutionalELM {
constructor(options) {
this.trained = false;
requireLicense(); // Premium feature - requires valid license
this.categories = options.categories;
this.options = {
categories: options.categories,
inputShape: options.inputShape ?? [28, 28, 1],
filters: options.filters ?? [32, 64],
kernelSizes: options.kernelSizes ?? [3, 3],
poolSizes: options.poolSizes ?? [2, 2],
hiddenUnits: options.hiddenUnits ?? 256,
activation: options.activation ?? 'relu',
maxLen: options.maxLen ?? 100,
useTokenizer: options.useTokenizer ?? true,
};
this.elm = new ELM({
useTokenizer: this.options.useTokenizer ? true : undefined,
hiddenUnits: this.options.hiddenUnits,
categories: this.options.categories,
maxLen: this.options.maxLen,
activation: this.options.activation,
});
}
/**
* Train on image/sequence data
*/
train(X, y) {
// Prepare labels
const labelIndices = y.map(label => typeof label === 'number'
? label
: this.options.categories.indexOf(label));
// Extract convolutional features
const images = Array.isArray(X[0][0]) ? X : X.map(x => [x]);
const features = this._extractConvolutionalFeatures(images);
// Train ELM on features
this.elm.setCategories?.(this.options.categories);
this.elm.trainFromData?.(features, labelIndices);
this.trained = true;
}
/**
* Extract features using convolutional layers
*/
_extractConvolutionalFeatures(images) {
const features = [];
for (const image of images) {
let current = image;
// Apply convolutional layers
for (let layer = 0; layer < this.options.filters.length; layer++) {
const convInput = Array.isArray(current[0][0])
? current[0]
: current;
const convOutput = this._convLayer(convInput, this.options.filters[layer], this.options.kernelSizes[layer] || 3);
current = this._poolLayer(convOutput, this.options.poolSizes[layer] || 2);
}
// Flatten
const flattened = this._flatten(current);
features.push(flattened);
}
return features;
}
/**
* Convolutional layer (simplified)
*/
_convLayer(input, numFilters, kernelSize) {
// Simplified convolution (in practice, use proper convolution)
const output = [];
for (let f = 0; f < numFilters; f++) {
const featureMap = [];
for (let i = 0; i < input.length; i++) {
featureMap[i] = [];
for (let j = 0; j < input[i].length; j++) {
// Simple convolution (simplified)
let sum = 0;
for (let ki = 0; ki < kernelSize; ki++) {
for (let kj = 0; kj < kernelSize; kj++) {
const row = i + ki - Math.floor(kernelSize / 2);
const col = j + kj - Math.floor(kernelSize / 2);
if (row >= 0 && row < input.length && col >= 0 && col < input[i].length) {
sum += input[row][col] || 0;
}
}
}
featureMap[i][j] = Math.max(0, sum / (kernelSize * kernelSize)); // ReLU
}
}
output.push(featureMap);
}
return output;
}
/**
* Pooling layer
*/
_poolLayer(input, poolSize) {
// Simplified pooling
const images = Array.isArray(input[0][0])
? input
: [input];
const pooled = [];
for (const img of images) {
const pooledImg = [];
for (let i = 0; i < img.length; i += poolSize) {
pooledImg[i / poolSize] = [];
for (let j = 0; j < img[i].length; j += poolSize) {
// Max pooling
let max = -Infinity;
for (let pi = 0; pi < poolSize && i + pi < img.length; pi++) {
for (let pj = 0; pj < poolSize && j + pj < img[i].length; pj++) {
max = Math.max(max, img[i + pi][j + pj] || 0);
}
}
pooledImg[i / poolSize][j / poolSize] = max;
}
}
pooled.push(pooledImg);
}
return pooled;
}
/**
* Flatten feature maps
*/
_flatten(featureMaps) {
if (Array.isArray(featureMaps[0][0])) {
const maps = featureMaps;
const flattened = [];
for (const map of maps) {
for (const row of map) {
flattened.push(...row);
}
}
return flattened;
}
else {
const map = featureMaps;
const flattened = [];
for (const row of map) {
flattened.push(...row);
}
return flattened;
}
}
/**
* Predict
*/
predict(X, topK = 3) {
if (!this.trained) {
throw new Error('Model must be trained before prediction');
}
const images = Array.isArray(X[0][0]) ? X : X.map(x => [x]);
const features = this._extractConvolutionalFeatures(images);
const results = [];
for (const feature of features) {
const preds = this.elm.predictFromVector?.([feature], topK) || [];
for (const pred of preds.slice(0, topK)) {
results.push({
label: pred.label || this.options.categories[pred.index || 0],
prob: pred.prob || 0,
});
}
}
return results;
}
}
//# sourceMappingURL=convolutional-elm.js.map