В задачах глубокого обучения понимание работы нейронной сети часто требует анализа промежуточных представлений данных. Карты активаций позволяют визуализировать реакцию каждого фильтра сверточного слоя на входные данные, выявлять признаки, извлекаемые сетью, и оценивать качество обучения.
Активация слоя — это выходной тензор, получаемый после применения слоя к входным данным и функции активации. Для сверточных сетей это многомерный массив, где:
Карты активаций отражают интенсивность реакции каждого фильтра на различные участки изображения. Яркие или насыщенные участки карты показывают, какие признаки сети оказались важными.
TensorFlow.js позволяет работать с активациями напрямую через модель
и слои. Для этого используется метод model.execute или
извлечение промежуточного слоя через
tf.model({inputs, outputs}).
Пример:
import * as tf from '@tensorflow/tfjs';
// Загрузка модели
const model = await tf.loadLayersModel('model.json');
// Выбор промежуточного слоя по имени
const layerName = 'conv2d_1';
const intermediateLayerModel = tf.model({
inputs: model.inputs,
outputs: model.getLayer(layerName).output
});
// Преобразование изображения в тензор
const imgTensor = tf.browser.fromPixels(imageElement)
.resizeNearestNeighbor([224, 224])
.expandDims(0)
.toFloat()
.div(tf.scalar(255));
// Получение активаций
const activations = intermediateLayerModel.predict(imgTensor);
В результате переменная activations будет содержать
тензор размером [1, height, width, filters]. Для
визуализации его нужно преобразовать в удобный формат.
Для визуализации каждой карты активации используют нормализацию значений и преобразование канала в изображение. Часто применяется мини-батч по фильтрам, например:
const activationData = activations.squeeze().arraySync(); // shape: [height, width, filters]
const numFilters = activationData[0][0].length;
for (let i = 0; i < numFilters; i++) {
const filter = activationData.map(row => row.map(pixel => pixel[i]));
const normalized = normalizeArray(filter); // функция нормализации в диапазон [0, 255]
renderCanvas(normalized, `filter-${i}`); // функция отрисовки на canvas
}
Нормализация часто выполняется через:
function normalizeArray(arr) {
const flat = arr.flat();
const min = Math.min(...flat);
const max = Math.max(...flat);
return arr.map(row => row.map(value => ((value - min) / (max - min)) * 255));
}
Чтобы сравнивать активируемые признаки, удобно отображать карты фильтров в виде сетки:
function renderGrid(activationArray, gridSize = 8) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const cellSize = 64; // размер каждой карты в пикселях
canvas.width = gridSize * cellSize;
canvas.height = gridSize * cellSize;
for (let i = 0; i < Math.min(gridSize * gridSize, activationArray.length); i++) {
const row = Math.floor(i / gridSize);
const col = i % gridSize;
const imageData = ctx.createImageData(cellSize, cellSize);
const normalized = resizeArray(activationArray[i], cellSize, cellSize);
for (let y = 0; y < cellSize; y++) {
for (let x = 0; x < cellSize; x++) {
const index = (y * cellSize + x) * 4;
const value = normalized[y][x];
imageData.data[index] = value;
imageData.data[index + 1] = value;
imageData.data[index + 2] = value;
imageData.data[index + 3] = 255;
}
}
ctx.putImageData(imageData, col * cellSize, row * cellSize);
}
document.body.appendChild(canvas);
}
Функция resizeArray выполняет интерполяцию значений до
нужного размера, сохраняя пропорции визуализации.
Визуализация активаций помогает:
Использование TensorFlow.js позволяет выполнять эти операции непосредственно в браузере, что удобно для интерактивных экспериментов и быстрого прототипирования.