NumPy индексирование и срезы: как свободно обрезать тензоры
1. Зачем так важно индексирование/срезы?
При работе с глубоким обучением вы часто будете манипулировать тензорами.
- Берёте только первые несколько образцов из батча
- Выбираете конкретный канал (R/G/B) изображения
- Обрезаете часть временных шагов в последовательных данных
- Отбираете только нужный класс из меток
Все эти операции в итоге сводятся к "индексированию (indexing) и срезам (slicing)".
И поскольку синтаксис индексирования/срезов в Tensor PyTorch почти идентичен NumPy, хорошо освоить его в NumPy, и код на PyTorch станет намного проще.
2. Базовое индексирование: от 1‑мерных массивов
2.1 Индексирование 1‑мерного массива
import numpy as np
x = np.array([10, 20, 30, 40, 50])
print(x[0]) # 10
print(x[1]) # 20
print(x[4]) # 50
- Индексы начинаются с 0
x[i]– i‑й элемент
2.2 Отрицательные индексы
Если нужно посчитать от конца, используйте отрицательные индексы.
print(x[-1]) # 50 (последний)
print(x[-2]) # 40
В PyTorch работает точно так же.
3. Основы срезов: start:stop:step
Срезы применяются как x[start:stop:step].
x = np.array([10, 20, 30, 40, 50])
print(x[1:4]) # [20 30 40], 1 ≤ i < 4
print(x[:3]) # [10 20 30], от начала до 3
print(x[2:]) # [30 40 50], от 2 до конца
print(x[:]) # копия всего
Если задать step, можно пропускать элементы.
print(x[0:5:2]) # [10 30 50], от 0 до 4 с шагом 2
print(x[::2]) # [10 30 50], то же
В глубоких сетях удобно, например, пропускать каждый второй временной шаг или выбирать образцы с заданным интервалом.
4. Индексирование массивов 2‑мерных и выше: работа с строками и столбцами
2‑мерные массивы – это уже матрицы/батчи, поэтому сразу ощущается дух глубокого обучения.
import numpy as np
X = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]) # shape: (3, 3)
4.1 Индексирование одной строки/столбца
print(X[0]) # первая строка: [1 2 3]
print(X[1]) # вторая строка: [4 5 6]
print(X[0, 0]) # 1‑й ряд, 1‑й столбец: 1
print(X[1, 2]) # 2‑й ряд, 3‑й столбец: 6
X[i]– i‑й ряд (1‑мерный массив)X[i, j]– значение в i‑м ряду и j‑м столбце (скаляр)
4.2 Срезы строк
print(X[0:2]) # строки 0 и 1
# [[1 2 3]
# [4 5 6]]
print(X[1:]) # от строки 1 до конца
# [[4 5 6]
# [7 8 9]]
Это типичный паттерн в PyTorch: обрезка батча.
4.3 Срезы столбцов
print(X[:, 0]) # все строки, 0‑й столбец → [1 4 7]
print(X[:, 1]) # все строки, 1‑й столбец → [2 5 8]
:означает «весь размерность»X[:, 0]– «все строки, столбец 0»
В глубоких сетях:
- В массиве
(batch_size, feature_dim)можно взять конкретный признак:X[:, k]
5. 3‑мерные и более: батч × канал × высота × ширина
Рассмотрим пример с изображениями.
# Предположим (batch, height, width)
images = np.random.randn(32, 28, 28) # 32 изображения 28×28
5.1 Выбор одного образца
img0 = images[0] # первое изображение, shape: (28, 28)
img_last = images[-1] # последнее
5.2 Использование части батча
first_8 = images[:8] # первые 8, shape: (8, 28, 28)
5.3 Обрезка части изображения (crop)
# Центр 20×20
crop = images[:, 4:24, 4:24] # shape: (32, 20, 20)
В PyTorch аналогично:
# images_torch: (32, 1, 28, 28)
center_crop = images_torch[:, :, 4:24, 4:24]
Индексирование/срезы почти идентичны.
6. Срезы обычно являются «просмотром» (view)
Ключевой момент:
Результат среза обычно является просмотром (view) исходного массива. То есть данные не копируются, а просто «видят» оригинал.
x = np.array([10, 20, 30, 40, 50])
y = x[1:4] # view
print(y) # [20 30 40]
y[0] = 999
print(y) # [999 30 40]
print(x) # [ 10 999 30 40 50] ← оригинал изменился!
Преимущества: экономия памяти и скорость. Недостаток: случайное изменение оригинала.
Если нужен полностью независимый массив, используйте copy().
x = np.array([10, 20, 30, 40, 50])
y = x[1:4].copy()
y[0] = 999
print(x) # [10 20 30 40 50], оригинал сохранён
В PyTorch аналогично, поэтому понимание «view vs copy» облегчает отладку.
7. Логическое индексирование: выбор по условию
Логическое индексирование позволяет выбрать элементы, удовлетворяющие условию.
import numpy as np
x = np.array([1, -2, 3, 0, -5, 6])
mask = x > 0
print(mask) # [ True False True False False True]
pos = x[mask]
print(pos) # [1 3 6]
x > 0– массивTrue/Falsex[mask]– берёт толькоTrueпозиции
Пример с 2‑мерным массивом:
X = np.array([[1, 2, 3],
[4, 5, 6],
[-1, -2, -3]])
pos = X[X > 0]
print(pos) # [1 2 3 4 5 6]
В глубоких сетях часто используют:
- Отбор образцов по условию (например, метка = 1)
- Маскирование при расчёте потерь – усреднение только нужных значений
В PyTorch аналогично:
import torch
x = torch.tensor([1, -2, 3, 0, -5, 6])
mask = x > 0
pos = x[mask]
8. Индексирование массивом/списком целых чисел (Fancy Indexing)
Можно сразу выбрать несколько позиций, передав массив или список индексов.
x = np.array([10, 20, 30, 40, 50])
idx = [0, 2, 4]
print(x[idx]) # [10 30 50]
В 2‑мерном массиве тоже работает.
X = np.array([[1, 2],
[3, 4],
[5, 6]]) # shape: (3, 2)
rows = [0, 2]
print(X[rows])
# [[1 2]
# [5 6]]
В глубоких сетях:
- Случайный выбор индексов для батча
- Сбор конкретных лейблов/предсказаний
PyTorch поддерживает такой стиль.
9. Часто используемые паттерны индексирования
Соберём типичные паттерны из точки зрения глубокого обучения:
import numpy as np
# (batch, feature)
X = np.random.randn(32, 10)
# 1) первые 8 образцов
X_head = X[:8] # (8, 10)
# 2) конкретный признак (например, 3‑й столбец)
f3 = X[:, 3] # (32,)
# 3) только чётные индексы
X_even = X[::2] # (16, 10)
# 4) только лейбл 1
labels = np.random.randint(0, 3, size=(32,))
mask = labels == 1
X_cls1 = X[mask] # только лейбл 1
# 5) случайный перетасовка, первые 24 – train, остальные 8 – val
indices = np.random.permutation(len(X))
train_idx = indices[:24]
val_idx = indices[24:]
X_train = X[train_idx]
X_val = X[val_idx]
Эти паттерны почти идентичны в PyTorch. Освоив NumPy‑индексирование, вы получите навык «свободного разрезания, перемешивания и выбора» тензоров.
10. Итоги
В итоге:
- Индексирование:
x[i],x[i, j], отрицательные индексы - Срезы:
start:stop:step,:, многомерные индексы (X[:, 0],X[:8],X[:, 4:8]) - Срезы обычно являются просмотром (view), поэтому оригинал может измениться → при необходимости используйте
copy() - Логическое индексирование: фильтрация по условию (
x[x > 0],X[labels == 1]) - Индексирование массивом целых чисел: выбор конкретных позиций (
x[[0,2,4]])
Уверенное владение этими техниками позволяет легко выполнять операции с батчами, каналами, масками и перемешиванием данных в PyTorch.

Комментариев нет.