TFRecord e Earth Engine

TFRecord é um formato binário para codificar de forma eficiente sequências longas de tf.Example protos. Os arquivos TFRecord são facilmente carregados pelo TensorFlow pelo pacote tf.data, conforme descrito aqui e aqui. Esta página descreve como o Earth Engine converte entre ee.FeatureCollection ou ee.Image e o formato TFRecord.

Como exportar dados para TFRecord

É possível exportar tabelas (ee.FeatureCollection) ou imagens (ee.Image) para arquivos TFRecord no Google Drive ou no Cloud Storage. A configuração da exportação depende do que você está exportando, conforme descrito abaixo. Todos os números exportados do Earth Engine para o TFRecord são convertidos em tipo float.

Como exportar tabelas

Ao exportar um ee.FeatureCollection para um arquivo TFRecord, há uma correspondência 1:1 entre cada ee.Feature na tabela e cada tf.train.Example (ou seja, cada registro) no arquivo TFRecord. Cada propriedade do ee.Feature é codificada como um tf.train.Feature com uma lista de números flutuantes correspondentes ao número ou ee.Array armazenado na propriedade. Se você exportar uma tabela com matrizes nas propriedades, precisará informar ao TensorFlow a forma da matriz quando ela for lida. Uma tabela exportada para um arquivo TFRecord sempre será compactada com o tipo de compactação GZIP. Você sempre recebe exatamente um arquivo TFRecord para cada exportação.

O exemplo a seguir demonstra a análise de dados de uma tabela exportada de propriedades escalares ('B2',...,'B7', 'landcover'). A dimensão das listas de ponto flutuante é [1], e o tipo é tf.float32:

Python

dataset = tf.data.TFRecordDataset(exportedFilePath)

featuresDict = {
  'B2': tf.io.FixedLenFeature(shape=[1], dtype=tf.float32),
  'B3': tf.io.FixedLenFeature(shape=[1], dtype=tf.float32),
  'B4': tf.io.FixedLenFeature(shape=[1], dtype=tf.float32),
  'B5': tf.io.FixedLenFeature(shape=[1], dtype=tf.float32),
  'B6': tf.io.FixedLenFeature(shape=[1], dtype=tf.float32),
  'B7': tf.io.FixedLenFeature(shape=[1], dtype=tf.float32),
  'landcover': tf.io.FixedLenFeature(shape=[1], dtype=tf.float32)
}

parsedDataset = dataset.map(lambda example: tf.io.parse_single_example(example, featuresDict))
        

Este exemplo ilustra a leitura de recursos escalares (ou seja, shape=[1]). Se você estiver exportando matrizes 2D ou 3D (por exemplo, patches de imagem), especifique a forma dos patches no momento da análise, por exemplo, shape=[16, 16] para um patch de 16x16 pixels.

Como exportar imagens

Quando você exporta uma imagem, os dados são ordenados como canais, altura e largura (CHW). A exportação pode ser dividida em vários arquivos TFRecord, com cada arquivo contendo um ou mais patches de tamanho patchSize, especificado pelo usuário na exportação. O tamanho dos arquivos em bytes é especificado pelo usuário no parâmetro maxFileSize. Há uma correspondência 1:1 entre cada patch e cada tf.train.Example no arquivo TFRecord resultante. Cada banda da imagem é armazenada como uma tf.train.Feature separada em cada tf.train.Example, em que o comprimento da lista de números flutuantes armazenada em cada recurso é a largura do patch * altura. As listas achatadas podem ser divididas em vários pixels individuais, conforme mostrado neste exemplo. Ou a forma do patch exportado pode ser recuperada como neste exemplo.

Para ajudar a reduzir os efeitos de borda, os patches exportados podem se sobrepor. Mais especificamente, é possível especificar um kernelSize que resultará em blocos de tamanho:

[patchSize[0] + kernelSize[0], patchSize[1] + kernelSize[1]]
    

Cada bloco se sobrepõe aos blocos adjacentes em [kernelSize[0]/2, kernelSize[1]/2]. Como resultado, um kernel de tamanho kernelSize centralizado em um pixel de borda de um patch de tamanho patchSize contém dados totalmente válidos. A disposição espacial dos patches no espaço é ilustrada na Figura 1, em que a dimensão de padding corresponde à parte do kernel que se sobrepõe à imagem adjacente:

Diagrama de imagem do TFRecord
Figura 1. Como os patches de imagem são exportados. A dimensão do padding é kernelSize/2.

formatOptions

Os parâmetros patchSize, maxFileSize e kernelSize são transmitidos para a chamada ee.Export (JavaScript) ou ee.batch.Export (Python) por um dicionário formatOptions, em que as chaves são os nomes de parâmetros adicionais transmitidos para Export. Os possíveis formatOptions para uma imagem exportada para o formato TFRecord são:

PropriedadeDescriçãoTipo
patchDimensions Dimensões empilhadas sobre a área de exportação, cobrindo cada pixel na caixa delimitadora exatamente uma vez, exceto quando as dimensões do patch não dividem uniformemente a caixa delimitadora. Nesse caso, os blocos de borda ao longo das maiores bordas x/y são descartados. As dimensões precisam ser maiores que 0. Matriz<int>[2].
kernelSize Se especificado, os blocos serão armazenados em buffer pelas dimensões da margem, tanto positivamente quanto negativamente, resultando na sobreposição entre os patches vizinhos. Se especificado, duas dimensões precisam ser fornecidas (X e Y, respectivamente). Matriz<int>[2]. Padrão: [1, 1]
compressed Se verdadeiro, compacta os arquivos .tfrecord com gzip e anexa o sufixo ".gz" Booleano. Padrão: true
maxFileSize Tamanho máximo, em bytes, de um .tfrecord exportado (antes da compactação). Um tamanho de arquivo menor vai resultar em mais fragmentação (e, portanto, em mais arquivos de saída). Int. Padrão: 1 GiB
defaultValue O valor definido em cada banda de um pixel que é parcialmente ou completamente mascarado e o valor definido em cada valor em um elemento 3D de saída criado a partir de uma banda de matriz em que o comprimento da matriz no pixel de origem era menor que a profundidade do valor do elemento (ou seja, o valor no índice 3 de um pixel de matriz de comprimento 2 em uma banda de matriz com uma profundidade de elemento correspondente de 3). A parte fracional é descartada para bandas do tipo inteiro e fixada no intervalo do tipo de banda. O padrão é 0. Int. Padrão: 0
tensorDepths Mapeamento dos nomes das bandas de matriz de entrada para a profundidade dos tensores 3D que elas criam. Os arrays serão truncados ou preenchidos com valores padrão para se ajustar à forma especificada. Para cada banda de matriz, ela precisa ter uma entrada correspondente. Array<int>[]. Padrão: []
sequenceData Se verdadeiro, cada pixel é gerado como um SequenceExample que mapeia bandas escalares para o contexto e bandas de matriz para as sequências do exemplo. Os exemplos de sequência são gerados na ordem de linha principal dos pixels em cada patch e, em seguida, na ordem de linha principal dos patches de área na sequência de arquivos. Booleano. Padrão: false
collapseBands Se verdadeiro, todas as bandas serão combinadas em um único tensor 3D, recebendo o nome da primeira banda na imagem. Todas as bandas são promovidas para bytes, int64s e depois flutuam nessa ordem, dependendo do tipo mais distante nessa sequência em todas as bandas. As bandas de matriz são permitidas, desde que tensor_depths seja especificado. Booleano. Padrão: false
maskedThreshold Proporção máxima permitida de pixels mascarados em um patch. Os patches que excederem essa permissão serão descartados em vez de gravados em arquivos. Se esse campo for definido como qualquer valor, exceto 1, o sidecar JSON não será produzido. O padrão é 1. Ponto flutuante. Padrão: 1

O arquivo "mixer" do TFRecord

Ao exportar para o TFRecord, o Earth Engine gera um sidecar com seus arquivos TFRecord, chamado de "mixer". Esse é um arquivo JSON simples usado para definir a disposição espacial dos blocos, ou seja, a georeferênciação. Esse arquivo é necessário para fazer o upload de previsões feitas nas imagens, conforme descrito na próxima seção.

Como exportar séries temporais

As exportações de imagens para exemplos e exemplos de sequência são compatíveis. Quando você exporta para Examples, a região de exportação é cortada em blocos, e esses blocos são exportados em ordem de linha principal para um número de arquivos .tfrecord com cada banda com o próprio recurso (a menos que você especifique collapseBands). Quando você exporta para SequenceExamples, um SequenceExample por pixel é exportado, com esses SequenceExamples em ordem de linha principal em um bloco e, em seguida, em ordem de linha principal de blocos na região de exportação original. Se você não tiver certeza, sempre presuma que as coisas estarão em ordem de linha principal de alguma forma. Observação: todas as bandas escalares de uma imagem serão empacotadas no contexto de um SequenceExample, enquanto as bandas de matriz vão se tornar os dados reais da sequência.

Bandas de matriz

As bandas de matriz podem ser exportadas quando uma imagem é exportada para o formato TFRecord. A exportação de bandas de matriz fornece um meio de preencher as "FeatureLists" de SequenceExamples e uma maneira de criar tensores 3D ao exportar para exemplos comuns. Para informações sobre como as comprimentos/profundidades das bandas de matriz são gerenciadas, consulte collapseBands e/ou tensorDepths na tabela acima. Observação: o uso de collapseBands e a exportação para SequenceExamples (ou seja, definir o parâmetro sequenceData) vão resultar na consolidação de todas as bandas em uma única série temporal por pixel.

Como fazer upload de TFRecords para o Earth Engine

É possível fazer upload de tabelas (somente linha de comando) e imagens para o Earth Engine como arquivos TFRecord. Para tabelas, a relação 1:1 descrita anteriormente se aplica na direção inversa (ou seja, tf.train.Example -> ee.Feature).

Upload de imagens

Se você gerar previsões em imagens exportadas, forneça o mixer ao fazer upload das previsões (como arquivos TFRecord) para receber imagens georeferenciadas. A parte sobreposta dos patches (dimensão de padding na Figura 1) será descartada para resultar em cobertura contígua da região exportada. As previsões precisam ser organizadas como uma sequência tf.train.Example do mesmo número e ordem que os exemplos de imagem exportados originalmente (mesmo entre um número arbitrário de arquivos).