Временная сверточная нейросеть (TCN)
Нейросеть для работы с последовательными данными, которая использует сверточные слои вместо рекуррентных, но при этом умеет учитывать долгосрочные зависимости во времени.
Временная сверточная нейросеть (Temporal Convolutional Network, TCN) — это нейросеть для работы с последовательными данными, которая использует сверточные слои вместо рекуррентных, но при этом умеет учитывать долгосрочные зависимости во времени. TCN — это «сверточная версия LSTM», которая часто быстрее и стабильнее.
Почему вообще понадобились TCN
Долгое время стандартом для последовательностей были:
- RNN
- LSTM
- GRU
Но у них есть проблемы:
- последовательная обработка (медленно на GPU),
- сложное обучение,
- нестабильные градиенты,
- трудности с очень длинными последовательностями.
TCN предложили другой подход: вместо рекурсии — одномерныесвертки по времени.
Ключевые идеи TCN
Каузальные свёртки (Causal Convolutions): модель не «заглядывает в будущее». Значение в момент времени t зависит только от:
- текущего шага,
- предыдущих шагов.
Это важно для:
- прогнозирования,
- временных рядов,
- онлайн-обработки.
Dilated Convolutions (расширенные свёртки): чтобы учитывать длинную историю, используются свёртки с пропусками.
Пример:
- dilation=1 → обычная свёртка
- dilation=2 → через один шаг
- dilation=4 → через три шага
Это позволяет быстро увеличивать «поле зрения» без резкого роста параметров.
Residual connections: как и в ResNet, используются Skip Connections. Это стабилизирует обучение и позволяет строить глубокие TCN.
Почему TCN часто лучше LSTM
- полностью параллельны (быстрее на GPU)
- стабильнее в обучении
- проще масштабируются
- хорошо работают на длинных последовательностях
В ряде задач временных рядов TCN показывают результаты не хуже или лучше LSTM.
Минимальный пример TCN на PyTorch
Импортируем инструменты:
import torch
import torch.nn as nn
import torch.nn.functional as F
Temporal Block
class TemporalBlock(nn.Module):
def __init__(self, in_channels, out_channels, kernel_size, dilation):
super().__init__()
padding = (kernel_size - 1) * dilation
self.conv1 = nn.Conv1d(
in_channels,
out_channels,
kernel_size,
padding=padding,
dilation=dilation
)
self.relu = nn.ReLU()
self.conv2 = nn.Conv1d(
out_channels,
out_channels,
kernel_size,
padding=padding,
dilation=dilation
)
self.downsample = nn.Conv1d(in_channels, out_channels, 1) \
if in_channels != out_channels else None
def forward(self, x):
out = self.conv1(x)
out = out[:, :, :-self.conv1.padding[0]] # обрезаем лишнее (causal)
out = self.relu(out)
out = self.conv2(out)
out = out[:, :, :-self.conv2.padding[0]]
res = x if self.downsample is None else self.downsample(x)
return self.relu(out + res)
Полная модель TCN:
class TCN(nn.Module):
def __init__(self, input_size, num_channels, kernel_size=3):
super().__init__()
layers = []
for i in range(len(num_channels)):
dilation = 2 i
in_channels = input_size if i == 0 else num_channels[i-1]
out_channels = num_channels[i]
layers.append(
TemporalBlock(
in_channels,
out_channels,
kernel_size,
dilation
)
)
self.network = nn.Sequential(*layers)
self.fc = nn.Linear(num_channels[-1], 1)
def forward(self, x):
# x: (batch, channels, time)
y = self.network(x)
y = y[:, :, -1] # последний временной шаг
return self.fc(y)
Проверим работу модели:
# 32 объекта, 5 признаков, 50 временных шагов
x = torch.randn(32, 5, 50)
model = TCN(
input_size=5,
num_channels=[16, 32, 64]
)
y = model(x)
print(y.shape)
# torch.Size([32, 1])
Где применяют TCN
- прогнозирование временных рядов
- обработка сигналов
- финансовые данные
- IoT и сенсоры
- анализ логов
- биомеханика движений
Для задач анализа динамики (например, спортивных движений) TCN может быть хорошей альтернативой LSTM.
Ограничения
- сложнее интерпретировать, чем линейные модели
- требует аккуратного выбора dilation
- при очень длинных рядах глубина может расти