Panduan Membuat Kueri

Ringkasan

Di bagian ini, kami akan menjelaskan cara mengonfigurasi kueri deteksi anomali dengan benar. Pada tingkat tinggi, ada empat jenis parameter yang perlu Anda sesuaikan:

  • Pemilihan data yang menentukan data apa yang disertakan dalam analisis kami. Contoh: QueryDataSetRequest.dimensionNames, QueryDataSetRequest.pinnedDimensions, dan QueryDataSetRequest.testedInterval.
  • Agregasi yang menentukan bagaimana beberapa peristiwa dikelompokkan untuk menghasilkan nilai yang digunakan, membandingkan irisan. Contoh: ForecastParams.aggregatedDimension.
  • Perkiraan yang digunakan untuk mengonfigurasi algoritme perkiraan yang digunakan untuk menghitung nilai yang diharapkan. Contoh: ForecastParams.holdout, ForecastParams.forecastHistory, dan ForecastParams.minDensity.
  • Penyesuaian sensitif yang, jika diubah, dapat meningkatkan atau mengurangi jumlah anomali yang dilaporkan, latensi, dan resource komputasi. Contoh: ForecastParams.maxPositiveRelativeChange, ForecastParams.maxNegativeRelativeChange, dan ForecastParams.forecastExtraWeight.

Prasyarat

Ikuti petunjuk penyiapan di Panduan memulai kami untuk memastikan Anda dapat menjalankan semua perintah dalam panduan ini.

Kami akan menunjukkan bagaimana memvariasikan setiap parameter memengaruhi hasil yang ditampilkan dengan mengajukan kueri set data demo publik yang telah kami pramuat dengan data dari Proyek GDELT.

Simpan kueri berikut sebagai query.json di direktori kerja Anda:

{
  dimensionNames: ["EntityLOCATION"],
  testedInterval: {
    startTime: "2019-04-15T00:00:00Z",
    length: "86400s"
  },
  forecastParams: {
    forecastHistory: "2592000s",
    holdout: 10.0,
    minDensity: 0.0,
    maxPositiveRelativeChange: 1.0,
    maxNegativeRelativeChange: 1.0,
    forecastExtraWeight: 200.0
  }
}

Seperti yang disebutkan dalam panduan Quickstart, Anda dapat mengeluarkan kueri dengan perintah berikut:

$ gcurl -X POST -d @query.json https://timeseriesinsights.googleapis.com/v1/projects/timeseries-insights-api-demo/datasets/webnlp-201901-202104:query

Dalam panduan ini, kami akan mengubah parameter yang berbeda di query.json untuk menunjukkan bagaimana pengaruhnya terhadap output. Anda dapat mengikuti dengan mengedit salinan dan menerbitkan ulang kueri menggunakan perintah gcurl di atas, yang ditetapkan sebagai aliad di Panduan memulai cepat.

Pemilihan data

Kueri deteksi anomali mengevaluasi apakah ada anomali dalam kumpulan data tertentu, dalam interval waktu tertentu, membagi data ke beberapa dimensi dan, secara opsional, memfilter beberapa nilai untuk beberapa dimensi. Di bagian ini, kami akan menjelaskan cara mengontrol semua langkah pemilihan data ini.

Spesifikasi interval waktu

Kita dapat menentukan interval waktu yang ingin kita selidiki untuk anomali dengan menyetel QueryDataSetRequest.tested_interval. Di query.json, kami menetapkan bahwa kami ingin mendeteksi anomali yang terjadi selama hari 15 April 2019:

...
  testedInterval: {
    startTime: "2019-04-15T00:00:00Z",
    length: "86400s"
  },
...

Jika, misalnya, kami ingin mendeteksi anomali yang terjadi pada tanggal 15 April 2019 antara pukul 13.00 dan 14.00, kami akan menyetel testedInterval ke:

...
  testedInterval: {
    startTime: "2019-04-15T13:00:00Z",
    length: "3600s"
  },
...

KIAT: Bermain dengan nilai testedInterval dengan menyetel waktu mulai dan panjang yang berbeda, serta melihat variasi anomali yang dihasilkan.

Pengirisan

Saat mendeteksi anomali dalam interval waktu tertentu, kita juga harus menentukan bagaimana peristiwa dikelompokkan ke dalam irisan data. Hal ini dilakukan dengan menyetel dimensionNames ke kumpulan dimensi yang ingin kita bagi di seluruh set data.

Di query.json kami hanya mengelompokkan data berdasarkan dimensi "EntityLOCATION": dimensionNames: ["EntityLOCATION"]. Anda dapat melihat dalam daftar hasil bahwa semua irisan adalah nilai yang berbeda untuk dimensi "EntityLocation".

Jika, alih-alih ingin mengelompokkan data lintas beberapa dimensi, kita dapat menentukan beberapa nama dimensi:

{
  dimensionNames: ["EntityLOCATION", "EntityORGANIZATION"],
  testedInterval: {
    startTime: "2019-04-15T00:00:00Z",
    length: "86400s"
  },
  forecastParams: {
    forecastHistory: "2592000s",
    holdout: 10.0,
    minDensity: 0.0,
    maxPositiveRelativeChange: 1.0,
    maxNegativeRelativeChange: 1.0,
    forecastExtraWeight: 50.0
  }
}

Saat menjalankan kueri ini, kami akan melihat bahwa irisan yang dihasilkan mengambil nilai di dua dimensi yang ditentukan, "EntityLOCATION" dan "EntityORGANIZATION" (kami hanya menampilkan irisan anomali pertama yang dikembalikan):

$ gcurl -X POST -d @query.json https://timeseriesinsights.googleapis.com/v1/projects/timeseries-insights-api-demo/datasets/webnlp-201901-202104:query

{
  "name": "projects/timeseries-insights-api-demo/datasets/webnlp-201901-202104",
  "anomalyDetectionResult": {
    "anomalies": [
      {
        "dimensions": [
          {
            "name": "EntityLOCATION",
            "stringVal": "Seine"
          },
          {
            "name": "EntityORGANIZATION",
            "stringVal": "AP"
          }
        ],
        "result": {
          "holdoutErrors": {},
          "trainingErrors": {},
          "forecastStats": {
            "numAnomalies": 1
          },
          "testedIntervalActual": 344
        },
        "status": {}
      },
...

Pemfilteran

Jika hanya tertarik menganalisis subkumpulan set data, kami hanya dapat memfilter peristiwa yang memiliki nilai tertentu di beberapa dimensi tertentu dengan menyetel pinnedDimensions.

Contoh untuk memfilter menurut EntityORGANIZATION dan memotong menurut EntityLOCATION (hanya menampilkan hasil pertama):

$ cat query.json

{
  dimensionNames: ["EntityLOCATION"],
  pinnedDimensions: [
  {
    name: "EntityORGANIZATION",
    stringVal: "AP"
  }
  ],
  testedInterval: {
    startTime: "2019-04-15T00:00:00Z",
    length: "86400s"
  },
  forecastParams: {
    forecastHistory: "2592000s",
    holdout: 10.0,
    minDensity: 0.0,
    maxPositiveRelativeChange: 1.0,
    maxNegativeRelativeChange: 1.0,
    forecastExtraWeight: 250.0
  }
}

$ gcurl -X POST -d @query.json https://timeseriesinsights.googleapis.com/v1/projects/timeseries-insights-api-demo/datasets/webnlp-201901-202104:query

{
  "name": "projects/timeseries-insights-api-demo/datasets/webnlp-201901-202104",
  "anomalyDetectionResult": {
    "anomalies": [
      {
        "dimensions": [
          {
            "name": "EntityLOCATION",
            "stringVal": "Seine"
          }
        ],
        "result": {
          "holdoutErrors": {},
          "trainingErrors": {},
          "forecastStats": {
            "numAnomalies": 1
          },
          "testedIntervalActual": 344
        },
        "status": {}
      },
      {
        "dimensions": [
          {
            "name": "EntityLOCATION",
            "stringVal": "Ile de la Cite"
          }
        ],
        "result": {
          "holdoutErrors": {},
          "trainingErrors": {},
          "forecastStats": {
            "numAnomalies": 1
          },
          "testedIntervalActual": 282
        },
        "status": {}
      },
...

Agregasi

Metode agregasi default menghitung jumlah peristiwa dalam irisan.

Kita juga dapat menentukan bahwa kita ingin menggabungkan peristiwa dengan menjumlahkan dimensi numerik. Hal tersebut ditentukan dengan menyetel ForecastParams.aggregatedDimension ke dimensi numerik yang ingin kami simpulkan.

Perkiraan konfigurasi

Untuk menghitung nilai yang diharapkan selama interval waktu yang diuji, kami menerapkan algoritme perkiraan, yang berdasarkan nilai historis untuk irisan tersebut, memprediksi nilai yang seharusnya selama interval yang diuji.

CATATAN: Nilai untuk slice diberikan oleh metode agregasi.

Perkiraan histori

Jumlah data dalam deret waktu yang diberikan oleh parameter ForecastParams.forecastHistory.

Dalam contoh awal kami:

  • Kami telah menetapkan forecastHistory: "2592000s", sehingga memberi tahu kami bahwa kami harus mengambil acara antara 16 Maret 2019 dan 15 April 2019 (30 hari, yaitu 2592000 detik) dan membentuk rangkaian waktu antara dua hari tersebut.
  • Setiap titik data dalam deret waktu akan mencakup jangka waktu yang sama dengan panjang interval yang diuji (jadi 86400s - 1 hari dalam contoh kami).
  • Rangkaian waktu akan memiliki 30 poin, setiap titik memiliki nilai gabungan untuk acara pada hari kalender tersebut. Dengan asumsi penghitungan sebagai metode agregasi kami, titik seri waktu pertama akan memiliki nilai total jumlah peristiwa pada tanggal 16 Maret 2019, titik kedua dari tanggal 17 Maret 2019, dan seterusnya.

Anda dapat melihat nilai historis untuk deret waktu yang ditampilkan di kolom ForecastResult.history (hanya akan dikembalikan jika QueryDataSetRequest.returnTimeseries disetel ke true dalam permintaan).

CATATAN: Kami membuat model deret waktu dalam proto Timeseries sebagai kumpulan titik (didefinisikan sebagai TimeseriesPoint), diurutkan menurut waktu dan memiliki nilai (TimeseriesPoint.value) nilai gabungan untuk potongan selama interval waktu [TimeseriesPoint.time, TimeseriesPoint.time + testedInterval.length].

Dengan meningkatkan ForecastParams.forecastHistory dan menyertakan histori yang lebih panjang, Anda dapat menangkap pola musiman tertentu dan, berpotensi, meningkatkan akurasi perkiraan karena akan berisi lebih banyak data. Misalnya, jika kita memiliki pola musiman musiman, menetapkan forecastHistory ke 30 hari tidak akan memungkinkan kita menangkap pola tersebut, jadi, dalam skenario ini, kita harus meningkatkan forecastHistory sehingga kita memiliki beberapa pola bulanan dalam rangkaian waktu yang dianalisis (misalnya, pola bulanan yang akan dideteksi 100-300 hari seharusnya sudah cukup, tetapi juga bergantung pada pola yang sebenarnya).

Dari contoh awal kami, coba kurangi testedInterval.length menjadi 3600s (1 jam) dan tingkatkan ForecastParams.forecastHistory menjadi 8640000s (100 hari). Ini akan meningkatkan jumlah poin dalam deret waktu history menjadi 2400, membuatnya lebih terperinci dan mencakup periode waktu yang lebih lama.

Penyisihan/interval pengujian

Untuk mengevaluasi kualitas prediksi, kami hanya melatih X% pertama dari deret waktu. Bagian terakhir dari deret waktu disimpan untuk tujuan evaluasi dan dikontrol oleh parameter ForecastParams.holdout.

Parameter ForecastParams.holdout mewakili persentase (dalam rentang 0-100) dan memberi tahu kami berapa banyak data yang harus kami simpan untuk tujuan pengujian. Dalam contoh kami, kami menentukan holdout: 10.0, jadi kami menyimpan 10% terakhir dari deret waktu untuk mengevaluasi seberapa baik prediksi berdasarkan 90% pertama.

Mempertimbangkan kita memiliki 30 titik waktu dalam contoh awal, ini menunjukkan bahwa 27 poin pertama disimpan untuk pelatihan dan 3 poin terakhir untuk pengujian/evaluasi model.

Error yang kami ukur selama periode ketidaksepakatan dikembalikan dalam ForecastResult.holdoutErrors dan error tersebut digunakan untuk menghitung perkiraan batas bawah dan atas (testedIntervalForecastLowerBound dan testedIntervalForecastUpperBound). Error penangguhan yang lebih tinggi akan memberi kami batas perkiraan yang lebih luas, sementara error yang lebih rendah akan memberi kami batas yang lebih ketat (dan mendekati ForecastResult.testedIntervalForecast).

Nilai selisih harus dalam poin persentase yang rendah (3%-10%), tetapi harus memastikan nilai tersebut berisi titik data yang cukup karena error ini diperlukan untuk penghitungan batas perkiraan.

Kepadatan min

Kepadatan minimum, yang diberikan oleh parameter ForecastParams.minDensity, menentukan berapa banyak titik rangkaian waktu yang tidak kosong (berisi setidaknya satu peristiwa) yang harus terdapat dalam deret waktu agar dapat dianggap sebagai anomali potensial.

Serupa dengan pengecualian, ini adalah nilai persentase dalam rentang 0-100.

Jumlah poin dibandingkan dengan jumlah poin yang diharapkan antara testedInterval.startTime - forecastHistory dan testedInterlal.startTime.

Misalnya, jika kita memiliki 30 titik waktu yang diharapkan (seperti yang kita miliki dalam contoh pertama yang menetapkan testedInterval.length menjadi 1 hari dan forecastHistory menjadi 30 hari) dan kita menetapkan minDensity ke 80, kita akan hanya menerima deret waktu yang berisi 24 poin dengan setidaknya satu peristiwa.

CATATAN: Dalam contoh ini, kita menetapkan minDensity ke 0 dan sebaiknya saat mendeteksi lonjakan, juga ditetapkan ke 0.

Cakrawala

Cakrawala waktu, yang ditentukan oleh ForecastParams.horizonTime hanya menentukan berapa banyak ke masa depan, dari interval yang diuji, kita harus memprediksi nilai berdasarkan deret waktu historis.

Jika QueryDataSetRequest.returnTimeseries disetel ke true, rangkaian waktu yang diperkirakan akan dikembalikan dalam ForecastResult.forecast untuk setiap potongan dan akan berisi nilai yang diprediksi antara testedInterval.startTime + testedInterval.length dan testedInterval.startTime + testedInterval.length + horizonTime.

Penyesuaian sensitif

Berdasarkan perkiraan batas dan nilai aktual selama interval yang diuji untuk sebuah irisan, kami dapat mengklasifikasikannya atau tidak sebagai anomali berdasarkan parameter sensitifitas. Parameter ini adalah:

  • ForecastParameters.maxPositiveRelativeChange menentukan seberapa besar nilai sebenarnya dapat meningkat jika dibandingkan dengan testedIntervalForecastUpperBound.
  • ForecastParameters.maxNegativeRelativeChange menentukan seberapa besar nilai yang sebenarnya dapat menurun jika dibandingkan dengan testedIntervalForecastLowerBound
  • ForecastParameters.forecastExtraWeight digunakan sebagai bobot tambahan saat membandingkan batas perkiraan dengan batas perkiraan. Memiliki bobot ekstra yang lebih tinggi berguna jika tertarik untuk mengabaikan varian absolut yang lebih kecil.

CATATAN: Kami memiliki parameter yang berbeda untuk perubahan positif dan negatif karena kami ingin memungkinkan klien kami memiliki fleksibilitas untuk memiliki ambang yang berbeda untuk lonjakan dan penurunan atau menonaktifkan satu atau lainnya dengan menetapkan batas yang sangat tinggi.

CATATAN: Nilai praktis maksimum untuk maxNegativeRelativeChange adalah 1,0 untuk deret waktu positif (misalnya, saat menghitung jumlah peristiwa sebagai metode agregasi) karena nilai tidak dapat turun lebih dari 100% dari nilai aktualnya .

Sebagai dasar, coba tetapkan semua parameter sensitifitas ini ke 0:

{
  dimensionNames: ["EntityLOCATION"],
  testedInterval: {
    startTime: "2019-04-15T00:00:00Z",
    length: "86400s"
  },
  forecastParams: {
    forecastHistory: "2592000s",
    holdout: 10.0,
    minDensity: 0.0,
    maxPositiveRelativeChange: 0.0,
    maxNegativeRelativeChange: 0.0,
    forecastExtraWeight: 0.0
  }
}

Ini adalah kueri paling sensitif yang dapat kami jalankan dan akan menandai anomali sebagai semua irisan yang memiliki testedIntervalActual di luar batas [testedIntervalForecastLowerBound, testedIntervalForecastUpperBound]. Meskipun hal ini mungkin tampak seperti yang kita inginkan (dan dapat berguna dalam beberapa aplikasi), dalam praktiknya kita akan tertarik untuk mengabaikan sebagian besar anomali ini, karena sebagian besar akan menghasilkan positif palsu.

Menjalankan kueri dasar ini akan menghasilkan ~ 2.500 anomali:

$ gcurl -X POST -d @query.json https://timeseriesinsights.googleapis.com/v1/projects/timeseries-insights-api-demo/datasets/webnlp-201901-202104:query \
    | grep "testedIntervalActual" | wc -l

2520

Jika kami meningkatkan maxPositiveRelativeChange dan maxNegativeRelativeChange menjadi 1,0, kami akan melihat bahwa jumlah anomali dikurangi menjadi ~ 1800, yang menghilangkan irisan dengan varian yang lebih kecil, namun, kami mendapatkan jumlah irisan yang tinggi sebagai anomali.

Dengan asumsi kami hanya akan tertarik dengan lonjakan terbesar dalam berita selama hari itu, kami juga dapat meningkatkan forecastExtraWeight, yang akan memfilter irisan volume rendah. Mari kita setel ke 200.0, yang akan memberi kita query.json terakhir:

{
  dimensionNames: ["EntityLOCATION"],
  testedInterval: {
    startTime: "2019-04-15T00:00:00Z",
    length: "86400s"
  },
  forecastParams: {
    forecastHistory: "2592000s",
    holdout: 10.0,
    minDensity: 0.0,
    maxPositiveRelativeChange: 1.0,
    maxNegativeRelativeChange: 1.0,
    forecastExtraWeight: 200.0
  }
}

Menjalankan kueri sebelumnya hanya akan menghasilkan 3 anomali, semuanya terkait dengan kebakaran Notre Dame, yang merupakan peristiwa yang paling banyak disebutkan dalam berita pada tanggal 15 April 2019:

$ gcurl -X POST -d @query.json https://timeseriesinsights.googleapis.com/v1/projects/timeseries-insights-api-demo/datasets/webnlp-201901-202104:query \
    | grep stringVal

            "stringVal": "Ile de la Cite"
            "stringVal": "Notre Dame"
            "stringVal": "Seine"

Kinerja kueri dan penggunaan resource

Selain mengurangi derau dan memfilter irisan yang tidak menarik, mengurangi sensitifitas deteksi anomali juga dapat mengurangi latensi kueri dan penggunaan resource secara signifikan.

Karena peningkatan forecastExtraWeight biasanya menghasilkan pengurangan yang paling mencolok pada irisan anomali, ini juga merupakan parameter sensitifitas utama yang harus ditingkatkan dengan tujuan meningkatkan performa kueri.

Anda dapat bermain dengan parameter sensitifitas yang berbeda untuk melihat pengaruhnya terhadap performa kueri. Contoh:

$ cat query.json

{
  dimensionNames: ["EntityLOCATION"],
  testedInterval: {
    startTime: "2019-04-15T00:00:00Z",
    length: "86400s"
  },
  forecastParams: {
    forecastHistory: "2592000s",
    holdout: 10.0,
    minDensity: 0.0,
    maxPositiveRelativeChange: 0.0,
    maxNegativeRelativeChange: 0.0,
    forecastExtraWeight: 0.0
  }
}

$ time gcurl -X POST -d @query.json https://timeseriesinsights.googleapis.com/v1/projects/timeseries-insights-api-demo/datasets/webnlp-201901-202104:query \
    | grep stringVal | wc -l

2580

real 0m26.765s
user 0m0.618s
sys  0m0.132s

Kita dapat melihat bahwa parameter yang paling sensitif menyebabkan kueri kami mengambil waktu sekitar 26,7 detik. Mengurangi sensitifitas memberikan peningkatan kecepatan hingga ~ 3,4 detik:

$ cat query.json

{
  dimensionNames: ["EntityLOCATION"],
  testedInterval: {
    startTime: "2019-04-15T00:00:00Z",
    length: "86400s"
  },
  forecastParams: {
    forecastHistory: "2592000s",
    holdout: 10.0,
    minDensity: 0.0,
    maxPositiveRelativeChange: 1.0,
    maxNegativeRelativeChange: 1.0,
    forecastExtraWeight: 200.0
  }
}

$ time gcurl -X POST -d @query.json https://timeseriesinsights.googleapis.com/v1/projects/timeseries-insights-api-demo/datasets/webnlp-201901-202104:query \
    | grep stringVal | wc -l

3

real 0m3.412s
user 0m0.681s
sys  0m0.047s

Langkah berikutnya