Tutorial

Utilizziamo un piccolo set di dati fornito da Kalev Leetaru per illustrare l'API Timeseries Insights. Il set di dati deriva dal Progetto GDELT, un database globale per il monitoraggio di eventi e la copertura multimediale. Questo set di dati contiene menzioni di entità negli URL di notizie ad aprile 2019.

Obiettivi

  • Scopri il formato dei dati per l'API Timeseries Insights.
  • Scopri come creare, eseguire query, aggiornare ed eliminare set di dati.

Costi

Non sono previsti costi per l'anteprima.

Prima di iniziare

Configura un progetto Cloud e abilita l'API TimeSeries Insights seguendo Guida introduttiva.

Set di dati Tutorial

Il set di dati comprende annotazioni di sedi, organizzazioni, persone e altri elementi.

L'API TimeSeries Insights inserisce dati in formato JSON. Un evento di esempio per questo set di dati è

{
  "groupId":"-6180929807044612746",
  "dimensions":[{"name":"EntityORGANIZATION","stringVal":"Medina Gazette"}],
  "eventTime":"2019-04-05T08:00:00+00:00"
}

Ogni evento deve avere un campo eventTime per il timestamp dell'evento e un valore groupId lungo per contrassegnare gli eventi correlati. Le proprietà dell'evento sono incluse come dimensions, ognuna delle quali name e una delle proprietà stringVal, boolVal, longVal o doubleVal.

NOTA:le API di Google Cloud accettano la custodia cammello (come camelCase) e il serpente (ad esempio snake_case) per i nomi dei campi JSON. Le risorse sono scritte per lo più in formato cammello.

NOTA: poiché i valori lunghi JSON (numeri) sono in realtà valori decimali con cifre precise, sia groupId sia longVal sono effettivamente limitati a 53 cifre binari se JSON utilizza dei numeri. Per fornire i dati int64, il valore JSON deve essere citato come una stringa. Un valore groupId è solitamente un ID numerico o generato con una funzione hash determinista, che corrisponde alla limitazione precedente.

NOTA: i campi name e stringVal devono essere valori alfanumerici, tra cui '_'. I caratteri speciali, incluso lo spazio non sono supportati.

NOTA: quando leggi un'origine dati statica di Google Cloud Storage, ogni evento JSON deve essere composto da una singola riga:

{"groupId":"-6180929807044612746","dimensions":[{"name":"EntityORGANIZATION","stringVal":"Medina Gazette"}],"eventTime":"2019-04-05T08:00:00+00:00"}

Elenca set di dati

projects.datasets.list mostra tutti i set di dati in ${PROJECT_ID}. Nota: gcurl è un alias e PROJECT_ID è una variabile di ambiente, configurata in Per iniziare.

$ gcurl https://timeseriesinsights.googleapis.com/v1/projects/${PROJECT_ID}/datasets

Il risultato è una stringa JSON come

{
  "datasets": [
    {
      "name": "example",
      "state": "LOADED",
      ...
    },
    {
      "name": "dataset_tutorial",
      "state": "LOADING",
      ...
    }
  ]
}

I risultati mostrano i set di dati attualmente sotto il progetto. Il campo state indica se il set di dati è pronto per essere utilizzato. Quando un set di dati viene appena creato, lo stato diventa LOADING fino al completamento dell'indicizzazione, quindi passa allo stato LOADED. Se si verificano errori durante la creazione e l'indicizzazione, lo stato sarà FAILED. Il risultato include anche le informazioni complete sul set di dati della richiesta di creazione originale.

Crea set di dati

projects.datasets.create aggiunge un nuovo set di dati al progetto.

$ gcurl -X POST -d @create.json https://timeseriesinsights.googleapis.com/v1/projects/${PROJECT}/datasets

dove create.json contiene:

{
  name: "dataset_tutorial",
  streaming: true,
  ttl: "8640000s",
  dataNames: [
    "EntityCONSUMER_GOOD",
    "EntityEVENT",
    "EntityLOCATION",
    "EntityORGANIZATION",
    "EntityOTHER",
    "EntityPERSON",
    "EntityUNKNOWN",
    "EntityWORK_OF_ART",
  ],
  dataSources: [
    {uri: "gs://data.gdeltproject.org/blog/2021-timeseries-insights-api/datasets/webnlp-201904.json"}
  ]
}

Questa richiesta crea un set di dati denominato dataset_tutorial da GCS dataSources, che contiene dati sugli eventi in formato JSON. Solo le dimensioni elencate in dataNames vengono indicizzate e utilizzate dal sistema. Se streaming=true, il set di dati accetta anche aggiornamenti di streaming dopo il completamento dell'indicizzazione iniziale. Tuttavia, gli aggiornamenti di streaming più vecchi di ttl vengono ignorati.

La richiesta di creazione restituisce esito positivo se è accettata dal server API. Il set di dati sarà in stato LOADING fino al completamento dell'indicizzazione, quindi lo stato diventerà LOADED e inizia ad accettare query e aggiornamenti.

Dataset query

projects.datasets.query esegue le query di rilevamento delle anomalie.

$ gcurl -X POST -d @query.json https://timeseriesinsights.googleapis.com/v1/projects/${PROJECT}/datasets/dataset_tutorial:query

dove query.json contiene:

{
  dimensionNames: ["EntityLOCATION"],
  testedInterval: {
    startTime: "2019-04-15T00:00:00Z",
    length: "86400s"
  },
  forecastParams: {
    holdout: 10,
    minDensity: 0,
    forecastHistory: "1209600s",
    maxPositiveRelativeChange: 1,
    maxNegativeRelativeChange: 1,
    forecastExtraWeight: 0,
    seasonalityHint: "DAILY",
  },
  returnNonAnomalies: true
}

Vogliamo rilevare se sono state riscontrate anomalie durante la classe testedInterval per le partizioni tra le dimensioni fornite da dimensionNames. Una slice è un sottoinsieme degli eventi nel set di dati con valori fissi per alcune delle proprie dimensioni. Ad esempio, {"name": "EntityLOCATION","stringVal": "Seine River"} è una sezione. Qualsiasi sottoinsieme di dataNames dalla definizione del set di dati può essere utilizzato come dimensionNames, l'API aggrega l'evento per le dimensioni non menzionate. Si tratta di un'operazione simile a "raggruppa per" contenente "count(*)" nelle query SQL.

Gli eventi di ogni sezione vengono aggregati in base all'forecastParams.aggregatedDimension. Se questo campo è vuoto, considereremo semplicemente tutti gli eventi nella sezione. Se non è vuoto, prevediamo che questo campo sia un nome di dimensione numerico valido negli eventi di questa fetta. I valori numerici vengono sommati per formare le serie temporali.

Analizzeremo ogni sezione per verificare se è un'anomalia:

  1. Creazione di una serie temporale che va da testedInterval.startTime - forecastParams.forecastHistory a testedInterval.startTime + testedInterval.length, in cui ciascun punto dati è un intervallo di tempo della durata testedInterval.length e il rispettivo valore viene aggregato gli eventi in quel bucket come specificato dal parametro aggregatedDimension. Se la serie temporale non dispone di punti dati sufficienti (come specificato dal parametro minDensity), ne interromperemo l'analisi.
  2. Una volta calcolata la serie temporale per la sezione, la analizziamo con le tecniche di previsione comuni. Le prime (100 - holdout)% della serie temporale vengono utilizzate per addestrare un modello di previsione e l'ultimo holdout% viene utilizzato per verificare la qualità del modello. In base alle metriche di errore, calcoleremo i limiti di confidenza per l'intervallo di test e, se il valore effettivo è al di fuori di questi limiti per un valore superiore a quello configurato, il processo verrà contrassegnato come errato. Per configurare quanto può essere effettivamente compreso il valore effettivo, controlla i parametri maxPositiveRelativeChange, maxNegativeRelativeChange e forecastExtraWeight.

Il risultato della query appare come segue:

{
  "name": "projects/timeseries-staging/datasets/dataset_tutorial",
  "anomalyDetectionResult": {
    "anomalies": [
      {
        "dimensions": [
          {
            "name": "EntityLOCATION",
            "stringVal": "Ile de la Cite"
          }
        ],
        "result": {
          "holdoutErrors": {},
          "trainingErrors": {
            "mdape": 1,
            "rmd": 1
          },
          "forecastStats": {
            "density": "23",
            "numAnomalies": 1
          },
          "testedIntervalActual": 440,
          "testedIntervalForecastLowerBound": -1,
          "testedIntervalForecastUpperBound": 1
        },
        "status": {}
      },
      {
        "dimensions": [
          {
            "name": "EntityLOCATION",
            "stringVal": "Seine"
          }
        ],
        "result": {
          "holdoutErrors": {
            "mdape": 0.1428571428571429,
            "rmd": 0.1428571428571429
          },
          "trainingErrors": {
            "mdape": 0.84615384615384626,
            "rmd": 0.62459546925566334
          },
          "forecastStats": {
            "density": "85",
            "numAnomalies": 1
          },
          "testedIntervalActual": 586,
          "testedIntervalForecast": 9.3333333333333339,
          "testedIntervalForecastLowerBound": 8,
          "testedIntervalForecastUpperBound": 10.666666666666668
        },
        "status": {}
      },
      {
        "dimensions": [
          {
            "name": "EntityLOCATION",
            "stringVal": "Notre Dame"
          }
        ],
        "result": {
          "holdoutErrors": {
            "mdape": 0.42857142857142855,
            "rmd": 0.42857142857142855
          },
          "trainingErrors": {
            "mdape": 0.19999999999999996,
            "rmd": 0.65055762081784374
          },
          "forecastStats": {
            "density": "100",
            "numAnomalies": 1
          },
          "testedIntervalActual": 790,
          "testedIntervalForecast": 7,
          "testedIntervalForecastLowerBound": 4,
          "testedIntervalForecastUpperBound": 10
        },
        "status": {}
      },
      ...
    ],
    "nonAnomalies": [
      ...
    ]
  }
}

Contiene anomalie e, facoltativamente, sezioni valutate che non sono state contrassegnate come anomalie, nello stesso formato di PredictionSlice. result mostra l'ora dell'anomalia, il valore effettivo e l'intervallo di valori della previsione. trainingErrors e holdoutErrors mostrano metriche aggiuntive utilizzate per il rilevamento di anomalie.

Aggiornamento dello streaming

projects.datasets.appendEvents aggiunge i record di eventi in modalità streaming se la richiesta di creazione specifica streaming: true.

$ gcurl -X POST -d @append.json https://timeseriesinsights.googleapis.com/v1/projects/${PROJECT}/datasets/dataset_tutorial:appendEvents

dove append.json contiene:

{
  events: [
    {
      "groupId":"-5379487492185488040",
      "dimensions":[{"name":"EntityPERSON","stringVal":"Jason Marsalis"}],
      "eventTime":"2021-06-01T15:45:00+00:00"
    },{
      "groupId":"1324354349507023708",
      "dimensions":[{"name":"EntityORGANIZATION","stringVal":"WAFA"}],
      "eventTime":"2021-06-02T04:00:00+00:00"
    }
  ]
}

Gli aggiornamenti in streaming vengono indicizzati quasi in tempo reale in modo che le modifiche possano rispondere rapidamente nei risultati delle query.

Elimina set di dati

projects.datasets.delete contrassegna il set di dati per l'eliminazione.

$ gcurl -X DELETE https://timeseriesinsights.googleapis.com/v1/projects/${PROJECT}/datasets/dataset_tutorial

La richiesta viene restituita immediatamente e il set di dati non accetta query o aggiornamenti aggiuntivi. Potrebbe essere necessario del tempo prima che i dati vengano rimossi completamente dal servizio, dopodiché l'elenco di set di dati non restituirà questo set di dati.

Passaggi successivi

Altri esempi sono disponibili sul sito web di GDELT.