Keras.js — это библиотека для выполнения моделей Keras прямо в браузере с использованием JavaScript. При работе с данными, полученными из модели или подаваемыми на вход, часто требуется манипулировать многомерными массивами — тензорами. Основной инструмент для этого — индексирование и срезы.
В Keras.js данные представлены в виде объектов Tensor.
Тензор — это многомерный массив с фиксированной размерностью. Каждый
тензор имеет атрибуты:
shape — массив, определяющий размеры по каждой
оси.data — одномерный массив, содержащий значения тензора в
линейном виде.Например, тензор формы [2, 3, 4] содержит 2 * 3 * 4 = 24
элемента в data. Фактическая организация данных одномерная,
поэтому для доступа к элементу требуется индексация с расчётом
смещения.
Одномерный тензор индексируется напрямую:
const tensor = new KerasJS.Tensor({data: [1, 2, 3, 4], shape: [4]});
console.log(tensor.data[2]); // 3
console.log(tensor.data[-1 + tensor.shape[0]]); // 4
Для многомерных тензоров необходимо вычислять линейный индекс:
const tensor = new KerasJS.Tensor({data: Array.from({length: 24}, (_, i) => i+1), shape: [2, 3, 4]});
Чтобы получить элемент [i, j, k], используется
формула:
linear_index = i * (shape[1]*shape[2]) + j * shape[2] + k
Пример:
const i = 1, j = 2, k = 3;
const linearIndex = i * (3*4) + j * 4 + k; // 1*12 + 2*4 + 3 = 23
console.log(tensor.data[linearIndex]); // 24
Ключевой момент: Keras.js хранит данные в row-major порядке (C-style), что важно при работе с индексами.
Срезы позволяют выделять подмассивы тензора по определённым
диапазонам индексов. В Keras.js нет встроенного синтаксиса
tensor[:, 1:3, :], как в Python, поэтому срезы реализуются
вручную через методы:
sliceTensor(startIndices, endIndices) — возвращает
новый тензор.Параметры:
startIndices — массив начальных индексов для каждой
оси.endIndices — массив конечных индексов (не
включая).Пример:
const slice = tensor.sliceTensor([0,1,0],[2,3,4]);
Это соответствует Python-подобному срезу
[0:2,1:3,0:4].
Для реализации шага (step) нужно вручную вычислить линейные индексы:
function sliceWithStep(tensor, axis, step) {
const shape = tensor.shape;
const newData = [];
const stride = shape.slice(axis+1).reduce((a,b)=>a*b,1);
const repeat = shape.slice(0,axis).reduce((a,b)=>a*b,1);
for(let r=0;r<repeat;r++){
for(let i=0;i<shape[axis];i+=step){
const base = r * stride * shape[axis] + i * stride;
for(let j=0;j<stride;j++){
newData.push(tensor.data[base+j]);
}
}
}
const newShape = shape.slice();
newShape[axis] = Math.ceil(shape[axis]/step);
return new KerasJS.Tensor({data: newData, shape: newShape});
}
Для выборки элементов по условию создаются булевы маски. В Keras.js это делается вручную через фильтрацию:
const tensor = new KerasJS.Tensor({data: [1,2,3,4,5], shape: [5]});
const mask = tensor.data.map(v => v % 2 === 0);
const filteredData = tensor.data.filter((v,i)=>mask[i]);
const filteredTensor = new KerasJS.Tensor({data: filteredData, shape: [filteredData.length]});
Это аналог tensor[tensor % 2 === 0] в NumPy/Keras.
После среза или фильтрации необходимо корректно задавать
shape. Пропуск этого шага приведёт к несоответствию данных
и размерности:
const newTensor = new KerasJS.Tensor({data: slicedData, shape: [2,2]});
shape) должна совпадать с количеством
элементов.tensor.shape перед
индексированием.[i,j,k] и линейным индексом.: напрямую.Индексирование и срезы — фундаментальная часть работы с тензорами в Keras.js. Грамотное использование этих методов позволяет эффективно управлять данными, подаваемыми на вход или получаемыми с выхода модели, обеспечивая корректность вычислений и оптимальное использование памяти.