Merge commit 'd803bfe2b1fe7f5e219e50ac20d6801a0a58ac75' as 'vendor/ruvector'
This commit is contained in:
69
vendor/ruvector/npm/packages/spiking-neural/examples/basic.js
vendored
Normal file
69
vendor/ruvector/npm/packages/spiking-neural/examples/basic.js
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Basic Spiking Neural Network Example
|
||||
*
|
||||
* Demonstrates the fundamental usage of the spiking-neural SDK.
|
||||
*/
|
||||
|
||||
const {
|
||||
createFeedforwardSNN,
|
||||
rateEncoding,
|
||||
native,
|
||||
version
|
||||
} = require('spiking-neural');
|
||||
|
||||
console.log(`\nSpiking Neural Network SDK v${version}`);
|
||||
console.log(`Native SIMD: ${native ? 'Enabled' : 'JavaScript fallback'}\n`);
|
||||
console.log('='.repeat(50));
|
||||
|
||||
// Create a 3-layer feedforward SNN
|
||||
const snn = createFeedforwardSNN([100, 50, 10], {
|
||||
dt: 1.0, // 1ms time step
|
||||
tau: 20.0, // 20ms membrane time constant
|
||||
a_plus: 0.005, // STDP LTP rate
|
||||
a_minus: 0.005, // STDP LTD rate
|
||||
lateral_inhibition: true,
|
||||
inhibition_strength: 10.0
|
||||
});
|
||||
|
||||
console.log('\nNetwork created: 100 -> 50 -> 10 neurons');
|
||||
console.log(`Total synapses: ${100 * 50 + 50 * 10}`);
|
||||
|
||||
// Create input pattern (random)
|
||||
const input_pattern = new Float32Array(100).map(() => Math.random());
|
||||
|
||||
console.log('\nRunning 100ms simulation...\n');
|
||||
|
||||
// Run for 100ms
|
||||
let total_spikes = 0;
|
||||
for (let t = 0; t < 100; t++) {
|
||||
// Encode input as spike train
|
||||
const spikes = rateEncoding(input_pattern, snn.dt, 100);
|
||||
total_spikes += snn.step(spikes);
|
||||
}
|
||||
|
||||
// Get network statistics
|
||||
const stats = snn.getStats();
|
||||
|
||||
console.log('Results:');
|
||||
console.log(` Simulation time: ${stats.time}ms`);
|
||||
console.log(` Total spikes: ${total_spikes}`);
|
||||
console.log(` Avg spikes/ms: ${(total_spikes / stats.time).toFixed(2)}`);
|
||||
|
||||
// Layer statistics
|
||||
console.log('\nLayer Statistics:');
|
||||
for (const layer of stats.layers) {
|
||||
if (layer.neurons) {
|
||||
console.log(` Layer ${layer.index}: ${layer.neurons.count} neurons, ${layer.neurons.spike_count} current spikes`);
|
||||
}
|
||||
if (layer.synapses) {
|
||||
console.log(` Weights: mean=${layer.synapses.mean.toFixed(3)}, range=[${layer.synapses.min.toFixed(3)}, ${layer.synapses.max.toFixed(3)}]`);
|
||||
}
|
||||
}
|
||||
|
||||
// Get final output
|
||||
const output = snn.getOutput();
|
||||
console.log('\nOutput layer activity:', Array.from(output).map(v => v.toFixed(2)).join(', '));
|
||||
|
||||
console.log('\nDone!\n');
|
||||
140
vendor/ruvector/npm/packages/spiking-neural/examples/benchmark.js
vendored
Normal file
140
vendor/ruvector/npm/packages/spiking-neural/examples/benchmark.js
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Spiking Neural Network Performance Benchmark
|
||||
*
|
||||
* Tests performance across different network sizes and configurations.
|
||||
*/
|
||||
|
||||
const {
|
||||
createFeedforwardSNN,
|
||||
rateEncoding,
|
||||
SIMDOps,
|
||||
native,
|
||||
version
|
||||
} = require('spiking-neural');
|
||||
|
||||
console.log(`\nSNN Performance Benchmark v${version}`);
|
||||
console.log(`Native SIMD: ${native ? 'Enabled (10-50x faster)' : 'JavaScript fallback'}\n`);
|
||||
console.log('='.repeat(60));
|
||||
|
||||
// Network scaling benchmark
|
||||
console.log('\n--- NETWORK SCALING ---\n');
|
||||
|
||||
const sizes = [100, 500, 1000, 2000];
|
||||
const iterations = 100;
|
||||
|
||||
console.log('Neurons | Time/Step | Spikes/Step | Steps/Sec');
|
||||
console.log('-'.repeat(50));
|
||||
|
||||
for (const size of sizes) {
|
||||
const snn = createFeedforwardSNN([size, Math.floor(size / 2), 10], {
|
||||
dt: 1.0,
|
||||
lateral_inhibition: true
|
||||
});
|
||||
|
||||
const input = new Float32Array(size).fill(0.5);
|
||||
|
||||
// Warmup
|
||||
for (let i = 0; i < 10; i++) {
|
||||
snn.step(rateEncoding(input, snn.dt, 100));
|
||||
}
|
||||
|
||||
// Benchmark
|
||||
const start = performance.now();
|
||||
let total_spikes = 0;
|
||||
for (let i = 0; i < iterations; i++) {
|
||||
total_spikes += snn.step(rateEncoding(input, snn.dt, 100));
|
||||
}
|
||||
const elapsed = performance.now() - start;
|
||||
|
||||
const time_per_step = elapsed / iterations;
|
||||
const spikes_per_step = total_spikes / iterations;
|
||||
const steps_per_sec = Math.round(1000 / time_per_step);
|
||||
|
||||
console.log(`${size.toString().padStart(7)} | ${time_per_step.toFixed(3).padStart(9)}ms | ${spikes_per_step.toFixed(1).padStart(11)} | ${steps_per_sec.toString().padStart(9)}`);
|
||||
}
|
||||
|
||||
// SIMD vector operations
|
||||
console.log('\n--- SIMD VECTOR OPERATIONS ---\n');
|
||||
|
||||
const dimensions = [64, 128, 256, 512];
|
||||
const vecIterations = 10000;
|
||||
|
||||
console.log('Dimension | Naive (ms) | SIMD (ms) | Speedup');
|
||||
console.log('-'.repeat(50));
|
||||
|
||||
for (const dim of dimensions) {
|
||||
const a = new Float32Array(dim).map(() => Math.random());
|
||||
const b = new Float32Array(dim).map(() => Math.random());
|
||||
|
||||
// Naive dot product
|
||||
let start = performance.now();
|
||||
for (let i = 0; i < vecIterations; i++) {
|
||||
let sum = 0;
|
||||
for (let j = 0; j < dim; j++) sum += a[j] * b[j];
|
||||
}
|
||||
const naiveTime = performance.now() - start;
|
||||
|
||||
// SIMD dot product
|
||||
start = performance.now();
|
||||
for (let i = 0; i < vecIterations; i++) {
|
||||
SIMDOps.dotProduct(a, b);
|
||||
}
|
||||
const simdTime = performance.now() - start;
|
||||
|
||||
const speedup = naiveTime / simdTime;
|
||||
console.log(`${dim.toString().padStart(9)} | ${naiveTime.toFixed(2).padStart(10)} | ${simdTime.toFixed(2).padStart(9)} | ${speedup.toFixed(2)}x`);
|
||||
}
|
||||
|
||||
// Distance benchmark
|
||||
console.log('\n--- EUCLIDEAN DISTANCE ---\n');
|
||||
|
||||
console.log('Dimension | Naive (ms) | SIMD (ms) | Speedup');
|
||||
console.log('-'.repeat(50));
|
||||
|
||||
for (const dim of dimensions) {
|
||||
const a = new Float32Array(dim).map(() => Math.random());
|
||||
const b = new Float32Array(dim).map(() => Math.random());
|
||||
|
||||
// Naive
|
||||
let start = performance.now();
|
||||
for (let i = 0; i < vecIterations; i++) {
|
||||
let sum = 0;
|
||||
for (let j = 0; j < dim; j++) {
|
||||
const d = a[j] - b[j];
|
||||
sum += d * d;
|
||||
}
|
||||
Math.sqrt(sum);
|
||||
}
|
||||
const naiveTime = performance.now() - start;
|
||||
|
||||
// SIMD
|
||||
start = performance.now();
|
||||
for (let i = 0; i < vecIterations; i++) {
|
||||
SIMDOps.distance(a, b);
|
||||
}
|
||||
const simdTime = performance.now() - start;
|
||||
|
||||
const speedup = naiveTime / simdTime;
|
||||
console.log(`${dim.toString().padStart(9)} | ${naiveTime.toFixed(2).padStart(10)} | ${simdTime.toFixed(2).padStart(9)} | ${speedup.toFixed(2)}x`);
|
||||
}
|
||||
|
||||
// Memory usage
|
||||
console.log('\n--- MEMORY USAGE ---\n');
|
||||
|
||||
const memBefore = process.memoryUsage().heapUsed;
|
||||
const largeSnn = createFeedforwardSNN([1000, 500, 100], {});
|
||||
const memAfter = process.memoryUsage().heapUsed;
|
||||
const memUsed = (memAfter - memBefore) / 1024 / 1024;
|
||||
|
||||
console.log(`1000-500-100 network: ${memUsed.toFixed(2)} MB`);
|
||||
console.log(`Per neuron: ${(memUsed * 1024 / 1600).toFixed(2)} KB`);
|
||||
|
||||
console.log('\n--- SUMMARY ---\n');
|
||||
console.log('Key findings:');
|
||||
console.log(' - Larger networks have better amortized overhead');
|
||||
console.log(' - SIMD provides 1.2-2x speedup for vector ops');
|
||||
console.log(` - Native addon: ${native ? '10-50x faster (enabled)' : 'not built (run npm run build:native)'}`);
|
||||
|
||||
console.log('\nBenchmark complete!\n');
|
||||
171
vendor/ruvector/npm/packages/spiking-neural/examples/pattern-recognition.js
vendored
Normal file
171
vendor/ruvector/npm/packages/spiking-neural/examples/pattern-recognition.js
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Pattern Recognition with Spiking Neural Networks
|
||||
*
|
||||
* This example demonstrates:
|
||||
* - Rate-coded input encoding
|
||||
* - STDP learning (unsupervised)
|
||||
* - Pattern classification
|
||||
* - Lateral inhibition for winner-take-all
|
||||
*/
|
||||
|
||||
const {
|
||||
createFeedforwardSNN,
|
||||
rateEncoding,
|
||||
native,
|
||||
version
|
||||
} = require('spiking-neural');
|
||||
|
||||
console.log(`\nPattern Recognition with SNNs v${version}`);
|
||||
console.log(`Native SIMD: ${native ? 'Enabled' : 'JavaScript fallback'}\n`);
|
||||
console.log('='.repeat(60));
|
||||
|
||||
// Define 5x5 patterns
|
||||
const patterns = {
|
||||
'Cross': [
|
||||
0, 0, 1, 0, 0,
|
||||
0, 0, 1, 0, 0,
|
||||
1, 1, 1, 1, 1,
|
||||
0, 0, 1, 0, 0,
|
||||
0, 0, 1, 0, 0
|
||||
],
|
||||
'Square': [
|
||||
1, 1, 1, 1, 1,
|
||||
1, 0, 0, 0, 1,
|
||||
1, 0, 0, 0, 1,
|
||||
1, 0, 0, 0, 1,
|
||||
1, 1, 1, 1, 1
|
||||
],
|
||||
'Diagonal': [
|
||||
1, 0, 0, 0, 0,
|
||||
0, 1, 0, 0, 0,
|
||||
0, 0, 1, 0, 0,
|
||||
0, 0, 0, 1, 0,
|
||||
0, 0, 0, 0, 1
|
||||
],
|
||||
'X-Shape': [
|
||||
1, 0, 0, 0, 1,
|
||||
0, 1, 0, 1, 0,
|
||||
0, 0, 1, 0, 0,
|
||||
0, 1, 0, 1, 0,
|
||||
1, 0, 0, 0, 1
|
||||
]
|
||||
};
|
||||
|
||||
// Visualize patterns
|
||||
console.log('\nPatterns:\n');
|
||||
for (const [name, pattern] of Object.entries(patterns)) {
|
||||
console.log(`${name}:`);
|
||||
for (let i = 0; i < 5; i++) {
|
||||
const row = pattern.slice(i * 5, (i + 1) * 5).map(v => v ? '##' : ' ').join('');
|
||||
console.log(` ${row}`);
|
||||
}
|
||||
console.log();
|
||||
}
|
||||
|
||||
// Create SNN
|
||||
const n_input = 25; // 5x5 pixels
|
||||
const n_hidden = 20; // Hidden layer
|
||||
const n_output = 4; // 4 pattern classes
|
||||
|
||||
const snn = createFeedforwardSNN([n_input, n_hidden, n_output], {
|
||||
dt: 1.0,
|
||||
tau: 20.0,
|
||||
v_thresh: -50.0,
|
||||
v_reset: -70.0,
|
||||
a_plus: 0.005,
|
||||
a_minus: 0.005,
|
||||
init_weight: 0.3,
|
||||
init_std: 0.1,
|
||||
lateral_inhibition: true,
|
||||
inhibition_strength: 15.0
|
||||
});
|
||||
|
||||
console.log(`Network: ${n_input}-${n_hidden}-${n_output} (${n_input * n_hidden + n_hidden * n_output} synapses)`);
|
||||
console.log(`Learning: STDP (unsupervised)`);
|
||||
|
||||
// Training
|
||||
console.log('\n--- TRAINING ---\n');
|
||||
|
||||
const n_epochs = 5;
|
||||
const presentation_time = 100;
|
||||
const pattern_names = Object.keys(patterns);
|
||||
const pattern_arrays = Object.values(patterns);
|
||||
|
||||
for (let epoch = 0; epoch < n_epochs; epoch++) {
|
||||
let total_spikes = 0;
|
||||
|
||||
for (let p = 0; p < pattern_names.length; p++) {
|
||||
const pattern = pattern_arrays[p];
|
||||
snn.reset();
|
||||
|
||||
for (let t = 0; t < presentation_time; t++) {
|
||||
const input_spikes = rateEncoding(pattern, snn.dt, 100);
|
||||
total_spikes += snn.step(input_spikes);
|
||||
}
|
||||
}
|
||||
|
||||
const stats = snn.getStats();
|
||||
const w = stats.layers[0].synapses;
|
||||
console.log(`Epoch ${epoch + 1}/${n_epochs}: ${total_spikes} spikes, weights: mean=${w.mean.toFixed(3)}`);
|
||||
}
|
||||
|
||||
// Testing
|
||||
console.log('\n--- TESTING ---\n');
|
||||
|
||||
const results = [];
|
||||
for (let p = 0; p < pattern_names.length; p++) {
|
||||
const pattern = pattern_arrays[p];
|
||||
snn.reset();
|
||||
|
||||
const output_activity = new Float32Array(n_output);
|
||||
|
||||
for (let t = 0; t < presentation_time; t++) {
|
||||
const input_spikes = rateEncoding(pattern, snn.dt, 100);
|
||||
snn.step(input_spikes);
|
||||
|
||||
const output = snn.getOutput();
|
||||
for (let i = 0; i < n_output; i++) {
|
||||
output_activity[i] += output[i];
|
||||
}
|
||||
}
|
||||
|
||||
const winner = Array.from(output_activity).indexOf(Math.max(...output_activity));
|
||||
const total = output_activity.reduce((a, b) => a + b, 0);
|
||||
const confidence = total > 0 ? (output_activity[winner] / total * 100) : 0;
|
||||
|
||||
results.push({ pattern: pattern_names[p], winner, confidence });
|
||||
console.log(`${pattern_names[p].padEnd(10)} -> Neuron ${winner} (${confidence.toFixed(1)}% confidence)`);
|
||||
}
|
||||
|
||||
// Noise test
|
||||
console.log('\n--- ROBUSTNESS (20% noise) ---\n');
|
||||
|
||||
function addNoise(pattern, noise_level = 0.2) {
|
||||
return pattern.map(v => Math.random() < noise_level ? 1 - v : v);
|
||||
}
|
||||
|
||||
for (let p = 0; p < pattern_names.length; p++) {
|
||||
const noisy_pattern = addNoise(pattern_arrays[p], 0.2);
|
||||
snn.reset();
|
||||
|
||||
const output_activity = new Float32Array(n_output);
|
||||
|
||||
for (let t = 0; t < presentation_time; t++) {
|
||||
const input_spikes = rateEncoding(noisy_pattern, snn.dt, 100);
|
||||
snn.step(input_spikes);
|
||||
|
||||
const output = snn.getOutput();
|
||||
for (let i = 0; i < n_output; i++) {
|
||||
output_activity[i] += output[i];
|
||||
}
|
||||
}
|
||||
|
||||
const winner = Array.from(output_activity).indexOf(Math.max(...output_activity));
|
||||
const correct = winner === results[p].winner;
|
||||
|
||||
console.log(`${pattern_names[p].padEnd(10)} -> Neuron ${winner} ${correct ? '✓' : '✗'}`);
|
||||
}
|
||||
|
||||
console.log('\nDone!\n');
|
||||
Reference in New Issue
Block a user