UNPKG

@astermind/astermind-premium

Version:

Astermind Premium - Premium ML Toolkit

176 lines 6.52 kB
// 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