skills/timeseries/cnn-transformer-multimodal-fusion/SKILL.md
Process multiple sensor modalities through separate CNN branches then fuse via a transformer with CLS token for classification
npx skillsauth add wenmin-wu/ds-skills timeseries-cnn-transformer-multimodal-fusionInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
For multi-sensor systems (IMU + thermal + depth), process each modality through its own CNN branch to extract temporal features, concatenate along the feature dimension, prepend a learnable CLS token, and feed into a transformer encoder. The CLS token output is used for classification.
import torch
import torch.nn as nn
from transformers import BertConfig, BertModel
class MultiModalFusion(nn.Module):
def __init__(self, modality_dims, hidden_dim, n_classes, n_layers=4):
super().__init__()
self.branches = nn.ModuleList([
nn.Sequential(
nn.Conv1d(dim, hidden_dim, 7, padding=3),
nn.BatchNorm1d(hidden_dim), nn.GELU(),
nn.Conv1d(hidden_dim, hidden_dim, 5, stride=2, padding=2),
nn.BatchNorm1d(hidden_dim), nn.GELU(),
) for dim in modality_dims
])
self.cls_token = nn.Parameter(torch.randn(1, 1, hidden_dim * len(modality_dims)))
config = BertConfig(hidden_size=hidden_dim * len(modality_dims),
num_hidden_layers=n_layers, num_attention_heads=8)
self.transformer = BertModel(config)
self.head = nn.Linear(config.hidden_size, n_classes)
def forward(self, *modalities):
feats = [branch(m.permute(0, 2, 1)) for branch, m in
zip(self.branches, modalities)]
fused = torch.cat(feats, dim=1).permute(0, 2, 1) # (B, T, C)
cls = self.cls_token.expand(fused.size(0), -1, -1)
x = torch.cat([cls, fused], dim=1)
out = self.transformer(inputs_embeds=x).last_hidden_state[:, 0]
return self.head(out)
data-ai
Scaled Pinball Loss (SPL) metric for evaluating quantile forecasts, normalized by mean absolute successive differences of training data
data-ai
Walk backward through a time series and multiplicatively rescale segments when jumps exceed a fraction of the running mean to correct data collection anomalies
testing
Transform forecasting target to next/current ratio minus one so that optimizing MAE or squared error implicitly minimizes SMAPE
tools
Convert point forecasts to prediction intervals by scaling with logit-transformed quantile ratios passed through a Normal CDF