我們會使用 Kalev Leetaru 提供的小型資料集來說明時間序列深入分析 API。 資料集來自 GDELT Project,這是一項全球資料庫追蹤事件和媒體涵蓋率。 這個資料集涵蓋 2019 年 4 月新聞網址提及的實體。
目標
- 瞭解 Timeseries API 的資料格式。
- 瞭解如何建立、查詢、更新及刪除資料集。
費用
預覽沒有任何費用。
事前準備
按照入門指南設定 Cloud 專案並啟用 Timeseries Insights API。
教學課程資料集
該資料集包含位置、機構、人員等實體註解。
Timeseries Insights API 會採用 JSON 格式輸入內容。這個資料集的事件範例為
{
"groupId":"-6180929807044612746",
"dimensions":[{"name":"EntityORGANIZATION","stringVal":"Medina Gazette"}],
"eventTime":"2019-04-05T08:00:00+00:00"
}
每個事件都必須有事件時間戳記的 eventTime
欄位,以及長值 groupId
以標記相關事件。事件屬性會以 dimensions
形式提供,每個屬性都有 name
、stringVal
、boolVal
、longVal
或 doubleVal
其中之一。
附註:Google Cloud API 接受 JSON 欄位名稱的 cam 客服案件 (例如 camelCase
) 和蛇大小寫 (例如 snake_case
)。這類說明文件大多是 came 尾形。
附註:由於 JSON 長值 (數字) 實際上是僅有整數精確度的浮點值,如果 JSON 使用 groupId
和 longVal
,則其有效效率為 53 個二進位數字使用數字。如要提供 int64 資料,JSON 值必須以字串加上引號。 groupId
通常是數字 ID,或者是以確定性雜湊函式產生的,並且符合上述限制。
附註:name
和 stringVal
欄位須為包含英數字元的英數字元值,包括 '_'
。不支援包含空格的特殊字元。
附註:從靜態 Google Cloud Storage 資料來源讀取資料時,每個 JSON 事件應為單行,如下所示:
{"groupId":"-6180929807044612746","dimensions":[{"name":"EntityORGANIZATION","stringVal":"Medina Gazette"}],"eventTime":"2019-04-05T08:00:00+00:00"}
列出資料集
projects.datasets.list 會顯示 ${PROJECT_ID}
之下的所有資料集。 請注意,gcurl
是別名,而 PROJECT_ID
是環境變數,可於入門指南中設定。
$ gcurl https://timeseriesinsights.googleapis.com/v1/projects/${PROJECT_ID}/datasets
結果會是 JSON 字串,如下所示:
{
"datasets": [
{
"name": "example",
"state": "LOADED",
...
},
{
"name": "dataset_tutorial",
"state": "LOADING",
...
}
]
}
結果會顯示專案目前下的資料集。 state
欄位指示資料集是否可供使用。如果資料集剛建立,則資料集處於 LOADING
狀態,直到索引完成為止,然後轉換為 LOADED
狀態。如果建立和建立索引時發生任何錯誤,則處於 FAILED
狀態。結果還會包含原始建立要求中的完整資料集資訊。
建立資料集
projects.datasets.create 將新資料集新增至專案。
$ gcurl -X POST -d @create.json https://timeseriesinsights.googleapis.com/v1/projects/${PROJECT}/datasets
其中 create.json
包含:
{
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"}
]
}
這個要求會從 GCS dataSources
建立名為 dataset_tutorial
的資料集,其中包含 JSON 格式的事件資料。只有 dataNames
中列出的維度會編入索引,並供系統使用。如果為 streaming=true
,則資料集也會在初次建立索引完成後接受資料集更新。
但系統會忽略超過 ttl
的串流更新。
如果 API 伺服器接受這個建立要求,就會傳回成功。在完成建立索引之前,資料集會處於 LOADING
狀態,然後會變成 LOADED
,並且會接受查詢 (如果有的話)。
查詢資料集
projects.datasets.query 可執行異常偵測查詢。
$ gcurl -X POST -d @query.json https://timeseriesinsights.googleapis.com/v1/projects/${PROJECT}/datasets/dataset_tutorial:query
其中 query.json
包含:
{
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
}
我們希望在 dimensionNames
提供的所有維度之間,偵測到 testedInterval
發生的任何異常情況。「slice」是資料集中一些事件固定值的子集, 例如,{"name": "EntityLOCATION","stringVal": "Seine River"}
是片段。資料集定義中 dataNames
的任何子集均可用來當做 dimensionNames
,API 則會匯總未提及的維度事件。這與 SQL 查詢中具有「計數(*)」的「分組依據」作業類似。
每個片段中的資料均由 forecastParams.aggregatedDimension
來匯總。如果這個欄位為空白,系統只會計算片段中的資料事件。如果沒有內容,我們會預期在此欄位的事件中顯示有效的數值維度名稱。
數值會加總,形成時間序列。
我們會分析每個片段,藉此確認問題是否異常:
- 組成時間序列影片
testedInterval.startTime - forecastParams.forecastHistory
收件者testedInterval.startTime + testedInterval.length
,每個資料點都變成一個時間長度區塊,testedInterval.length
匯總該值區中的事件,並利用aggregatedDimension
。如果時間序列沒有足夠的資料點 (如minDensity
參數所指定),我們會停止分析這個時間序列。 - 計算出配量的時間序列後,我們會使用常見的預測技巧來分析這個時間序列。時間序列中的第一個
(100 - holdout)%
會用於訓練預測模型,且最後的holdout%
是用來測試模型的品質。根據錯誤指標,我們會計算受測試間隔的信賴度,如果實際值超過這些範圍,系統就會將這些值標示為異常。如要設定實際值超出界限的範圍,請檢查maxPositiveRelativeChange
、maxNegativeRelativeChange
和forecastExtraWeight
參數。
查詢結果如下所示:
{
"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": [
...
]
}
}
這個檔案內含異常,但您也可以選擇在相同的 ForecastSlic 開始格式中,找出未標示為異常的片段。 result
會顯示異常情況、實際值以及預測值的範圍。trainingErrors
和 holdoutErrors
會顯示用於異常偵測的其他指標。
串流更新
如果建立要求指定了 streaming: true
,projects.datasets.appendEvent 會以串流方式新增事件記錄。
$ gcurl -X POST -d @append.json https://timeseriesinsights.googleapis.com/v1/projects/${PROJECT}/datasets/dataset_tutorial:appendEvents
其中 append.json
包含:
{
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"
}
]
}
串流更新會以近乎即時的方式建立索引,因此變更可在查詢結果中快速反應。
刪除資料集
projects.datasets.delete 會標示要刪除的資料集。
$ gcurl -X DELETE https://timeseriesinsights.googleapis.com/v1/projects/${PROJECT}/datasets/dataset_tutorial
要求會立即傳回,而資料集不會接受其他查詢或更新。資料可能需要一段時間才能完全從服務完全移除,之後資料集清單不會傳回這個資料集。
後續步驟
您可以在 GDELT 網站上找到其他範例。