@aleph-ai/tinyaleph 1.5.7 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core/alexander-module.js +1469 -0
- package/core/arithmetic-link-kernel.js +1338 -0
- package/core/index.js +95 -2
- package/examples/01-hello-world.js +69 -0
- package/examples/02-basic-hash.js +90 -0
- package/examples/02-observer-stack.js +385 -0
- package/examples/03-quantum-coin.js +136 -0
- package/examples/05-symbolic-resonance.js +146 -0
- package/examples/06-symbol-database.js +150 -0
- package/examples/07-semantic-inference.js +223 -0
- package/examples/08-compound-symbols.js +219 -0
- package/examples/README.md +170 -0
- package/examples/ai/01-embeddings.js +155 -0
- package/examples/ai/02-semantic-memory.js +243 -0
- package/examples/ai/03-reasoning.js +243 -0
- package/examples/ai/04-knowledge-graph.js +279 -0
- package/examples/ai/05-llm-integration.js +333 -0
- package/examples/ai/06-agent.js +294 -0
- package/examples/ai/07-hybrid-ai.js +223 -0
- package/examples/ai/08-entropy-reasoning.js +259 -0
- package/examples/ai/09-concept-learning.js +271 -0
- package/examples/ai/10-prompt-primes.js +312 -0
- package/examples/ai/11-rag.js +332 -0
- package/examples/ai/12-neuro-symbolic.js +321 -0
- package/examples/ai/README.md +80 -0
- package/examples/arithmetic-topology/01-legendre-symbol.js +78 -0
- package/examples/arithmetic-topology/02-redei-symbol.js +126 -0
- package/examples/arithmetic-topology/03-alk-kuramoto.js +138 -0
- package/examples/arithmetic-topology/04-alexander-module.js +117 -0
- package/examples/arithmetic-topology/05-signature-memory.js +118 -0
- package/examples/arithmetic-topology/README.md +291 -0
- package/examples/bioinformatics/01-dna-encoding.js +108 -0
- package/examples/bioinformatics/02-central-dogma.js +162 -0
- package/examples/bioinformatics/03-protein-folding.js +206 -0
- package/examples/bioinformatics/04-dna-computing.js +192 -0
- package/examples/bioinformatics/05-molecular-binding.js +209 -0
- package/examples/chat.js +105 -0
- package/examples/crt-homology/01-residue-encoding.js +87 -0
- package/examples/crt-homology/02-birkhoff-attention.js +100 -0
- package/examples/crt-homology/03-homology-loss.js +132 -0
- package/examples/crt-homology/04-crt-resoformer.js +132 -0
- package/examples/crt-homology/README.md +67 -0
- package/examples/crypto/01-password-hash.js +210 -0
- package/examples/crypto/02-key-derivation.js +210 -0
- package/examples/crypto/03-hmac.js +229 -0
- package/examples/crypto/04-file-integrity.js +263 -0
- package/examples/crypto/05-content-hash.js +263 -0
- package/examples/crypto/README.md +99 -0
- package/examples/demo-modular.js +223 -0
- package/examples/demo-two-layer.js +196 -0
- package/examples/discrete/01-integer-sine-table.js +120 -0
- package/examples/discrete/02-codebook-tunneling.js +118 -0
- package/examples/discrete/03-canonical-fusion.js +135 -0
- package/examples/discrete/04-tick-gate.js +139 -0
- package/examples/discrete/README.md +142 -0
- package/examples/formal-semantics/01-typed-terms.js +156 -0
- package/examples/formal-semantics/02-reduction.js +202 -0
- package/examples/formal-semantics/03-lambda-translation.js +206 -0
- package/examples/formal-semantics/04-enochian-language.js +257 -0
- package/examples/formal-semantics/README.md +98 -0
- package/examples/math/01-quaternions.js +237 -0
- package/examples/math/02-octonions.js +192 -0
- package/examples/math/03-prime-factorization.js +215 -0
- package/examples/math/04-vector-spaces.js +210 -0
- package/examples/math/05-gaussian-primes.js +234 -0
- package/examples/math/README.md +93 -0
- package/examples/physics/01-oscillator.js +177 -0
- package/examples/physics/02-lyapunov.js +201 -0
- package/examples/physics/03-collapse.js +183 -0
- package/examples/physics/04-kuramoto.js +212 -0
- package/examples/physics/05-entropy.js +226 -0
- package/examples/physics/05-sync-models.js +298 -0
- package/examples/physics/06-primeon-ladder.js +233 -0
- package/examples/physics/07-kuramoto-coupled-ladder.js +298 -0
- package/examples/physics/README.md +126 -0
- package/examples/resonance/01-prime-hilbert-space.js +140 -0
- package/examples/resonance/02-prime-resonance-network.js +221 -0
- package/examples/resonance/03-resoformer.js +349 -0
- package/examples/resonance/04-resoformer-training.js +329 -0
- package/examples/resonance/05-language-model.js +484 -0
- package/examples/resonance/README.md +238 -0
- package/examples/run-examples.js +417 -0
- package/examples/scientific/01-single-qubit.js +185 -0
- package/examples/scientific/02-two-qubit.js +209 -0
- package/examples/scientific/03-quantum-circuits.js +270 -0
- package/examples/scientific/04-measurement.js +229 -0
- package/examples/scientific/05-algorithms.js +245 -0
- package/examples/scientific/06-random.js +225 -0
- package/examples/scientific/07-wavefunction.js +192 -0
- package/examples/scientific/README.md +118 -0
- package/examples/semantic/01-vocabulary.js +186 -0
- package/examples/semantic/02-similarity.js +263 -0
- package/examples/semantic/03-word-algebra.js +295 -0
- package/examples/semantic/04-clustering.js +348 -0
- package/examples/semantic/05-classification.js +386 -0
- package/examples/semantic/06-dna-encoding.js +228 -0
- package/examples/semantic/07-search.js +304 -0
- package/examples/semantic/08-qa-system.js +278 -0
- package/examples/semantic/README.md +116 -0
- package/examples/topology/01-108-invariant.js +81 -0
- package/examples/topology/02-trefoil-constants.js +112 -0
- package/examples/topology/03-gauge-symmetry.js +112 -0
- package/examples/topology/04-free-energy-dynamics.js +124 -0
- package/examples/topology/README.md +129 -0
- package/index.js +32 -0
- package/modular.js +63 -2
- package/package.json +8 -3
- package/physics/alk-kuramoto.js +817 -0
- package/physics/index.js +23 -2
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @example Text Classification
|
|
3
|
+
* @description Classify texts into categories using embeddings
|
|
4
|
+
*
|
|
5
|
+
* TinyAleph enables supervised text classification:
|
|
6
|
+
* - Train category prototypes from labeled examples
|
|
7
|
+
* - Classify new texts by similarity to prototypes
|
|
8
|
+
* - Multi-class and multi-label classification support
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const { SemanticBackend, Hypercomplex } = require('../../modular');
|
|
12
|
+
|
|
13
|
+
// ===========================================
|
|
14
|
+
// SETUP
|
|
15
|
+
// ===========================================
|
|
16
|
+
|
|
17
|
+
const backend = new SemanticBackend({ dimension: 16 });
|
|
18
|
+
|
|
19
|
+
console.log('TinyAleph Text Classification Example');
|
|
20
|
+
console.log('=====================================\n');
|
|
21
|
+
|
|
22
|
+
// ===========================================
|
|
23
|
+
// HELPER FUNCTIONS
|
|
24
|
+
// ===========================================
|
|
25
|
+
|
|
26
|
+
function similarity(state1, state2) {
|
|
27
|
+
let dot = 0, mag1 = 0, mag2 = 0;
|
|
28
|
+
for (let i = 0; i < state1.c.length; i++) {
|
|
29
|
+
dot += state1.c[i] * state2.c[i];
|
|
30
|
+
mag1 += state1.c[i] * state1.c[i];
|
|
31
|
+
mag2 += state2.c[i] * state2.c[i];
|
|
32
|
+
}
|
|
33
|
+
return dot / (Math.sqrt(mag1) * Math.sqrt(mag2) || 1);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// ===========================================
|
|
37
|
+
// PROTOTYPE-BASED CLASSIFIER
|
|
38
|
+
// ===========================================
|
|
39
|
+
|
|
40
|
+
console.log('Building Prototype-Based Classifier:');
|
|
41
|
+
console.log('─'.repeat(50) + '\n');
|
|
42
|
+
|
|
43
|
+
class PrototypeClassifier {
|
|
44
|
+
constructor(backend) {
|
|
45
|
+
this.backend = backend;
|
|
46
|
+
this.prototypes = new Map();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Train by averaging examples per class
|
|
50
|
+
train(examples) {
|
|
51
|
+
const classEmbeddings = new Map();
|
|
52
|
+
|
|
53
|
+
// Group embeddings by class
|
|
54
|
+
for (const { text, label } of examples) {
|
|
55
|
+
const state = this.backend.textToOrderedState(text);
|
|
56
|
+
if (!classEmbeddings.has(label)) {
|
|
57
|
+
classEmbeddings.set(label, []);
|
|
58
|
+
}
|
|
59
|
+
classEmbeddings.get(label).push(state);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Compute prototype for each class
|
|
63
|
+
for (const [label, embeddings] of classEmbeddings) {
|
|
64
|
+
const prototype = Hypercomplex.zero(16);
|
|
65
|
+
for (const emb of embeddings) {
|
|
66
|
+
for (let i = 0; i < 16; i++) {
|
|
67
|
+
prototype.c[i] += emb.c[i];
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
for (let i = 0; i < 16; i++) {
|
|
71
|
+
prototype.c[i] /= embeddings.length;
|
|
72
|
+
}
|
|
73
|
+
this.prototypes.set(label, prototype.normalize());
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
console.log(`Trained ${this.prototypes.size} class prototypes`);
|
|
77
|
+
for (const [label, proto] of this.prototypes) {
|
|
78
|
+
console.log(` ${label}: norm=${proto.norm().toFixed(4)}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Classify a new text
|
|
83
|
+
predict(text) {
|
|
84
|
+
const state = this.backend.textToOrderedState(text);
|
|
85
|
+
|
|
86
|
+
const scores = [];
|
|
87
|
+
for (const [label, prototype] of this.prototypes) {
|
|
88
|
+
const sim = similarity(state, prototype);
|
|
89
|
+
scores.push({ label, score: sim });
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
scores.sort((a, b) => b.score - a.score);
|
|
93
|
+
return scores;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Classify with confidence threshold
|
|
97
|
+
predictWithThreshold(text, threshold = 0.3) {
|
|
98
|
+
const scores = this.predict(text);
|
|
99
|
+
const prediction = scores[0];
|
|
100
|
+
|
|
101
|
+
if (prediction.score < threshold) {
|
|
102
|
+
return { label: 'unknown', score: prediction.score, confident: false };
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return { ...prediction, confident: true };
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// ===========================================
|
|
110
|
+
// TRAINING DATA
|
|
111
|
+
// ===========================================
|
|
112
|
+
|
|
113
|
+
const trainingData = [
|
|
114
|
+
// Positive sentiment
|
|
115
|
+
{ text: 'I love this product amazing quality', label: 'positive' },
|
|
116
|
+
{ text: 'Excellent service highly recommended', label: 'positive' },
|
|
117
|
+
{ text: 'Best purchase I ever made fantastic', label: 'positive' },
|
|
118
|
+
{ text: 'Wonderful experience great value', label: 'positive' },
|
|
119
|
+
{ text: 'Absolutely delighted very happy', label: 'positive' },
|
|
120
|
+
|
|
121
|
+
// Negative sentiment
|
|
122
|
+
{ text: 'Terrible product complete waste', label: 'negative' },
|
|
123
|
+
{ text: 'Worst experience never again', label: 'negative' },
|
|
124
|
+
{ text: 'Very disappointed poor quality', label: 'negative' },
|
|
125
|
+
{ text: 'Horrible service would not recommend', label: 'negative' },
|
|
126
|
+
{ text: 'Awful broke immediately regret buying', label: 'negative' },
|
|
127
|
+
|
|
128
|
+
// Neutral sentiment
|
|
129
|
+
{ text: 'Average product nothing special', label: 'neutral' },
|
|
130
|
+
{ text: 'Standard quality as expected', label: 'neutral' },
|
|
131
|
+
{ text: 'Okay for the price basic functionality', label: 'neutral' },
|
|
132
|
+
{ text: 'Normal delivery time acceptable', label: 'neutral' },
|
|
133
|
+
{ text: 'Regular product does the job', label: 'neutral' }
|
|
134
|
+
];
|
|
135
|
+
|
|
136
|
+
// ===========================================
|
|
137
|
+
// TRAIN AND TEST
|
|
138
|
+
// ===========================================
|
|
139
|
+
|
|
140
|
+
const classifier = new PrototypeClassifier(backend);
|
|
141
|
+
classifier.train(trainingData);
|
|
142
|
+
|
|
143
|
+
console.log('\n' + '═'.repeat(50));
|
|
144
|
+
console.log('Testing Classification:');
|
|
145
|
+
console.log('═'.repeat(50) + '\n');
|
|
146
|
+
|
|
147
|
+
const testTexts = [
|
|
148
|
+
'This is the best thing ever I am so happy',
|
|
149
|
+
'Terrible awful never buying this again',
|
|
150
|
+
'It works I guess nothing remarkable',
|
|
151
|
+
'Absolutely fantastic exceeded expectations',
|
|
152
|
+
'Broken on arrival very frustrated',
|
|
153
|
+
'Does what it says adequate performance'
|
|
154
|
+
];
|
|
155
|
+
|
|
156
|
+
for (const text of testTexts) {
|
|
157
|
+
const scores = classifier.predict(text);
|
|
158
|
+
const top = scores[0];
|
|
159
|
+
|
|
160
|
+
console.log(`"${text.substring(0, 40)}..."`);
|
|
161
|
+
console.log(` Prediction: ${top.label.toUpperCase()} (${(top.score * 100).toFixed(1)}%)`);
|
|
162
|
+
console.log(` All scores: ${scores.map(s => `${s.label}:${(s.score*100).toFixed(0)}%`).join(', ')}\n`);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// ===========================================
|
|
166
|
+
// K-NEAREST NEIGHBORS CLASSIFIER
|
|
167
|
+
// ===========================================
|
|
168
|
+
|
|
169
|
+
console.log('═'.repeat(50));
|
|
170
|
+
console.log('K-Nearest Neighbors Classification:');
|
|
171
|
+
console.log('═'.repeat(50) + '\n');
|
|
172
|
+
|
|
173
|
+
class KNNClassifier {
|
|
174
|
+
constructor(backend, k = 3) {
|
|
175
|
+
this.backend = backend;
|
|
176
|
+
this.k = k;
|
|
177
|
+
this.trainingSet = [];
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
train(examples) {
|
|
181
|
+
this.trainingSet = examples.map(ex => ({
|
|
182
|
+
text: ex.text,
|
|
183
|
+
label: ex.label,
|
|
184
|
+
state: this.backend.textToOrderedState(ex.text)
|
|
185
|
+
}));
|
|
186
|
+
console.log(`Stored ${this.trainingSet.length} training examples`);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
predict(text) {
|
|
190
|
+
const state = this.backend.textToOrderedState(text);
|
|
191
|
+
|
|
192
|
+
// Compute distances to all training examples
|
|
193
|
+
const distances = this.trainingSet.map(ex => ({
|
|
194
|
+
label: ex.label,
|
|
195
|
+
similarity: similarity(state, ex.state)
|
|
196
|
+
}));
|
|
197
|
+
|
|
198
|
+
// Sort by similarity (descending)
|
|
199
|
+
distances.sort((a, b) => b.similarity - a.similarity);
|
|
200
|
+
|
|
201
|
+
// Take k nearest neighbors
|
|
202
|
+
const neighbors = distances.slice(0, this.k);
|
|
203
|
+
|
|
204
|
+
// Vote
|
|
205
|
+
const votes = new Map();
|
|
206
|
+
for (const n of neighbors) {
|
|
207
|
+
votes.set(n.label, (votes.get(n.label) || 0) + 1);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Find winner
|
|
211
|
+
let winner = null;
|
|
212
|
+
let maxVotes = 0;
|
|
213
|
+
for (const [label, count] of votes) {
|
|
214
|
+
if (count > maxVotes) {
|
|
215
|
+
maxVotes = count;
|
|
216
|
+
winner = label;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return {
|
|
221
|
+
label: winner,
|
|
222
|
+
votes: maxVotes,
|
|
223
|
+
k: this.k,
|
|
224
|
+
neighbors: neighbors.map(n => ({ label: n.label, sim: n.similarity.toFixed(3) }))
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const knnClassifier = new KNNClassifier(backend, 3);
|
|
230
|
+
knnClassifier.train(trainingData);
|
|
231
|
+
|
|
232
|
+
console.log('\nKNN predictions:\n');
|
|
233
|
+
for (const text of testTexts.slice(0, 4)) {
|
|
234
|
+
const result = knnClassifier.predict(text);
|
|
235
|
+
console.log(`"${text.substring(0, 35)}..."`);
|
|
236
|
+
console.log(` Prediction: ${result.label.toUpperCase()} (${result.votes}/${result.k} votes)`);
|
|
237
|
+
console.log(` Neighbors: ${result.neighbors.map(n => n.label).join(', ')}\n`);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// ===========================================
|
|
241
|
+
// MULTI-LABEL CLASSIFICATION
|
|
242
|
+
// ===========================================
|
|
243
|
+
|
|
244
|
+
console.log('═'.repeat(50));
|
|
245
|
+
console.log('Multi-Label Classification:');
|
|
246
|
+
console.log('═'.repeat(50) + '\n');
|
|
247
|
+
|
|
248
|
+
class MultiLabelClassifier {
|
|
249
|
+
constructor(backend, threshold = 0.4) {
|
|
250
|
+
this.backend = backend;
|
|
251
|
+
this.threshold = threshold;
|
|
252
|
+
this.labelPrototypes = new Map();
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
train(examples) {
|
|
256
|
+
// Each example can have multiple labels
|
|
257
|
+
const labelEmbeddings = new Map();
|
|
258
|
+
|
|
259
|
+
for (const { text, labels } of examples) {
|
|
260
|
+
const state = this.backend.textToOrderedState(text);
|
|
261
|
+
for (const label of labels) {
|
|
262
|
+
if (!labelEmbeddings.has(label)) {
|
|
263
|
+
labelEmbeddings.set(label, []);
|
|
264
|
+
}
|
|
265
|
+
labelEmbeddings.get(label).push(state);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Compute prototypes
|
|
270
|
+
for (const [label, embeddings] of labelEmbeddings) {
|
|
271
|
+
const prototype = Hypercomplex.zero(16);
|
|
272
|
+
for (const emb of embeddings) {
|
|
273
|
+
for (let i = 0; i < 16; i++) {
|
|
274
|
+
prototype.c[i] += emb.c[i];
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
for (let i = 0; i < 16; i++) {
|
|
278
|
+
prototype.c[i] /= embeddings.length;
|
|
279
|
+
}
|
|
280
|
+
this.labelPrototypes.set(label, prototype.normalize());
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
predict(text) {
|
|
285
|
+
const state = this.backend.textToOrderedState(text);
|
|
286
|
+
|
|
287
|
+
const matchedLabels = [];
|
|
288
|
+
for (const [label, prototype] of this.labelPrototypes) {
|
|
289
|
+
const sim = similarity(state, prototype);
|
|
290
|
+
if (sim >= this.threshold) {
|
|
291
|
+
matchedLabels.push({ label, score: sim });
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
matchedLabels.sort((a, b) => b.score - a.score);
|
|
296
|
+
return matchedLabels;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
const multiLabelData = [
|
|
301
|
+
{ text: 'breaking news politics election results', labels: ['news', 'politics'] },
|
|
302
|
+
{ text: 'celebrity gossip entertainment scandal', labels: ['entertainment', 'celebrity'] },
|
|
303
|
+
{ text: 'sports team wins championship title', labels: ['sports', 'news'] },
|
|
304
|
+
{ text: 'tech company announces new smartphone', labels: ['tech', 'business', 'news'] },
|
|
305
|
+
{ text: 'movie star interview red carpet', labels: ['entertainment', 'celebrity'] },
|
|
306
|
+
{ text: 'economic report market analysis', labels: ['business', 'finance'] },
|
|
307
|
+
{ text: 'athlete scandal controversy', labels: ['sports', 'celebrity', 'news'] },
|
|
308
|
+
{ text: 'startup funding investment round', labels: ['business', 'tech', 'finance'] }
|
|
309
|
+
];
|
|
310
|
+
|
|
311
|
+
const multiClassifier = new MultiLabelClassifier(backend, 0.35);
|
|
312
|
+
multiClassifier.train(multiLabelData);
|
|
313
|
+
|
|
314
|
+
const multiLabelTests = [
|
|
315
|
+
'tech giant stock price soars',
|
|
316
|
+
'famous actor premieres new film',
|
|
317
|
+
'team player sets new record'
|
|
318
|
+
];
|
|
319
|
+
|
|
320
|
+
console.log('Multi-label predictions:\n');
|
|
321
|
+
for (const text of multiLabelTests) {
|
|
322
|
+
const labels = multiClassifier.predict(text);
|
|
323
|
+
console.log(`"${text}"`);
|
|
324
|
+
if (labels.length > 0) {
|
|
325
|
+
console.log(` Labels: ${labels.map(l => `${l.label}(${(l.score*100).toFixed(0)}%)`).join(', ')}\n`);
|
|
326
|
+
} else {
|
|
327
|
+
console.log(' No labels above threshold\n');
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// ===========================================
|
|
332
|
+
// EVALUATION METRICS
|
|
333
|
+
// ===========================================
|
|
334
|
+
|
|
335
|
+
console.log('═'.repeat(50));
|
|
336
|
+
console.log('Classifier Evaluation:');
|
|
337
|
+
console.log('═'.repeat(50) + '\n');
|
|
338
|
+
|
|
339
|
+
// Create test set
|
|
340
|
+
const testSet = [
|
|
341
|
+
{ text: 'Absolutely love it perfect in every way', label: 'positive' },
|
|
342
|
+
{ text: 'Complete garbage do not buy', label: 'negative' },
|
|
343
|
+
{ text: 'Fine I suppose mediocre quality', label: 'neutral' },
|
|
344
|
+
{ text: 'Outstanding exceeded all expectations', label: 'positive' },
|
|
345
|
+
{ text: 'Worst thing I ever purchased', label: 'negative' }
|
|
346
|
+
];
|
|
347
|
+
|
|
348
|
+
let correct = 0;
|
|
349
|
+
const confusionMatrix = {};
|
|
350
|
+
|
|
351
|
+
for (const test of testSet) {
|
|
352
|
+
const prediction = classifier.predict(test.text)[0].label;
|
|
353
|
+
const actual = test.label;
|
|
354
|
+
|
|
355
|
+
if (prediction === actual) correct++;
|
|
356
|
+
|
|
357
|
+
if (!confusionMatrix[actual]) confusionMatrix[actual] = {};
|
|
358
|
+
confusionMatrix[actual][prediction] = (confusionMatrix[actual][prediction] || 0) + 1;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
const accuracy = correct / testSet.length;
|
|
362
|
+
console.log(`Accuracy: ${(accuracy * 100).toFixed(1)}% (${correct}/${testSet.length})\n`);
|
|
363
|
+
|
|
364
|
+
console.log('Confusion Matrix:');
|
|
365
|
+
const labels = ['positive', 'negative', 'neutral'];
|
|
366
|
+
console.log(' ' + labels.map(l => l.substring(0, 5).padStart(8)).join(''));
|
|
367
|
+
for (const actual of labels) {
|
|
368
|
+
process.stdout.write(actual.substring(0, 8).padEnd(9));
|
|
369
|
+
for (const pred of labels) {
|
|
370
|
+
const count = confusionMatrix[actual]?.[pred] || 0;
|
|
371
|
+
process.stdout.write(String(count).padStart(8));
|
|
372
|
+
}
|
|
373
|
+
console.log();
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// ===========================================
|
|
377
|
+
// KEY TAKEAWAYS
|
|
378
|
+
// ===========================================
|
|
379
|
+
|
|
380
|
+
console.log('\n' + '═'.repeat(50));
|
|
381
|
+
console.log('KEY TAKEAWAYS:');
|
|
382
|
+
console.log('1. Prototype classifiers average training examples');
|
|
383
|
+
console.log('2. KNN uses nearest neighbors for voting');
|
|
384
|
+
console.log('3. Multi-label assigns multiple categories');
|
|
385
|
+
console.log('4. Threshold controls prediction confidence');
|
|
386
|
+
console.log('5. Confusion matrix reveals error patterns');
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @example DNA-Inspired Encoding
|
|
3
|
+
* @description Explore biological-inspired text processing
|
|
4
|
+
*
|
|
5
|
+
* TinyAleph implements DNA-like text processing inspired by molecular biology:
|
|
6
|
+
* - Bidirectional processing (boustrophedon reading)
|
|
7
|
+
* - Codon-style triplet chunking
|
|
8
|
+
* - 6-frame reading (like DNA translation)
|
|
9
|
+
* - Sense/antisense duality
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const { SemanticBackend, Hypercomplex } = require('../../modular');
|
|
13
|
+
|
|
14
|
+
// ===========================================
|
|
15
|
+
// SETUP
|
|
16
|
+
// ===========================================
|
|
17
|
+
|
|
18
|
+
const backend = new SemanticBackend({ dimension: 16 });
|
|
19
|
+
|
|
20
|
+
console.log('TinyAleph DNA-Inspired Encoding Example');
|
|
21
|
+
console.log('=======================================\n');
|
|
22
|
+
|
|
23
|
+
// ===========================================
|
|
24
|
+
// BIDIRECTIONAL PROCESSING
|
|
25
|
+
// ===========================================
|
|
26
|
+
|
|
27
|
+
console.log('Bidirectional Processing (Boustrophedon):');
|
|
28
|
+
console.log('-'.repeat(50) + '\n');
|
|
29
|
+
|
|
30
|
+
const text = 'The quick brown fox jumps over the lazy dog';
|
|
31
|
+
|
|
32
|
+
// Tokenize first
|
|
33
|
+
const tokens = backend.encodeOrdered(text);
|
|
34
|
+
|
|
35
|
+
// Standard forward encoding
|
|
36
|
+
const forwardState = backend.textToOrderedState(text);
|
|
37
|
+
|
|
38
|
+
// Bidirectional encoding (alternating direction per line)
|
|
39
|
+
const bidirectionalState = backend.bidirectionalState(tokens);
|
|
40
|
+
|
|
41
|
+
console.log('Input: "' + text + '"\n');
|
|
42
|
+
|
|
43
|
+
// Show how bidirectional differs
|
|
44
|
+
console.log('Forward state (first 4 components):');
|
|
45
|
+
console.log(' [' + forwardState.c.slice(0, 4).map(function(v) { return v.toFixed(4); }).join(', ') + ']');
|
|
46
|
+
|
|
47
|
+
console.log('\nBidirectional state (first 4 components):');
|
|
48
|
+
console.log(' [' + bidirectionalState.c.slice(0, 4).map(function(v) { return v.toFixed(4); }).join(', ') + ']');
|
|
49
|
+
|
|
50
|
+
// Similarity between approaches
|
|
51
|
+
function similarity(s1, s2) {
|
|
52
|
+
var dot = 0, m1 = 0, m2 = 0;
|
|
53
|
+
for (var i = 0; i < s1.c.length; i++) {
|
|
54
|
+
dot += s1.c[i] * s2.c[i];
|
|
55
|
+
m1 += s1.c[i] * s1.c[i];
|
|
56
|
+
m2 += s2.c[i] * s2.c[i];
|
|
57
|
+
}
|
|
58
|
+
return dot / (Math.sqrt(m1) * Math.sqrt(m2) || 1);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
var simValue = similarity(forwardState, bidirectionalState) * 100;
|
|
62
|
+
console.log('\nSimilarity between approaches: ' + simValue.toFixed(1) + '%');
|
|
63
|
+
|
|
64
|
+
// ===========================================
|
|
65
|
+
// CODON-STYLE TRIPLET CHUNKING
|
|
66
|
+
// ===========================================
|
|
67
|
+
|
|
68
|
+
console.log('\n' + '='.repeat(50));
|
|
69
|
+
console.log('Codon-Style Triplet Chunking:');
|
|
70
|
+
console.log('='.repeat(50) + '\n');
|
|
71
|
+
|
|
72
|
+
// Tokenize first (reuse tokens from above)
|
|
73
|
+
console.log('Tokens: [' + tokens.slice(0, 6).map(function(t) { return t.word; }).join(', ') + '...] (' + tokens.length + ' total)\n');
|
|
74
|
+
|
|
75
|
+
// Create codons (triplets)
|
|
76
|
+
var codons = backend.tokensToCodons(tokens);
|
|
77
|
+
console.log('Codons (triplets of primes):');
|
|
78
|
+
for (var i = 0; i < Math.min(4, codons.length); i++) {
|
|
79
|
+
var codonPrimes = codons[i].primes || codons[i];
|
|
80
|
+
console.log(' Codon ' + (i + 1) + ': [' + codonPrimes.join(', ') + ']');
|
|
81
|
+
}
|
|
82
|
+
console.log(' ... (' + codons.length + ' codons total)');
|
|
83
|
+
|
|
84
|
+
// ===========================================
|
|
85
|
+
// 6-FRAME READING
|
|
86
|
+
// ===========================================
|
|
87
|
+
|
|
88
|
+
console.log('\n' + '='.repeat(50));
|
|
89
|
+
console.log('6-Frame Reading (Like DNA Translation):');
|
|
90
|
+
console.log('='.repeat(50) + '\n');
|
|
91
|
+
|
|
92
|
+
console.log('DNA has 6 reading frames:');
|
|
93
|
+
console.log(' Forward: +1 (start at 0), +2 (start at 1), +3 (start at 2)');
|
|
94
|
+
console.log(' Reverse: -1 (reverse, start at 0), -2 (reverse, start at 1), -3 (reverse, start at 2)');
|
|
95
|
+
console.log('');
|
|
96
|
+
|
|
97
|
+
var frames = backend.readingFrameStates(tokens);
|
|
98
|
+
|
|
99
|
+
console.log('Reading frame embeddings:');
|
|
100
|
+
for (var i = 0; i < frames.length; i++) {
|
|
101
|
+
var frame = frames[i];
|
|
102
|
+
var state = frame.state;
|
|
103
|
+
var norm = state.norm();
|
|
104
|
+
var firstComp = state.c[0].toFixed(4);
|
|
105
|
+
var frameName = frame.direction + '_' + frame.offset;
|
|
106
|
+
console.log(' ' + frameName + ': norm=' + norm.toFixed(4) + ', c[0]=' + firstComp);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Compare frame similarities
|
|
110
|
+
console.log('\nFrame similarity matrix:');
|
|
111
|
+
var frameNames = frames.map(function(f) { return f.direction + '_' + f.offset; });
|
|
112
|
+
var frameStates = frames.map(function(f) { return f.state; });
|
|
113
|
+
|
|
114
|
+
process.stdout.write(' ');
|
|
115
|
+
for (var n = 0; n < frameNames.length; n++) {
|
|
116
|
+
process.stdout.write(frameNames[n].padStart(6));
|
|
117
|
+
}
|
|
118
|
+
console.log();
|
|
119
|
+
|
|
120
|
+
for (var i = 0; i < frameNames.length; i++) {
|
|
121
|
+
process.stdout.write(frameNames[i].padEnd(5));
|
|
122
|
+
for (var j = 0; j < frameNames.length; j++) {
|
|
123
|
+
var sim = similarity(frameStates[i], frameStates[j]) * 100;
|
|
124
|
+
process.stdout.write(sim.toFixed(0).padStart(5) + '%');
|
|
125
|
+
}
|
|
126
|
+
console.log();
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// ===========================================
|
|
130
|
+
// SENSE/ANTISENSE DUALITY
|
|
131
|
+
// ===========================================
|
|
132
|
+
|
|
133
|
+
console.log('\n' + '='.repeat(50));
|
|
134
|
+
console.log('Sense/Antisense Duality:');
|
|
135
|
+
console.log('='.repeat(50) + '\n');
|
|
136
|
+
|
|
137
|
+
console.log('In DNA, each strand has a complement:');
|
|
138
|
+
console.log(' - Sense strand: carries the coding information');
|
|
139
|
+
console.log(' - Antisense strand: complementary, reversed');
|
|
140
|
+
console.log('');
|
|
141
|
+
console.log('TinyAleph creates dual representations by:');
|
|
142
|
+
console.log(' 1. Sense: forward prime encoding');
|
|
143
|
+
console.log(' 2. Antisense: reversed token sequence');
|
|
144
|
+
console.log('');
|
|
145
|
+
|
|
146
|
+
var dual = backend.dualRepresentation(tokens);
|
|
147
|
+
|
|
148
|
+
console.log('Sense strand (forward):');
|
|
149
|
+
console.log(' First 4: [' + dual.sense.c.slice(0, 4).map(function(v) { return v.toFixed(3); }).join(', ') + ']');
|
|
150
|
+
|
|
151
|
+
console.log('\nAntisense strand (reversed):');
|
|
152
|
+
console.log(' First 4: [' + dual.antisense.c.slice(0, 4).map(function(v) { return v.toFixed(3); }).join(', ') + ']');
|
|
153
|
+
|
|
154
|
+
var dualSim = similarity(dual.sense, dual.antisense) * 100;
|
|
155
|
+
console.log('\nSense-Antisense similarity: ' + dualSim.toFixed(1) + '%');
|
|
156
|
+
|
|
157
|
+
// ===========================================
|
|
158
|
+
// DNA ENCODING
|
|
159
|
+
// ===========================================
|
|
160
|
+
|
|
161
|
+
console.log('\n' + '='.repeat(50));
|
|
162
|
+
console.log('Full DNA Encoding:');
|
|
163
|
+
console.log('='.repeat(50) + '\n');
|
|
164
|
+
|
|
165
|
+
var dnaResult = backend.dnaEncode(text);
|
|
166
|
+
|
|
167
|
+
console.log('DNA encoding produces:');
|
|
168
|
+
console.log(' - Combined state (all frames merged)');
|
|
169
|
+
console.log(' - Dual representation (sense + antisense)');
|
|
170
|
+
console.log(' - Reading frames (6 offset encodings)');
|
|
171
|
+
console.log(' - Codons (triplet groupings)');
|
|
172
|
+
|
|
173
|
+
console.log('\nCombined state norm: ' + dnaResult.combined.norm().toFixed(4));
|
|
174
|
+
console.log('Number of codons: ' + dnaResult.codons.length);
|
|
175
|
+
console.log('Frames available: ' + Object.keys(dnaResult.frames).join(', '));
|
|
176
|
+
|
|
177
|
+
// ===========================================
|
|
178
|
+
// PRACTICAL APPLICATION: ROBUST MATCHING
|
|
179
|
+
// ===========================================
|
|
180
|
+
|
|
181
|
+
console.log('\n' + '='.repeat(50));
|
|
182
|
+
console.log('Practical Application: Robust Text Matching');
|
|
183
|
+
console.log('='.repeat(50) + '\n');
|
|
184
|
+
|
|
185
|
+
var documents = [
|
|
186
|
+
'The quick brown fox jumps over the lazy dog',
|
|
187
|
+
'A fast brown fox leaps over a sleepy dog',
|
|
188
|
+
'The lazy dog was jumped over by a quick fox',
|
|
189
|
+
'Machine learning algorithms process data'
|
|
190
|
+
];
|
|
191
|
+
|
|
192
|
+
console.log('Using DNA encoding for robust similarity:\n');
|
|
193
|
+
|
|
194
|
+
var query = 'brown fox jumps lazy dog';
|
|
195
|
+
var queryDna = backend.dnaEncode(query);
|
|
196
|
+
|
|
197
|
+
for (var d = 0; d < documents.length; d++) {
|
|
198
|
+
var doc = documents[d];
|
|
199
|
+
var docDna = backend.dnaEncode(doc);
|
|
200
|
+
|
|
201
|
+
// Compare using combined states
|
|
202
|
+
var combinedSim = similarity(queryDna.combined, docDna.combined);
|
|
203
|
+
|
|
204
|
+
// Compare sense-to-sense
|
|
205
|
+
var senseSim = similarity(queryDna.dual.sense, docDna.dual.sense);
|
|
206
|
+
|
|
207
|
+
// Compare sense-to-antisense (for reversed order matches)
|
|
208
|
+
var crossSim = similarity(queryDna.dual.sense, docDna.dual.antisense);
|
|
209
|
+
|
|
210
|
+
var maxSim = Math.max(combinedSim, senseSim, crossSim);
|
|
211
|
+
|
|
212
|
+
console.log('"' + doc.substring(0, 45) + '..."');
|
|
213
|
+
console.log(' Combined: ' + (combinedSim * 100).toFixed(1) + '%, Sense: ' + (senseSim * 100).toFixed(1) + '%, Cross: ' + (crossSim * 100).toFixed(1) + '%');
|
|
214
|
+
console.log(' Best match: ' + (maxSim * 100).toFixed(1) + '%\n');
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// ===========================================
|
|
218
|
+
// KEY TAKEAWAYS
|
|
219
|
+
// ===========================================
|
|
220
|
+
|
|
221
|
+
console.log('='.repeat(50));
|
|
222
|
+
console.log('KEY TAKEAWAYS:');
|
|
223
|
+
console.log('1. Bidirectional encoding captures reading patterns');
|
|
224
|
+
console.log('2. Codon triplets group related tokens');
|
|
225
|
+
console.log('3. 6 reading frames provide multiple perspectives');
|
|
226
|
+
console.log('4. Sense/antisense handles word order variation');
|
|
227
|
+
console.log('5. DNA encoding enables robust text matching');
|
|
228
|
+
console.log('6. Combined representations merge all frames');
|