close
close

first Drop

Com TW NOw News 2024

VAE voor tijdreeksen
news

VAE voor tijdreeksen

Genereer realistische sequentiële gegevens met dit eenvoudig te trainen model

VAE voor tijdreeksenFoto door Joe Cook op Unsplash

Variational autoencoders (VAE’s) zijn een vorm van generatieve AI die in de schijnwerpers is komen te staan ​​vanwege hun vermogen om realistische beelden te creëren, maar ze kunnen ook boeiende tijdreeksen creëren. De standaard VAE kan worden aangepast om periodieke en sequentiële patronen van tijdreeksgegevens vast te leggen en vervolgens worden gebruikt om plausibele simulaties te genereren. Het model dat ik heb gebouwd, simuleert temperatuurgegevens met behulp van 1-D convolutielagenA strategische keuze van stappen, A flexibele tijdsdimensieEn A seizoensgebonden afhankelijk voorafgaand.

Objectief

Ik heb een model getraind op 50 jaar aan uurlijkse ERA5-temperatuurgegevens uit Phoenix, Arizona (1). Om bruikbare gegenereerde gegevens te hebben, moet het een paar kenmerken van de oorspronkelijke gegevens vastleggen:

  1. seizoensgebonden profiel— zomers zouden warmer moeten zijn dan winters
  2. dagelijks profiel— de dagen zouden warmer moeten zijn dan de nachten
  3. autocorrelatie—de gegevens moeten vloeiend zijn en opeenvolgende dagen moeten vergelijkbare temperaturen hebben

Bevat aangepaste informatie van de Copernicus Climate Change Service (2024)

Impact van klimaatverandering

Het model presteert het beste als de trainingsdata stationair zijn, zonder een langetermijntrend. Vanwege klimaatverandering stijgt de temperatuur echter met ongeveer 0,7 °F per decennium — een waarde die is afgeleid van de waargenomen data die consistent is met gepubliceerde kaarten die recente opwarmingstrends per regio laten zien (2). Om rekening te houden met de stijgende temperatuur, heb ik een lineaire transformatie van -0,7 °F per decennium toegepast op de ruwe observaties om de opwaartse trend uit te wissen. Deze aangepaste dataset geeft weer hoe historische temperaturen eruit zouden kunnen hebben gezien als we uitgaan van de klimaatomstandigheden van 2024. Interpretaties van de gegenereerde data moeten hiermee rekening houden.

Bevat aangepaste informatie van de Copernicus Climate Change Service (2024)

Wat is een VAE?

Variationele autoencoders reduceren de dimensies van de invoergegevens tot een kleinere subruimte. VAE’s definiëren een encoder om waargenomen invoer om te zetten in een gecomprimeerde vorm, de latente variabele genaamd. Vervolgens probeert een afzonderlijke, spiegelende decoder de oorspronkelijke gegevens opnieuw te creëren. De encoder en decoder worden gecooptimaliseerd om een ​​codering te maken die zo min mogelijk informatie verliest.

De volledige verliesfunctie die bij de training wordt gebruikt, omvat:

  • A wederopbouw verlies: meten hoe nauw de retour-, getransformeerde gegevens overeenkomen met de oorspronkelijke invoer
  • A regularisatie termijn: meten hoe nauw de gecodeerde verdeling voor de latente variabele overeenkomt met de voorafgaande verdeling.

Deze twee verliestermen worden afgeleid met behulp van variatie-inferentie door te proberen de bewijsondergrens (ELBO) van de waargenomen gegevens te maximaliseren. Bekijk deze video voor de wiskundige afleiding (3).

Intuïtief voeren VAE’s feature-extractie uit op de trainingsdata op zo’n manier dat de belangrijkste features, vertegenwoordigd door de latente variabele, de gedefinieerde prior-distributie volgen. Nieuwe data wordt gegenereerd door de latente distributie te bemonsteren en deze vervolgens te decoderen naar de vorm van de originele inputs.

Bekijk het artikel van Joseph Rocca, Understanding Variational Autoencoders, voor een uitgebreidere uitleg van hoe VAE’s werken (4).

1-D convolutionele lagen

Voor het modelleren van Phoenix-temperatuurgegevens heb ik mijn encoder een neuraal netwerk gemaakt met eendimensionale convolutionele lagen. Elke convolutielaag past een kernel toe — een matrix van gewichten — op verschoven intervallen van de invoer. Omdat dezelfde kernel wordt gebruikt over de gehele invoer, worden convolutionele lagen beschouwd als shift-invariant en zijn ze goed geschikt voor tijdreeksen met herhalende patronen van sequenties.

links: convolutielaag als matrixbewerking | rechts: grafische weergave | Meestal hebben de invoer en uitvoer meerdere featurevariabelen. Voor de eenvoud toont de matrixbewerking convolutie tussen een invoer en uitvoer met slechts één feature.

De decoder voert de tegenovergestelde taak uit van de encoder met getransponeerde 1-D convolutionele lagen, ook wel deconvolutielagen genoemd. Latente kenmerken worden geprojecteerd in overlappende sequenties om een ​​output-tijdreeks te creëren die nauw aansluit bij de inputs.

De gewichtsmatrix voor een deconvolutielaag is de transpositie van een convolutiematrix.

Het volledige model stapelt meerdere convolutie- en deconvolutielagen op elkaar. Elke tussenliggende, verborgen laag breidt het bereik van de latente variabelen uit, waardoor het model effecten op lange termijn in de data kan vastleggen.

Strategische stappen

De stap — de sprong tussen shifts — bepaalt de grootte van de volgende laag. Convolutielagen gebruiken stappen om de invoer te verkleinen, en deconvolutielagen gebruiken stappen om de latente variabelen terug te breiden naar de invoergrootte. Ze dienen echter ook een secundair doel — om periodieke trends in de tijdreeks vast te leggen.

U kunt de stappen van de convolutielagen strategisch selecteren om de periodieke patronen in de gegevens te repliceren.

Convoluties passen de kernel cyclisch toe, waarbij dezelfde gewichten worden herhaald met een periode die gelijk is aan de stride. Dit geeft het trainingsproces de vrijheid om de gewichten aan te passen op basis van de positie van de invoer in de cyclus.

Door meerdere lagen op elkaar te stapelen ontstaat een grotere effectieve periode bestaande uit geneste subconvoluties.

Beschouw een convolutioneel netwerk dat uurlijkse tijdreeksgegevens distilleert in een featuresruimte met vier variabelen per dag die ochtend, middag, avond en nacht vertegenwoordigen. Een laag met een stap van 4 zal gewichten hebben die uniek zijn toegewezen aan elk tijdstip van de dag dat het dagelijkse profiel in de verborgen laag vastlegt. Tijdens de training leren de encoder en decoder gewichten die de dagelijkse cycli in de gegevens repliceren.

Convoluties maken gebruik van de cyclische aard van de invoer om betere latente kenmerken te bouwen. Deconvoluties zetten latente kenmerken om in overlappende, herhalende sequenties om gegevens met periodieke patronen te genereren.

Flexibele tijdsdimensie

Image-generating VAE’s hebben doorgaans duizenden images die vooraf zijn verwerkt om een ​​vaste breedte en hoogte te hebben. De gegenereerde images komen overeen met de breedte en hoogte van de trainingsdata.

Voor de Phoenix-dataset heb ik slechts één tijdreeks van 50 jaar. Om de training te verbeteren, heb ik de data in sequenties opgedeeld en uiteindelijk besloten om aan elke periode van 96 uur een latente variabele toe te wijzen. Ik wil echter mogelijk tijdreeksen genereren die langer zijn dan 4 dagen en idealiter is de uitvoer vloeiend in plaats van discrete stukken van 96 uur in de simulaties.

Gelukkig kunt u met Tensorflow onbeperkte dimensies in uw neurale netwerk specificeren. Op dezelfde manier dat neurale netwerken elke batchgrootte aankunnen, kunt u uw model bouwen om een ​​willekeurig aantal tijdsstappen aan te kunnen. Als gevolg hiervan bevat mijn latente variabele ook een tijdsdimensie die kan variëren. In mijn model is er één tijdsstap in de latente ruimte voor elke 96 uur in de invoer.

Het genereren van nieuwe gegevens is net zo eenvoudig als het bemonsteren van latente variabelen uit de prior, waarbij u het aantal stappen selecteert dat u in de tijdsdimensie wilt opnemen.

VAE’s met een onbeperkte tijdsdimensie kunnen gegevens van elke lengte genereren.

De gesimuleerde uitvoer bevat 4 dagen voor elke tijdstap die u hebt bemonsterd. De resultaten zien er vloeiend uit, omdat convolutielagen ervoor zorgen dat invoerlagen overlopen in aangrenzende tijdsperioden.

Seizoensafhankelijk voorafgaand

In de meeste VAE’s wordt aangenomen dat elk onderdeel van de latente variabele een standaardnormale verdeling volgt. Deze verdeling, soms de prior genoemd, wordt bemonsterd en vervolgens gedecodeerd om nieuwe gegevens te genereren. In dit geval heb ik een iets complexere prior gekozen die afhankelijk is van de tijd van het jaar.

Latente variabelen die uit een seizoensgebonden voorafgaande periode worden bemonsterd, genereren gegevens met kenmerken die per jaargetijde variëren.

Op basis van deze prioriteit zullen de gegenereerde gegevens van januari er heel anders uitzien dan de gegevens van juli. Bovendien zullen de gegenereerde gegevens van dezelfde maand veel van dezelfde kenmerken hebben.

Ik heb de tijd van het jaar weergegeven als een hoek, en, waarbij 0° 1 januari is, 180° het begin van juli is en 360° weer terug is naar januari. De prior is een normale verdeling waarvan het gemiddelde en de log-variantie een derdegraads trigonometrische polynoom is van θ waarbij de coëfficiënten van de polynoom parameters zijn die tijdens de training in combinatie met de encoder en decoder zijn geleerd.

De voorafgaande distributieparameters zijn een periodieke functie van θen goed gedragende periodieke functies kunnen worden benaderd met elk niveau van nauwkeurigheid, gegeven een trigonometrische polynoom van voldoende hoge graad. (5)

links: visualisatie van θ | rechts: prior distributie van Z in termen van parameters m en s

De seizoensgegevens worden alleen in de prior gebruikt en hebben geen invloed op de encoder of decoder. De volledige set van probabilistische afhankelijkheden wordt hier grafisch weergegeven.

Probabilistisch grafisch model inclusief de prior

Uitvoering

Ik heb het model getraind met behulp van Tensorflow in Python.

from tensorflow.keras import layers, models

Codeerder

De invoer is gedefinieerd met een flexibele tijdsdimensie. In Keras specificeert u een onbeperkte dimensie met None.

Als u dezelfde opvulling gebruikt, worden er nullen aan de invoerlaag toegevoegd, zodat de uitvoergrootte overeenkomt met de invoergrootte gedeeld door de stapgrootte.

inputs = layers.Input(shape=(None,)) # (N, 96*k)
x = layers.Reshape((-1, 1))(inputs) # (N, 96*k, 1)

# Conv1D parameters: filters, kernel_size, strides, padding
x = layers.Conv1D(40, 5, 3, 'same', activation='relu')(x) # (N, 32*k, 40)
x = layers.Conv1D(40, 3, 2, 'same', activation='relu')(x) # (N, 16*k, 40)
x = layers.Conv1D(40, 3, 2, 'same', activation='relu')(x) # (N, 8*k, 40)
x = layers.Conv1D(40, 3, 2, 'same', activation='relu')(x) # (N, 4*k, 40)
x = layers.Conv1D(40, 3, 2, 'same', activation='relu')(x) # (N, 2*k, 40)
x = layers.Conv1D(20, 3, 2, 'same')(x) # (N, k, 20)

z_mean = x(: ,:, :10) # (N, k, 10)
z_log_var = x(:, :, 10:) # (N, k, 10)
z = Sampling()((z_mean, z_log_var)) # custom layer sampling from gaussian

encoder = models.Model(inputs, (z_mean, z_log_var, z), name="encoder")

Sampling() is een aangepaste laag die gegevens uit een normale verdeling met het opgegeven gemiddelde en de logaritmische variantie bemonstert.

Decoder

Deconvolutie wordt uitgevoerd met Conv1DTranspose.

# input shape: (batch_size, time_length/96, latent_features)
inputs = layers.Input(shape=(None, 10)) # (N, k, 10)

# Conv1DTranspose parameters: filters, kernel_size, strides, padding
x = layers.Conv1DTranspose(40, 3, 2, 'same', activation='relu')(inputs) # (N, 2*k, 40)
x = layers.Conv1DTranspose(40, 3, 2, 'same', activation='relu')(x) # (N, 4*k, 40)
x = layers.Conv1DTranspose(40, 3, 2, 'same', activation='relu')(x) # (N, 8*k, 40)
x = layers.Conv1DTranspose(40, 3, 2, 'same', activation='relu')(x) # (N, 16*k, 40)
x = layers.Conv1DTranspose(40, 3, 2, 'same', activation='relu')(x) # (N, 32*k, 40)
x = layers.Conv1DTranspose(1, 5, 3, 'same')(x) # (N, 96*k, 1)

outputs = layers.Reshape((-1,))(x) # (N, 96*k)

decoder = models.Model(inputs, outputs, name="decoder")

Voorafgaand

De prior verwacht invoer die al in de vorm (sin() isθ), cos(θ), zonde(2θ), cos(2θ), zonde(3θ), cos(3θ)).

De Dense-laag heeft geen bias-term om te voorkomen dat de prior-verdeling te ver van nul afdwaalt of een algehele variantie heeft die te hoog of te klein is.

# seasonal inputs shape: (N, k, 6)
inputs = layers.Input(shape=(None, 2*3))

x = layers.Dense(20, use_bias=False)(inputs) # (N, k, 20)
z_mean = x(:, :, :10) # (N, k, 10)
z_log_var = x(:, :, 10:) # (N, k, 10)
z = Sampling()((z_mean, z_log_var)) # (N, k, 10)

prior = models.Model(inputs, (z_mean, z_log_var, z), name="seasonal_prior")

Volledig model

De verliesfunctie bevat een reconstructieterm en een latente regularisatieterm.

Functie log_lik_normal_sum is een aangepaste functie voor het berekenen van de normale log-waarschijnlijkheid van de waargenomen gegevens, gegeven de gereconstrueerde uitvoer. Het berekenen van de log-waarschijnlijkheid vereist ruisverdeling rond de gedecodeerde uitvoer, waarvan wordt aangenomen dat deze normaal is met logvariantie gegeven door self.noise_log_var, geleerd tijdens de training.

Voor de regularisatieterm berekent kl_divergence_sum de Kullback-Leibler-divergentie tussen twee gaussianen — in dit geval de latente gecodeerde en eerdere distributies.

class VAE(models.Model):
def __init__(self, encoder, decoder, prior, **kwargs):
super(VAE, self).__init__(**kwargs)
self.encoder = encoder
self.decoder = decoder
self.prior = prior
self.noise_log_var = self.add_weight(name="var", shape=(1,), initializer="zeros", trainable=True)

@tf.function
def vae_loss(self, data):
values, seasonal = data
z_mean, z_log_var, z = self.encoder(values)
reconstructed = self.decoder(z)
reconstruction_loss = -log_lik_normal_sum(values, reconstructed, self.noise_log_var)/INPUT_SIZE
seasonal_z_mean, seasonal_z_log_var, _ = self.prior(seasonal)
kl_loss_z = kl_divergence_sum(z_mean, z_log_var, seasonal_z_mean, seasonal_z_log_var)/INPUT_SIZE
return reconstruction_loss, kl_loss_z

def train_step(self, data):
with tf.GradientTape() as tape:
reconstruction_loss, kl_loss_z = self.vae_loss(data)
total_loss = reconstruction_loss + kl_loss_z

gradients = tape.gradient(total_loss, self.trainable_variables)
self.optimizer.apply_gradients(zip(gradients, self.trainable_variables))

return {'loss': total_loss}

Bezoek mijn Github-repository voor de volledige implementatie.

Resultaten

Nadat het model is getraind, komen de gegenereerde gegevens overeen met de seizoens-/dagprofielen en de autocorrelatie van de oorspronkelijke temperatuurgegevens.

Bevat aangepaste informatie van de Copernicus Climate Change Service (2024)

Conclusie

Het bouwen van technieken voor generatieve time series modellering is een cruciaal veld met toepassingen die verder gaan dan alleen het simuleren van data. De methoden die ik deelde, kunnen worden aangepast voor toepassingen in data-imputatie, anomaliedetectie en prognoses.

Door gebruik te maken van 1-D convolutionele lagen, strategische stappen, flexibele tijdsinputs en seizoensgebonden priors, kunt u een VAE bouwen die complexe patronen in uw tijdreeksen repliceert. Laten we samenwerken om best practices voor tijdreeksmodellering te verfijnen.

Deel in de reacties eventuele ervaringen, vragen of inzichten die u hebt met VAE’s en/of generatieve AI voor tijdreeksen.

Tenzij anders vermeld, zijn alle afbeeldingen door de auteur gemaakt.

(1) Hersbach, H., Bell, B., Berrisford, P., Biavati, G., Horányi, A., Muñoz Sabater, J., Nicolas, J., Peubey, C., Radu, R., Rozum, I., Schepers, D., Simmons, A., Soci, C., Dee, D., Thépaut, JN. (2023): ERA5-uurgegevens op afzonderlijke niveaus van 1940 tot heden. Copernicus Climate Change Service (C3S) Climate Data Store (CDS), DOI: 10.24381/cds.adbb2d47 (geraadpleegd op 01-08-2024)

(2) Lindsey, R., & Dahlman, L. (2024, 18 januari). Klimaatverandering: Wereldwijde temperatuur. Klimaat.gov. https://www.climate.gov/news-features/understanding-climate/climate-change-global-temperature

(3) Sachdeva, K. (2021, 26 januari). Bewijsondergrens (ELBO) — Duidelijk uitgelegd! (Video). YouTube. https://www.youtube.com/watch?v=IXsA5Rpp25w

(4) Rocca, J. (23 september 2019). Inzicht in variationele autoencoders (VAE’s). Op weg naar Data Science. https://towardsdatascience.com/understanding-variational-autoencoders-vaes-f70510919f73

(5) Baidoo, FA (2015, 28 augustus). Uniforme convergentie van Fourierreeksen (REU-rapport). Universiteit van Chicago. https://math.uchicago.edu/~may/REU2015/REUPapers/Baidoo.pdf


VAE voor tijdreeksen werd oorspronkelijk gepubliceerd in Towards Data Science op Medium, waar mensen het gesprek voortzetten door dit verhaal te markeren en erop te reageren.