卫星影像时序自监督预训练论文复现

Author

赵昌浩、陈星灿、李世豪、李迁

Published

June 16, 2026

📦 源代码: GitHub 仓库

论文信息

  • 题目: Self-Supervised Pretraining of Transformers for Satellite Image Time Series
  • 期刊: IEEE
  • DOI: 10.1109/9252123

研究背景

本项目复现使用 BERT-like 思路对遥感时序进行自监督掩码训练的方法。核心目标是学习时序编码器(encoder),用于后续下游任务(分类、分割、检测等)。

方法概述

  1. 自制时序数据集:通过 Planet 卫星获取武汉襄阳区域的时序数据
  2. 数据集处理:对时序数据集进行采样,将 4 个波段(RGBNIR)进行拼接作为特征输入
  3. 模型构建:类似 BERT 的双向注意力机制,对时序进行掩码,监督目标是预测完整时序

模型架构

SITSBERT(
  (embedding): ObservationEmbedding(
    (spectral_embed): Linear(in_features=4, out_features=64, bias=True)
  )
  (transformer): TransformerEncoder(
    (layers): ModuleList(
      (0-3): 4 x TransformerEncoderLayer(
        (self_attn): MultiheadAttention(out_features=128)
        (linear1): Linear(in_features=128, out_features=256)
        (linear2): Linear(in_features=256, out_features=128)
      )
    )
  )
  (output_layer): Linear(in_features=128, out_features=4, bias=True)
)

数据集

Dataset visualization showing satellite imagery

数据集可视化

重建可视化

使用训练好的模型对遮盖的时序进行重建,遮盖 7 月和 8 月的数据:

Reconstruction visualization showing masked time series prediction

重建可视化结果

模型使用

1. 作为 Encoder

负责将时序编码为向量,用于后续下游任务(分类、分割、检测等)。

2. 时序预测

回归任务,可视化预测结果与真实值的对比。

核心代码

import torch
import torch.nn as nn

class ObservationEmbedding(nn.Module):
    def __init__(self, input_dim, embed_dim):
        super().__init__()
        self.spectral_embed = nn.Linear(input_dim, embed_dim // 2)
        self.register_buffer('positional_encoding', self._generate_positional_encoding())

    def forward(self, spectral_data, doy):
        spectral_embed = self.spectral_embed(spectral_data)
        pe = self.positional_encoding[doy.long()]
        return torch.cat([spectral_embed, pe], dim=-1)

class SITSBERT(nn.Module):
    def __init__(self, input_dim=4, embed_dim=128, num_heads=8, num_layers=4):
        super().__init__()
        self.embedding = ObservationEmbedding(input_dim, embed_dim)
        encoder_layer = nn.TransformerEncoderLayer(
            d_model=embed_dim, nhead=num_heads, batch_first=True
        )
        self.transformer = nn.TransformerEncoder(encoder_layer, num_layers=num_layers)
        self.output_layer = nn.Linear(embed_dim, input_dim)

    def forward(self, spectral_data, doy):
        x = self.embedding(spectral_data, doy)
        x = self.transformer(x)
        return self.output_layer(x)