TensorFlow.js — это библиотека для машинного обучения на JavaScript,
которая позволяет создавать, обучать и использовать модели прямо в
браузере или на сервере с Node.js. Основной элемент работы с библиотекой
— это тензоры (tf.Tensor), которые
являются многомерными массивами чисел, поддерживающими автоматическое
дифференцирование.
Для построения модели трансформера используется набор ключевых компонентов: эмбеддинги, механизмы внимания, слои нормализации и позиционные кодировки. Каждая часть играет критическую роль в способности модели обрабатывать последовательности данных.
Тензоры создаются из массивов Jav * aScript:
const tf = require('@tensorflow/tfjs');
const a = tf.tensor([1, 2, 3, 4]);
const b = tf.tensor2d([[1, 2], [3, 4]]);
Ключевые операции включают matMul для матричного
умножения, add, sub, mul и
div для арифметических операций, а также функции активации
(relu, softmax).
Поскольку трансформеры не используют рекуррентные сети, они требуют позиционной информации. Позиционная кодировка добавляется к эмбеддингам входных токенов:
function positionalEncoding(maxLen, dModel) {
const pos = tf.range(0, maxLen);
const i = tf.range(0, dModel, 2);
const angleRates = tf.div(pos.expandDims(1), tf.pow(10000, tf.div(i, dModel)));
const sinEncoding = tf.sin(angleRates);
const cosEncoding = tf.cos(angleRates);
return tf.concat([sinEncoding, cosEncoding], -1);
}
Ключевой момент: позиционная кодировка позволяет модели различать порядок элементов в последовательности, сохраняя параллельную обработку.
Self-Attention — центральная часть трансформера. Он вычисляет вес каждого элемента последовательности относительно всех остальных:
Q), ключи (K) и
значения (V) через линейные слои:function denseLayer(input, units) {
return tf.layers.dense({ units }).apply(input);
}
const Q = denseLayer(inputTensor, dModel);
const K = denseLayer(inputTensor, dModel);
const V = denseLayer(inputTensor, dModel);
function scaledDotProductAttention(Q, K, V) {
const matmulQK = tf.matMul(Q, K, false, true);
const dk = tf.scalar(K.shape[K.shape.length - 1], 'float32');
const scaledScores = tf.div(matmulQK, tf.sqrt(dk));
const attentionWeights = tf.softmax(scaledScores);
return tf.matMul(attentionWeights, V);
}
Особенности реализации:
dModel.Многоголовое внимание позволяет модели одновременно учитывать разные представления последовательности:
function multiHeadAttention(input, numHeads, dModel) {
const depth = dModel / numHeads;
const heads = [];
for (let i = 0; i < numHeads; i++) {
const Q = denseLayer(input, depth);
const K = denseLayer(input, depth);
const V = denseLayer(input, depth);
const head = scaledDotProductAttention(Q, K, V);
heads.push(head);
}
return tf.concat(heads, -1);
}
Трансформеры используют layer normalization и residual connections для стабильного обучения:
function addResidualNorm(x, sublayer) {
const out = tf.add(x, sublayer(x));
return tf.layers.layerNormalization().apply(out);
}
Это помогает сохранять градиенты и ускоряет сходимость.
Энкодер состоит из N одинаковых блоков, каждый из которых включает:
Пример одного блока:
function encoderBlock(input, numHeads, dModel, dff) {
const attnOutput = addResidualNorm(input, x => multiHeadAttention(x, numHeads, dModel));
const ffnOutput = addResidualNorm(attnOutput, x => tf.layers.dense({ units: dff, activation: 'relu' }).apply(x));
return ffnOutput;
}
Блоки энкодера можно стекать, формируя полную модель:
let encoderOutput = inputEmbedding;
for (let i = 0; i < numBlocks; i++) {
encoderOutput = encoderBlock(encoderOutput, numHeads, dModel, dff);
}
Feed-Forward слой применяет нелинейное преобразование к каждому элементу последовательности:
const ffn = tf.sequential();
ffn.add(tf.layers.dense({ units: dff, activation: 'relu' }));
ffn.add(tf.layers.dense({ units: dModel }));
Он повышает способность модели захватывать сложные зависимости.
Для обучения трансформера применяются стандартные методы TensorFlow.js:
model.compile({
optimizer: tf.train.adam(0.001),
loss: tf.losses.softmaxCrossEntropy,
metrics: ['accuracy']
});
Важно учитывать:
При генерации текста используется автогенерация по одному токену с маской, чтобы модель не видела будущие элементы:
function generateNextToken(inputSeq) {
const logits = model.predict(inputSeq);
const nextToken = tf.argMax(logits.slice([-1, 1]), -1);
return nextToken;
}
Механизм attention и позиционные кодировки обеспечивают правильный порядок и согласованность генерируемого текста.
TensorFlow.js позволяет полностью реализовать упрощённый трансформер на JavaScript, используя стандартные компоненты: тензоры, слои Dense, LayerNormalization, softmax и матричные операции. Правильная организация внимания, позиционной информации и feed-forward слоев обеспечивает базовую функциональность современных трансформеров, пригодную для экспериментов и обучения небольших моделей прямо в браузере.