Partilhar via


series_uv_anomalies_fl()

Aplica-se a: ✅Microsoft FabricAzure Data Explorer

A função series_uv_anomalies_fl() é uma UDF (função definida pelo usuário) que detecta anomalias em séries temporais chamando a API de Detecção de Anomalias Univariadas, parte dos Serviços Cognitivos do Azure. A função aceita um conjunto limitado de séries temporais como matrizes dinâmicas numéricas e o nível de confidencialidade de detecção de anomalias necessário. Cada série temporal é convertida no formato JSON necessário e a posta no ponto de extremidade de serviço do Detector de Anomalias. A resposta de serviço contém matrizes dinâmicas de anomalias altas/baixas/todas, a série temporal de linha de base modelada, seus limites normais, alto/baixo (um valor acima ou abaixo do limite alto/baixo é uma anomalia) e a sazonalidade detectada.

Observação

Considere usar a função nativa series_decompose_anomalies(), que é mais escalável e é executada mais rapidamente.

Pré-requisitos

No exemplo de função a seguir, substitua YOUR-AD-RESOURCE-NAME no uri e YOUR-KEY no Ocp-Apim-Subscription-Key cabeçalho pelo nome e pela chave do recurso do Detector de Anomalias.

Sintaxe

T | invoke series_uv_anomalies_fl( y_series [ , sensibilidade [, tsid]])

Saiba mais sobre as convenções de sintaxe.

Parâmetros

Nome Digitar Obrigatória Descrição
y_series string ✔️ O nome da coluna da tabela de entrada que contém os valores da série a ser detectada por anomalias.
sensibilidade Número inteiro Um número inteiro no intervalo [0-100] que especifica a sensibilidade de detecção de anomalias. 0 é a detecção menos sensível, enquanto 100 é a mais sensível, indicando que mesmo um pequeno desvio da linha de base esperada seria marcado como anomalia. Valor padrão: 85
tsid string O nome da coluna da tabela de entrada que contém a ID da série temporal. Pode ser omitido ao analisar uma única série temporal.

Definição de função

Você pode definir a função inserindo seu código como uma função definida por consulta ou criando-a como uma função armazenada em seu banco de dados, da seguinte maneira:

Defina a função usando a instrução let a seguir. Nenhuma permissão é necessária.

Importante

Uma instrução let não pode ser executada sozinha. Ele deve ser seguido por uma instrução de expressão tabular. Para executar um exemplo funcional de series_uv_anomalies_fl(), consulte Exemplos.

let series_uv_anomalies_fl=(tbl:(*), y_series:string, sensitivity:int=85, tsid:string='_tsid')
{
    let uri = 'https://YOUR-AD-RESOURCE-NAME.cognitiveservices.azure.com/anomalydetector/v1.0/timeseries/entire/detect';
    let headers=dynamic({'Ocp-Apim-Subscription-Key': h'YOUR-KEY'});
    let kwargs = bag_pack('y_series', y_series, 'sensitivity', sensitivity);
    let code = ```if 1:
        import json
        y_series = kargs["y_series"]
        sensitivity = kargs["sensitivity"]
        json_str = []
        for i in range(len(df)):
            row = df.iloc[i, :]
            ts = [{'value':row[y_series][j]} for j in range(len(row[y_series]))]
            json_data = {'series': ts, "sensitivity":sensitivity}     # auto-detect period, or we can force 'period': 84. We can also add 'maxAnomalyRatio':0.25 for maximum 25% anomalies
            json_str = json_str + [json.dumps(json_data)]
        result = df
        result['json_str'] = json_str
    ```;
    tbl
    | evaluate python(typeof(*, json_str:string), code, kwargs)
    | extend _tsid = column_ifexists(tsid, 1)
    | partition by _tsid (
       project json_str
       | evaluate http_request_post(uri, headers, dynamic(null))
       | project period=ResponseBody.period, baseline_ama=ResponseBody.expectedValues, ad_ama=series_add(0, ResponseBody.isAnomaly), pos_ad_ama=series_add(0, ResponseBody.isPositiveAnomaly)
       , neg_ad_ama=series_add(0, ResponseBody.isNegativeAnomaly), upper_ama=series_add(ResponseBody.expectedValues, ResponseBody.upperMargins), lower_ama=series_subtract(ResponseBody.expectedValues, ResponseBody.lowerMargins)
       | extend _tsid=toscalar(_tsid)
      )
};
// Write your query to use the function here.

Exemplos

Os exemplos a seguir usam o operador invoke para executar a função.

Use series_uv_anomalies_fl() para detectar anomalias

Para usar uma função definida por consulta, invoque-a após a definição da função inserida.

let series_uv_anomalies_fl=(tbl:(*), y_series:string, sensitivity:int=85, tsid:string='_tsid')
{
    let uri = 'https://YOUR-AD-RESOURCE-NAME.cognitiveservices.azure.com/anomalydetector/v1.0/timeseries/entire/detect';
    let headers=dynamic({'Ocp-Apim-Subscription-Key': h'YOUR-KEY'});
    let kwargs = bag_pack('y_series', y_series, 'sensitivity', sensitivity);
    let code = ```if 1:
        import json
        y_series = kargs["y_series"]
        sensitivity = kargs["sensitivity"]
        json_str = []
        for i in range(len(df)):
            row = df.iloc[i, :]
            ts = [{'value':row[y_series][j]} for j in range(len(row[y_series]))]
            json_data = {'series': ts, "sensitivity":sensitivity}     # auto-detect period, or we can force 'period': 84. We can also add 'maxAnomalyRatio':0.25 for maximum 25% anomalies
            json_str = json_str + [json.dumps(json_data)]
        result = df
        result['json_str'] = json_str
    ```;
    tbl
    | evaluate python(typeof(*, json_str:string), code, kwargs)
    | extend _tsid = column_ifexists(tsid, 1)
    | partition by _tsid (
       project json_str
       | evaluate http_request_post(uri, headers, dynamic(null))
       | project period=ResponseBody.period, baseline_ama=ResponseBody.expectedValues, ad_ama=series_add(0, ResponseBody.isAnomaly), pos_ad_ama=series_add(0, ResponseBody.isPositiveAnomaly)
       , neg_ad_ama=series_add(0, ResponseBody.isNegativeAnomaly), upper_ama=series_add(ResponseBody.expectedValues, ResponseBody.upperMargins), lower_ama=series_subtract(ResponseBody.expectedValues, ResponseBody.lowerMargins)
       | extend _tsid=toscalar(_tsid)
      )
};
let etime=datetime(2017-03-02);
let stime=datetime(2017-01-01);
let dt=1h;
let ts = requests
| make-series value=avg(value) on timestamp from stime to etime step dt
| extend _tsid='TS1';
ts
| invoke series_uv_anomalies_fl('value')
| lookup ts on _tsid
| render anomalychart with(xcolumn=timestamp, ycolumns=value, anomalycolumns=ad_ama)

Saída

Gráfico mostrando anomalias em uma série temporal.

Compare series_uv_anomalies_fl() e nativo series_decompose_anomalies()

O exemplo a seguir compara a API de Detecção de Anomalias Univariadas com a função nativa em três séries temporais series_decompose_anomalies() e pressupõe que a series_uv_anomalies_fl() função já esteja definida no banco de dados:

Para usar uma função definida por consulta, invoque-a após a definição da função inserida.

let series_uv_anomalies_fl=(tbl:(*), y_series:string, sensitivity:int=85, tsid:string='_tsid')
{
    let uri = 'https://YOUR-AD-RESOURCE-NAME.cognitiveservices.azure.com/anomalydetector/v1.0/timeseries/entire/detect';
    let headers=dynamic({'Ocp-Apim-Subscription-Key': h'YOUR-KEY'});
    let kwargs = bag_pack('y_series', y_series, 'sensitivity', sensitivity);
    let code = ```if 1:
        import json
        y_series = kargs["y_series"]
        sensitivity = kargs["sensitivity"]
        json_str = []
        for i in range(len(df)):
            row = df.iloc[i, :]
            ts = [{'value':row[y_series][j]} for j in range(len(row[y_series]))]
            json_data = {'series': ts, "sensitivity":sensitivity}     # auto-detect period, or we can force 'period': 84. We can also add 'maxAnomalyRatio':0.25 for maximum 25% anomalies
            json_str = json_str + [json.dumps(json_data)]
        result = df
        result['json_str'] = json_str
    ```;
    tbl
    | evaluate python(typeof(*, json_str:string), code, kwargs)
    | extend _tsid = column_ifexists(tsid, 1)
    | partition by _tsid (
       project json_str
       | evaluate http_request_post(uri, headers, dynamic(null))
       | project period=ResponseBody.period, baseline_ama=ResponseBody.expectedValues, ad_ama=series_add(0, ResponseBody.isAnomaly), pos_ad_ama=series_add(0, ResponseBody.isPositiveAnomaly)
       , neg_ad_ama=series_add(0, ResponseBody.isNegativeAnomaly), upper_ama=series_add(ResponseBody.expectedValues, ResponseBody.upperMargins), lower_ama=series_subtract(ResponseBody.expectedValues, ResponseBody.lowerMargins)
       | extend _tsid=toscalar(_tsid)
      )
};
let ts = demo_make_series2
| summarize TimeStamp=make_list(TimeStamp), num=make_list(num) by sid;
ts
| invoke series_uv_anomalies_fl('num', 'sid', 90)
| join ts on $left._tsid == $right.sid
| project-away _tsid
| extend (ad_adx, score_adx, baseline_adx)=series_decompose_anomalies(num, 1.5, -1, 'linefit')
| project-reorder num, *
| render anomalychart with(series=sid, xcolumn=TimeStamp, ycolumns=num, baseline_adx, baseline_ama, lower_ama, upper_ama, anomalycolumns=ad_adx, ad_ama)

Saída

O gráfico a seguir mostra anomalias detectadas pela API de Detecção de Anomalias Univariadas no TS1. Você também pode selecionar TS2 ou TS3 na caixa de filtro de gráfico.

Gráfico mostrando anomalias usando o Univariate A P I em uma série temporal.

O gráfico a seguir mostra as anomalias detectadas pela função nativa no TS1.

Gráfico mostrando anomalias usando a função nativa em uma série temporal.