Appearance
16. Анатомия многомерных тензоров (3D+) в компьютерном зрении и NLP
Структуры данных в Computer Vision и NLP
Переход к N-мерным пространствам (Тензорам)
В реальных задачах глубокого обучения (Deep Learning) данных в виде одномерных векторов или двумерных матриц часто недостаточно. Объекты реального мира обладают большей вложенностью структур. В NumPy многомерные массивы размерностью
Принцип их устройства «под капотом» остается прежним: это все тот же линейный непрерывный блок памяти на C-уровне, но метаданные заголовка описывают сложную геометрию из 3, 4 и более осей (ndim >= 3), переходы между которыми контролируются многомерными шагами (strides).
Структуры данных в Компьютерном Зрении (Computer Vision)
Для обработки изображений нейросетями используются строго фиксированные стандарты размерностей:
- Одиночное цветное изображение (3D-тензор): Описывается формой
[Height, Width, Channels].
Height— высота в пикселях,Width— ширина,Channels— цветовые каналы (обычно 3 канала для RGB: красный, зеленый, синий).
- Батч (порция) изображений для сверточных сетей (4D-тензор): Компьютер обрабатывает картинки пачками. Такая структура кодируется как
[Batch, Height, Width, Channels]. Например, тензор формы(32, 224, 224, 3)означает пакет из 32 картинок размером 224x224 пикселя с 3 RGB-каналами.
Структуры данных в обработке текста (NLP) и Трансформерах
В текстовых моделях (например, GPT, BERT) данные организуются совершенно иначе:
- Батч (порции) текстовых последовательностей (3D-тензор): Описывается формой
[Batch, Seq_Len, Hidden_Dim].Batch— количество предложений (текстов) в обрабатываемой пачке.Seq_Len(Sequence Length) — длина предложения в токенах (словах или подсловах).Hidden_Dim(Hidden Dimension) — размерность вектора эмбеддинга. Каждый токен кодируется плотным вектором чисел, отражающим его семантический смысл (например, 768 или 1024 числа на один токен).
python
import numpy
# Simulating an NLP Transformer input batch: 2 sentences, 4 tokens each, vector size 5
# Shape contract: [Batch, Seq_Len, Hidden_Dim]
nlp_tensor = numpy.ones((2, 4, 5), dtype=numpy.float32)
print("Tensors dimension count:", nlp_tensor.ndim) # Outputs: 3
print("Tensor structural shape:", nlp_tensor.shape) # Outputs: (2, 4, 5)Понятие эмбеддингов (Embeddings) и их размерности
При работе с текстом, аудио или графикой в искусственном интеллекте компьютеры не могут напрямую оперировать словами или абстрактными образами. Для этого используется технология эмбеддингов (Embeddings).
Эмбеддинг — это способ представления объекта (например, слова или токена текста) в виде плотного вектора вещественных чисел, который отражает его скрытый смысл и контекст. В отличие от старых методов кодирования (вроде One-Hot Encoding), эмбеддинги позволяют математически вычислять схожесть понятий. Слова «кошка» и «собака» в пространстве эмбеддингов будут находиться близко друг к другу, а слово «небоскреб» — далеко от них.
Что значит «Плотный вектор чисел» (Dense Vector)?
В NumPy плотный вектор — это классический одномерный массив ndarray типа float32 или float64, в котором каждая ячейка заполнена значимым числом (обычно в диапазоне от -1.0 до 1.0).
- Разреженный вектор (Sparse Vector): Огромный массив из тысяч нулей, где лишь в одном месте стоит единица (
[0, 0, 0, 1, 0, 0, ...]). Неэффективно расходует память. - Плотный вектор (Dense Vector): Компактный массив, где каждое число кодирует определенный микро-признак слова (
[-0.12, 0.45, 0.89, -0.31, ...]).
Размерность вектора эмбеддинга (Embedding Dimension)
Размерность (длина вектора) определяет, сколько именно чисел выделяется на кодирование смысла одного токена. В коде это обозначается как embedding_dim или d_model.
Каждое число внутри вектора отвечает за определенную абстрактную характеристику, которую нейросеть вывела самостоятельно в процессе обучения (например, одушевленность, род, отношение к технологиям, эмоциональный окрас):
- В простых моделях (например, Word2Vec) размерность обычно равна 300.
- В современных трансформерах (BERT) размерность составляет 768.
- В мощных LLM (GPT-4, LLaMA) размерность одного токена может достигать 4096 чисел и более.
Пример. Анатомия токена и его размерности в NumPy
Рассмотрим, как один текстовый токен (слово «AI») превращается в плотный вектор с размерностью dim=8 (для наглядности размерность уменьшена):
python
import numpy as np
# A real token ID from a vocabulary (e.g., word "AI" equals token 2467)
token_id = 2467
# A dense embedding vector for this token (Embedding Dimension = 8)
# Each float value represents a hidden semantic feature learned by the AI
ai_token_embedding = np.array([0.15, -0.62, 0.88, 0.04, -0.11, 0.93, -0.42, 0.21], dtype=np.float32)
# Checking the dimensionality (length of the vector)
print(f"Token vector shape: {ai_token_embedding.shape}") # Outputs: (8,)
print(f"Embedding dimension size: {len(ai_token_embedding)}") # Outputs: 8Визуализация смысла через геометрию
Благодаря тому, что токен становится вектором чисел, мы можем измерять расстояние между словами с помощью стандартных векторных ufuncs-операций NumPy. Например, если вычесть из эмбеддинга слова «Король» эмбеддинг слова «Мужчина» и прибавить эмбеддинг слова «Женщина», математический вектор результата окажется максимально близким к эмбеддингу слова «Королева».
Срезы многомерных пространств
Правила многомерных срезов
Логика срезов в N-мерных пространствах является прямым продолжением двумерного слайсинга. Внутри квадратных скобок параметры каждой оси перечисляются через запятую: tensor[batch_idx, height_idx, width_idx, channel_idx]
Если по какой-то оси требуется забрать элементы целиком, используется символ двоеточия :.
Практические сценарии извлечения подмассивов
При работе с изображениями и текстом многомерный слайсинг применяется для решения следующих задач:
- Вычленение конкретного объекта из батча: Срез
image_batch[0, :, :, :](или сокращенноimage_batch[0]) извлечет самую первую картинку из пакета, сохранив её 3D-структуру[Height, Width, Channels]. - Изоляция цветового канала: Срез
image_batch[:, :, :, 0]соберет только нулевой (Красный — R) канал для абсолютно всех картинок внутри батча. - Кроп (Cropping): Обрезание краев изображения по осям высоты и ширины:
image[40:160, 40:160, :].
python
import numpy
# Simulating a mini-batch of 2 color images, 100x100 pixels each
# Shape layout: [Batch, Height, Width, Channels]
image_batch = numpy.zeros((2, 100, 100, 3), dtype=numpy.uint8)
# Extracting the second image from the batch
single_image = image_batch[1, :, :, :]
print("Single image shape:", single_image.shape) # Outputs: (100, 100, 3)
# Extracting only the Green channel (index 1) for the first image
green_channel = image_batch[0, :, :, 1]
print("Green channel slice shape:", green_channel.shape) # Outputs 2D grid: (100, 100)Упражнения базовые (5 шт) (только с опорой на объясненную в данном уроке теорию)
1. Конструирование 3D-тензора цветного изображения
Задача: Инициализируйте пустой 3D-тензор, имитирующий одиночное цветное RGB-изображение размером 480 пикселей по высоте и 640 пикселей по ширине, полностью заполненный нулями. Выведите его структуру .shape и вес в килобайтах.
Посмотреть решение
python
import numpy
# Allocation syntax for a 3D image tensor: [Height, Width, Channels]
rgb_image = numpy.zeros((480, 640, 3), dtype=numpy.uint8)
print("Image geometry shape:", rgb_image.shape) # Outputs: (480, 640, 3)
print("Image weight kilobytes:", rgb_image.nbytes//1024, 'kB') # Outputs: 9002. Извлечение отдельного предложения из батча Трансформера
Задача: Дан 3D-тензор текстовых эмбеддингов nlp_batch = numpy.ones((4, 12, 768)), содержащий пакет из 4 предложений. Используя многомерный срез, извлеките из батча целиком третье предложение (индекс 2), включая все его токены и их эмбеддинги. Выведите форму (shape) полученного подмассива.
Посмотреть решение
python
import numpy
nlp_batch = numpy.ones((4, 12, 768))
# Extracting the 3rd sample while preserving all tokens and hidden dimensions
single_sentence = nlp_batch[2, :, :]
print("Extracted sentence shape:", single_sentence.shape) # Outputs: (12, 768)3. Изоляция Синего (Blue) канала в батче картинок
Задача: Сгенерируйте 4D-тензор батча изображений images_tensor = numpy.ones((8, 224, 224, 3)) (8 картинок формата 224x224x3). С помощью одного многомерного среза извлеките Синий цветовой канал (индекс 2) для всех картинок батча одновременно. Выведите форму полученного результата.
Посмотреть решение
python
import numpy
images_tensor = numpy.ones((8, 224, 224, 3))
# Using ':' to capture all items along Batch, Height, and Width axes
blue_channels_batch = images_tensor[:, :, :, 2]
print("Blue channels projection shape:", blue_channels_batch.shape) # Outputs: (8, 224, 224)4. Извлечение конкретного токена из структуры данных NLP
Задача: Дан 3D-тензор текстовой последовательности text_tensor = numpy.ones((2, 10, 512)) (2 предложения, по 10 токенов в каждом, размер эмбеддинга 512). Извлеките вектор эмбеддинга для самого первого токена (индекс 0) во втором предложении (индекс 1). Выведите геометрию полученного вектора.
Посмотреть решение
python
import numpy
text_tensor = numpy.ones((2, 10, 512))
# Pinpointing specific batch and token positions, capturing the whole embedding axis
token_embedding_vector = text_tensor[1, 0, :]
print("Token vector dimensions:", token_embedding_vector.shape) # Outputs: (512,)5. Обрезание краев изображения (Центральный кроп)
Задача: Имеется 3D-массив фотографии photo = numpy.ones((300, 300, 3)). Выполните операцию кроппинга — вырежьте центральный квадратный фрагмент с координатами по высоте от 100 до 200 (не включая верхнюю границу) и по ширине от 100 до 200, сохранив все цветовые каналы. Выведите форму кропнутого массива.
Посмотреть решение
python
import numpy
photo = numpy.ones((300, 300, 3))
# Slicing bounding regions on structural axes, keeping channels intact
cropped_photo = photo[100:200, 100:200, :]
print("Cropped image geometry shape:", cropped_photo.shape) # Outputs: (100, 100, 3)Упражнения смешанные (5 шт) (включают материал прошлых уроков)
6. Глобальный аудит характеристик и шагов многомерного тензора
Задача: Создайте 3D-тензор текстовых батчей размерностью (2, 3, 4) из целых чисел с явным указанием типа данных dtype=numpy.int32 (Урок 4 / Урок 16). Выведите на экран его базовые метаданные: общее число элементов .size, физический вес в байтах .nbytes (Урок 2) и шаг в памяти .strides (Урок 11). Прочитайте комментарий к решению, объясняющий физическое устройство 3D-шагов.
Посмотреть решение
python
import numpy
# Setting up a structured 3D coordinate block tensor (Lesson 4 & Lesson 16)
text_tensor = numpy.ones((2, 3, 4), dtype=numpy.int32)
print("Total items:", text_tensor.size) # 2 * 3 * 4 = 24 elements
print("Byte size:", text_tensor.nbytes, "bytes") # 24 elements * 4 bytes = 96 bytes
# Strides analysis in 3D block layouts (Lesson 2 & Lesson 11)
print("Tensor strides layout:", text_tensor.strides) # Outputs: (48, 16, 4)
# Explanation: Each int32 is 4 bytes. Moving 1 item right takes 4 bytes.
# Moving 1 token down forces skipping an entire row of 4 items (4 * 4 = 16 bytes).
# Moving 1 batch block forces skipping 3 rows of tokens (3 * 16 = 48 bytes).7. Поэлементная маска и in-place модификация канала батча изображений
Задача: Сгенерируйте 4D-тензор батча масок цветных картинок image_batch = numpy.ones((2, 10, 10, 3), dtype=numpy.float32) (Урок 11 / Урок 16). Выделите из него Синий канал (индекс 2) для первой картинки (индекс 0) через многомерный срез (Урок 16). Умножьте элементы этого канала на месте (in-place) на скаляр 0.0 через оператор *= (Урок 8). Выведите форму всего батча и убедитесь через проверку мутаций, что исходный тензор изменил значения в буфере памяти (Урок 6).
Посмотреть решение
python
import numpy
image_batch = numpy.ones((2, 10, 10, 3), dtype=numpy.float32)
# Extracting a specific 2D matrix channel view slice (Lesson 13 & Lesson 16)
blue_channel_view = image_batch[0, :, :, 2]
# Perform in-place multiplication optimization (Lesson 8)
blue_channel_view *= 0.0
# Verifying array states and metadata preservation (Lesson 6 & Lesson 11)
print("Original batch architecture remains:", image_batch.shape) # (2, 10, 10, 3)
print("Check if changes propagated to root memory:", image_batch[0, 0, 0, 2]) # Outputs: 0.08. Матричная агрегация по осям внутри извлеченного NLP-батча
Задача: Дан 3D-тензор скрытых состояний Трансформера hidden_states = numpy.ones((2, 5, 3)) (Урок 16). Выделите из него срез, содержащий только первое предложение (индекс 0) (Урок 13). Для полученной 2D-матрицы посчитайте вектор средних значений вдоль столбцов (axis=0), то есть усредните скрытые фичи по всем токенам последовательности (Урок 15). Выведите форму результирующего вектора.
Посмотреть решение
python
import numpy
hidden_states = numpy.ones((2, 5, 3))
# Step 1: Extract flat matrix view from 3D block space (Lesson 13 & Lesson 16)
first_sample_matrix = hidden_states[0, :, :] # Shape: (5, 3)
# Step 2: Perform feature reduction along columns axis (Lesson 15)
features_mean_vector = first_sample_matrix.mean(axis=0)
print("Averaged feature vector content:", features_mean_vector) # Outputs: [1. 1. 1.]
print("Final vector geometry shape:", features_mean_vector.shape) # Outputs: (3,)9. Квантование и изолированное копирование текстового батча
Задача: Имеется 3D-тензор сырых распределений вероятностей символов text_scores = numpy.ones((2, 4, 3)) (Урок 16). Преобразуйте его в целочисленный квантованный формат numpy.int8 с помощью метода .astype() (Урок 4 / Урок 7). Чтобы защитить лог, сделайте полную изолированную копию полученного тензора через .copy() (Урок 6). С помощью numpy.isnan() докажите в комментарии, почему в целочисленных квантованных массивах поиск вещественных NaN не имеет практического смысла.
Посмотреть решение
python
import numpy
text_scores = numpy.ones((2, 4, 3))
# Explicit quantization and deep copying (Lesson 4, 6 & 7)
quantized_tensor_copy = text_scores.astype(numpy.int8).copy()
print("Is structural base None?", quantized_tensor_copy.base is None) # True
# Note on engineering practices:
# Running numpy.isnan(quantized_tensor_copy) will work, but it will return ALL False.
# Integer data types (int8, int32) cannot physically store IEEE 754 NaN markers.
# NaN is strictly a floating-point (float32/float64) feature component (Lesson 9).10. Поиск предсказанных классов (Argmax) в многомерном выходном пространстве
Задача: Модель классификации пикселей (сегментация) выдала 3D-тензор прогнозов для одной картинки размером 2x2 пикселя по 3 классам: segmentation_logits = numpy.array([[[0.8, 0.1, 0.1], [0.2, 0.2, 0.6]], [[0.3, 0.4, 0.3], [0.1, 0.9, 0.0]]]) (Размерность 2x2x3) (Урок 16). С помощью метода .argmax() найдите индексы максимальных классов, указав в качестве оси последнюю размерность axis=2 (ось классов) (Урок 15). Выведите полученную 2D-карту сегментации пикселей на экран.
Посмотреть решение
python
import numpy
# 3D matrix pixel logs setup: Shape [Height=2, Width=2, Classes=3] (Lesson 16)
segmentation_logits = numpy.array([
[[0.8, 0.1, 0.1], [0.2, 0.2, 0.6]],
[[0.3, 0.4, 0.3], [0.1, 0.9, 0.0]]
])
# Reducing the classes dimension to extract single index label maps per pixel (Lesson 15)
segmentation_map = segmentation_logits.argmax(axis=2)
print("Extracted 2D segmentations pixels map:\n", segmentation_map)
# Outputs a clean 2D grid containing winning class index codes:
# [[0 2]
# [1 1]]