Recuperar registros semelhantes com funções de ordem superior

Use as funções de ordem superior do Data Distiller para resolver vários casos de uso comuns. Para identificar e recuperar registros semelhantes ou relacionados de um ou mais conjuntos de dados, use as funções de filtragem, transformação e redução, conforme detalhado neste guia. Para saber como funções de ordem superior podem ser usadas para processar tipos de dados complexos, consulte a documentação sobre como gerenciar matriz e mapear tipos de dados.

Use este guia para identificar produtos de diferentes conjuntos de dados que tenham uma semelhança significativa em suas características ou atributos. Essa metodologia fornece soluções para: desduplicação de dados, vinculação de registros, sistemas de recomendação, recuperação de informações e análise de texto, entre outras.

O documento descreve o processo de implementação de uma junção de similaridade, que usa funções de ordem superior do Data Distiller para calcular a similaridade entre conjuntos de dados e filtrá-los com base em atributos selecionados. São fornecidos trechos de código SQL e explicações para cada etapa do processo. O workflow implementa junções de similaridade usando a medida de similaridade Jaccard e a tokenização usando funções de ordem superior do Data Distiller. Esses métodos são usados para identificar e recuperar registros semelhantes ou relacionados de um ou mais conjuntos de dados com base em uma métrica de similaridade. As principais seções do processo incluem: tokenização usando funções de ordem superior, a junção cruzada de elementos exclusivos, o cálculo de similaridade de Jaccard e a filtragem baseada em limite.

Pré-requisitos

Antes de continuar com este documento, você deve se familiarizar com os seguintes conceitos:

  • Uma junção de similaridade é uma operação que identifica e recupera pares de registros de uma ou mais tabelas com base em uma medida de similaridade entre os registros. Os principais requisitos para uma junção de similaridade são os seguintes:

    • Métrica de similaridade: uma junção de similaridade depende de uma métrica ou medida de similaridade predefinida. Essas métricas incluem: similaridade de Jaccard, similaridade do cosseno, distância de edição, e assim por diante. A métrica depende da natureza dos dados e do caso de uso. Essa métrica quantifica a semelhança ou diferença entre dois registros.
    • Limite: um limite de similaridade é usado para determinar quando os dois registros são considerados semelhantes o suficiente para serem incluídos no resultado de junção. Os registros com uma pontuação de similaridade acima do limite são considerados correspondências.
  • O índice de similaridade de Jaccard, ou a medida de similaridade de Jaccard, é uma estatística usada para medir a similaridade e a diversidade dos conjuntos de amostras. É definido como o tamanho da interseção dividido pelo tamanho da união dos conjuntos de amostra. A medida de similaridade de Jaccard varia de zero a um. Uma similaridade de Jaccard de zero indica nenhuma similaridade entre os conjuntos, e uma similaridade de Jaccard de um indica que os conjuntos são idênticos.
    Um diagrama de Venn para ilustrar a medida de similaridade de Jaccard.

  • As funções de ordem superior no Data Distiller são ferramentas dinâmicas e integradas que processam e transformam dados diretamente nas instruções SQL. Essas funções versáteis eliminam a necessidade de várias etapas na manipulação de dados, especialmente quando se trata de tipos complexos como matrizes e mapas. Ao melhorar a eficiência da consulta e simplificar as transformações, as funções de alto nível contribuem para uma análise mais ágil e uma melhor tomada de decisões em vários cenários de negócios.

Introdução

O SKU do Data Distiller é necessário para executar as funções de ordem superior nos dados do Adobe Experience Platform. Se você não tiver o Data Distiller SKU, entre em contato com o representante do serviço de atendimento ao cliente da Adobe para obter mais informações.

Estabelecer similaridade establish-similarity

Este caso de uso requer uma medida de similaridade entre cadeias de texto que podem ser usadas posteriormente para estabelecer um limite para filtragem. Neste exemplo, os produtos no Conjunto A e no Conjunto B representam as palavras em dois documentos.

A medida de similaridade de Jaccard pode ser aplicada a uma grande variedade de tipos de dados, incluindo dados de texto, dados categóricos e dados binários. Também é adequado para processamento em tempo real ou em lote, pois pode ser computacionalmente eficiente para calcular conjuntos de dados grandes.

O Conjunto de produtos A e o Conjunto B contêm os dados de teste para esse workflow.

  • Conjunto de Produtos A: {iPhone, iPad, iWatch, iPad Mini}
  • Conjunto de Produtos B: {iPhone, iPad, Macbook Pro}

Para calcular a similaridade de Jaccard entre os conjuntos de produtos A e B, localize primeiro a interseção (elementos comuns) dos conjuntos de produtos. Neste caso, {iPhone, iPad}. Em seguida, localize a união (todos os elementos exclusivos) de ambos os conjuntos de produtos. Neste exemplo, {iPhone, iPad, iWatch, iPad Mini, Macbook Pro}.

Finalmente, use a fórmula de similaridade de Jaccard: J(A,B) = A∪B / A∩B para calcular a similaridade.

J = Distância de Jacard
A = conjunto 1
B = conjunto 2

A similaridade de Jaccard entre os conjuntos de produtos A e B é de 0,4. Isso indica um grau moderado de similaridade entre as palavras usadas nos dois documentos. Essa similaridade entre os dois conjuntos define as colunas na junção de similaridade. Essas colunas representam informações, ou características associadas aos dados, que são armazenadas em uma tabela e usadas para executar os cálculos de similaridade.

Computação de Jaccard emparelhada com similaridade de strings pairwise-similarity

Para comparar com mais precisão as semelhanças entre as cadeias de caracteres, a similaridade emparelhada deve ser calculada. A similaridade emparelhada divide objetos altamente dimensionais em objetos dimensionais menores para comparação e análise. Para fazer isso, uma cadeia de caracteres de texto é dividida em partes ou unidades menores (tokens). Elas podem ser letras individuais, grupos de letras (como sílabas) ou palavras inteiras. A similaridade é calculada para cada par de tokens entre cada elemento no Conjunto A com cada elemento no Conjunto B. Essa geração de tokens fornece uma base para comparações analíticas e computacionais, relações e insights a serem obtidos dos dados.

Para o cálculo de similaridade em pares, este exemplo usa bigramas de caracteres (dois tokens de caracteres) para comparar uma correspondência de similaridade entre as strings de texto dos produtos no Conjunto A e no Conjunto B. Um bigrama é uma sequência consecutiva de dois itens ou elementos em uma determinada sequência ou texto. Você pode generalizar isso para n-gramas.

Este exemplo pressupõe que o caso não importa e que os espaços não devem ser contabilizados. De acordo com esses critérios, o conjunto A e o conjunto B têm os seguintes bigramas:

Conjunto de produtos A, em gramas:

  • iPhone (5): "ip", "ph", "ho", "on", "ne"
  • iPad (3): "ip", "pa", "ad"
  • iWatch (5): "iw", "wa", "at", "tc", "ch"
  • iPad Mini (7): "ip", "pa", "ad", "dm", "mi", "in", "ni"

Grupo de produtos B, em bigramas:

  • iPhone (5): "ip", "ph", "ho", "on", "ne"
  • iPad (3): "ip", "pa", "ad"
  • Macbook Pro (9): "Ma", "ac", "cb", "bo", "oo", "ok", "kp", "pr", "ro"

Em seguida, calcule o coeficiente de similaridade de Jaccard para cada par:

iPhone (Conjunto B)
iPad (Conjunto B)
Macbook Pro (Conjunto B)
iPhone (Conjunto A)
(Interseção: 5, União: 5) = 5 / 5 = 1
(Interseção: 1, União: 7) =1 / 7 ≈ 0.14
(Interseção: 0, União: 14) = 0 / 14 = 0
iPad (Conjunto A)
(Interseção: 1, União: 7) = 1 / 7 ≈ 0,14
(Interseção: 3, União: 3) = 3 / 3 = 1
(Interseção: 0, União: 12) = 0 / 12 = 0
iWatch (conjunto A)
(Interseção: 0, União: 8) = 0 / 8 = 0
(Interseção: 0, União: 8) = 0 / 8 = 0
(Interseção: 0, União: 8) = 0 / 8 =0
iPad Mini (Conjunto A)
(Interseção: 1, União: 11) = 1 / 11 ≈ 0,09
(Interseção: 3, União: 7) = 3 / 7 ≈ 0,43
(Interseção: 0, União: 16) = 0 / 16 = 0

Criar os dados de teste com SQL create-test-data

Para criar manualmente uma tabela de teste para os conjuntos de produtos, use a instrução SQL CREATE TABLE.

CREATE TABLE featurevector1 AS SELECT *
FROM (
    SELECT 'iPad' AS ProductName
    UNION ALL
    SELECT 'iPhone'
    UNION ALL
    SELECT 'iWatch'
     UNION ALL
    SELECT 'iPad Mini'
);
SELECT * FROM featurevector1;

As descrições a seguir fornecem um detalhamento do bloco de código SQL acima:

  • Linha 1: CREATE TEMP TABLE featurevector1 AS: Essa instrução cria uma tabela temporária chamada featurevector1. Normalmente, as tabelas temporárias só podem ser acessadas na sessão atual e são descartadas automaticamente no final da sessão.
  • Linhas 1 e 2: SELECT * FROM (...): Essa parte do código é uma subconsulta usada para gerar os dados inseridos na tabela featurevector1.
    Dentro da subconsulta, várias instruções SELECT são combinadas usando o comando UNION ALL. Cada instrução SELECT gera uma linha de dados com os valores especificados para a coluna ProductName.
  • Linha 3: SELECT 'iPad' AS ProductName: isso gera uma linha com o valor iPad na coluna ProductName.
  • Linha 5: SELECT 'iPhone': isso gera uma linha com o valor iPhone na coluna ProductName.

A instrução SQL cria uma tabela como visto abaixo:

ProductName
1
iPad
2
iPhone
3
iWatch
4
iPad Mini

Para criar o segundo vetor de recurso, use a seguinte instrução SQL:

CREATE TABLE featurevector2 AS SELECT *
FROM (
    SELECT 'iPad' AS ProductName
    UNION ALL
    SELECT 'iPhone'
    UNION ALL
    SELECT 'Macbook Pro'
);
SELECT * FROM featurevector2;

Transformações de dados data-transformation

Neste exemplo, várias ações devem ser executadas para comparar com precisão os conjuntos. Primeiro, todos os espaços em branco são removidos dos vetores de recursos, pois assume-se que não contribuem para a medida de similaridade. Em seguida, quaisquer duplicatas presentes no vetor de recurso são removidas, pois desperdiçam o processamento computacional. Em seguida, tokens de dois caracteres (bigramas) são extraídos dos vetores de recursos. Neste exemplo, supõe-se que estejam sobrepostas.

NOTE
Para fins de ilustração, as colunas processadas são adicionadas ao lado do vetor de recurso para cada uma das etapas.

As seções a seguir ilustram as transformações de dados de pré-requisito, como desduplicação, remoção de espaços em branco e conversão de minúsculas, antes de iniciar o processo de geração de tokens.

Desduplicação deduplication

Em seguida, use a cláusula DISTINCT para remover duplicatas. Não há duplicatas neste exemplo, no entanto, é uma etapa importante para melhorar a precisão de qualquer comparação. O SQL necessário é exibido abaixo:

SELECT DISTINCT(ProductName) AS featurevector1_distinct FROM featurevector1
SELECT DISTINCT(ProductName) AS featurevector2_distinct FROM featurevector2

Remoção de espaço em branco whitespace-removal

Na instrução SQL a seguir, os espaços em branco são removidos dos vetores de recursos. A parte replace(ProductName, ' ', '') AS featurevector1_nospaces da consulta pega a coluna ProductName da tabela featurevector1 e usa a função replace(). A função REPLACE substitui todas as ocorrências de um espaço (' ') por uma cadeia de caracteres vazia (''). Isso remove efetivamente todos os espaços dos valores ProductName. O resultado recebeu o alias de featurevector1_nospaces.

SELECT DISTINCT(ProductName) AS featurevector1_distinct, replace(ProductName, ' ', '') AS featurevector1_nospaces FROM featurevector1

Os resultados são mostrados na tabela abaixo:

featurevetor1_distinct
featurevetor1_nospaces
1
iPad Mini
iPadMini
2
iPad
iPad
3
iWatch
iWatch
4
iPhone
iPhone

A instrução SQL e seus resultados no segundo vetor de recurso são vistos abaixo:

Selecione para expandir
code language-sql
SELECT DISTINCT(ProductName) AS featurevector2_distinct, replace(ProductName, ' ', '') AS featurevector2_nospaces FROM featurevector2

Os resultados são exibidos conforme abaixo:

table 0-row-3 1-row-3 2-row-3 3-row-3 layout-auto
featurevetor2_distinct featurevetor2_nospaces
1 iPad iPad
2 Macbook Pro MacbookPro
3 iPhone iPhone

Converter para minúsculas lowercase-conversion

Em seguida, o SQL é aprimorado para converter os nomes de produtos em minúsculas e remover espaços em branco. A função inferior (lower(...)) é aplicada ao resultado da função replace(). A função lower converte todos os caracteres nos valores ProductName modificados em minúsculas. Isso garante que os valores estejam em minúsculas, independentemente da caixa original.

SELECT DISTINCT(ProductName) AS featurevector1_distinct, lower(replace(ProductName, ' ', '')) AS featurevector1_transform FROM featurevector1;

O resultado dessa instrução é:

featurevetor1_distinct
featurevetor1_transform
1
iPad Mini
ipadmini
2
iPad
iPad
3
iWatch
iWatch
4
iPhone
iPhone

A instrução SQL e seus resultados no segundo vetor de recurso são vistos abaixo:

Selecione para expandir
code language-sql
SELECT DISTINCT(ProductName) AS featurevector2_distinct, lower(replace(ProductName, ' ', '')) AS featurevector2_transform FROM featurevector2

Os resultados são exibidos conforme abaixo:

table 0-row-3 1-row-3 2-row-3 3-row-3 layout-auto
featurevetor2_distinct featurevetor2_transform
1 iPad ipad
2 Macbook Pro macbookpro
3 iPhone iphone

Extrair tokens usando SQL tokenization

A próxima etapa é a geração de tokens ou a divisão de texto. Tokenization é o processo de pegar o texto e quebrá-lo em termos individuais. Normalmente, isso envolve dividir frases em palavras. Neste exemplo, as cadeias de caracteres são divididas em bigramas (e n-gramas de ordem superior) extraindo tokens usando funções SQL como regexp_extract_all. Bigramas sobrepostos devem ser gerados para geração de tokens eficaz.

O SQL foi aprimorado para usar regexp_extract_all. regexp_extract_all(lower(replace(ProductName, ' ', '')), '.{2}', 0) AS tokens: Essa parte da consulta processa ainda mais os ProductName valores modificados criados na etapa anterior. Ele usa a função regexp_extract_all() para extrair todas as subcadeias de um a dois caracteres não sobrepostas dos valores ProductName modificados e em minúsculas. O padrão de expressão regular .{2} corresponde a subsequências de dois caracteres de comprimento. A parte regexp_extract_all(..., '.{2}', 0) da função extrai todas as subsequências correspondentes do texto de entrada.

SELECT DISTINCT(ProductName) AS featurevector1_distinct, lower(replace(ProductName, ' ', '')) AS featurevector1_transform,
regexp_extract_all(lower(replace(ProductName, ' ', '')) , '.{2}', 0) AS tokens
FROM featurevector1;

Os resultados são mostrados na tabela abaixo:

Selecione para expandir
table 0-row-4 1-row-4 2-row-4 3-row-4 4-row-4 layout-auto
featurevetor1_distinct featurevetor1_transform tokens
1 iPad Mini ipadmini {"ip","ad","mi","ni"}
2 iPad iPad {"ip","ad"}
3 iWatch iWatch {"iw","at", "ch"}
4 iPhone iPhone {"ip","ho","ne"}

Para melhorar ainda mais a precisão, o SQL deve ser usado para criar tokens sobrepostos. Por exemplo, a cadeia de caracteres "iPad" acima não tem o token "pa". Para corrigir isso, alterne o operador de lookahead (usando substring) em uma etapa e gere os bigramas.

Semelhante à etapa anterior, o regexp_extract_all(lower(replace(substring(ProductName, 2), ' ', '')), '.{2}', 0): extrai sequências de dois caracteres do nome do produto modificado, mas começa com o segundo caractere usando o método substring para criar tokens sobrepostos. Em seguida, nas linhas 3-7 (array_union(...) AS tokens), a função array_union() combina as matrizes de sequências de dois caracteres obtidas pelas duas extrações de expressão regular. Isso garante que o resultado contenha tokens exclusivos de sequências não sobrepostas e sobrepostas.

SELECT DISTINCT(ProductName) AS featurevector1_distinct,
       lower(replace(ProductName, ' ', '')) AS featurevector1_transform,
       array_union(
           regexp_extract_all(lower(replace(ProductName, ' ', '')), '.{2}', 0),
           regexp_extract_all(lower(replace(substring(ProductName, 2), ' ', '')), '.{2}', 0)
       ) AS tokens
FROM featurevector1;

Os resultados são mostrados na tabela abaixo:

Selecione para expandir
table 0-row-4 1-row-4 2-row-4 3-row-4 4-row-4 layout-auto
featurevetor1_distinct featurevetor1_transform tokens
1 iPad Mini ipadmini {"ip","ad","mi","ni","pa","dm","in"}
2 iPad iPad {"ip","ad","pa"}
3 iWatch iWatch {"iw","at","ch","wa","tc"}
4 iPhone iPhone {"ip","ho","ne","ph","on"}

No entanto, o uso do substring como solução para o problema tem limitações. Se você fizesse tokens do texto com base em trigramas (três caracteres), seria necessário usar dois substrings para analisar com antecedência para obter os turnos necessários. Para criar 10 gramas, você precisaria de nove expressões substring. Isso faria o código inflar e se torna insustentável. O uso de expressões regulares simples não é adequado. É necessária uma nova abordagem.

Ajustar para o comprimento do nome do produto length-adjustment

O SQl pode ser melhorado com as funções de sequência e comprimento. No exemplo a seguir, sequence(1, length(lower(replace(ProductName, ' ', ''))) - 3) gera uma sequência de números de um ao comprimento do nome de produto modificado menos três. Por exemplo, se o nome do produto modificado for "ipadmini" com um comprimento de caracteres de oito, ele gerará números de um a cinco (oito a três).

A instrução abaixo extrai nomes de produtos exclusivos e depois divide cada nome em sequências de caracteres (tokens) de quatro tamanhos de caracteres, excluindo espaços e apresentando-os como duas colunas. Uma coluna mostra os nomes exclusivos de produtos e a outra mostra os tokens gerados.

SELECT
   DISTINCT(ProductName) AS featurevector1_distinct,
  transform(
    sequence(1, length(lower(replace(ProductName, ' ', ''))) - 3),
    i -> substring(lower(replace(ProductName, ' ', '')), i, 4)
  ) AS tokens
FROM
  featurevector1;

Os resultados são mostrados na tabela abaixo:

Selecione para expandir
table 0-row-3 1-row-3 2-row-3 3-row-3 4-row-3 layout-auto
featurevetor1_distinct tokens
1 iPad Mini {"ipad","padm","admi","dmin","mini"}
2 iPad {"ipad"}
3 iWatch {"iwat","watc","atch"}
4 iPhone {"ipho","phone","phone"}

Garantir o comprimento do token definido ensure-set-token-length

Condições adicionais podem ser adicionadas à instrução para garantir que as sequências geradas sejam de um comprimento específico. A instrução SQL a seguir se expande na lógica de geração de token tornando a função transform mais complexa. A instrução usa a função filter em transform para garantir que as sequências geradas tenham seis caracteres de comprimento. Ela trata os casos em que isso não é possível, atribuindo valores NULL a essas posições.

SELECT
  DISTINCT(ProductName) AS featurevector1_distinct,
  transform(
    filter(
      sequence(1, length(lower(replace(ProductName, ' ', ''))) - 5),
      i -> i + 5 <= length(lower(replace(ProductName, ' ', '')))
    ),
    i -> CASE WHEN length(substring(lower(replace(ProductName, ' ', '')), i, 6)) = 6
               THEN substring(lower(replace(ProductName, ' ', '')), i, 6)
               ELSE NULL
          END
  ) AS tokens
FROM
  featurevector1;

Os resultados são mostrados na tabela abaixo:

Selecione para expandir
table 0-row-3 1-row-3 2-row-3 3-row-3 4-row-3 layout-auto
featurevetor1_distinct tokens
1 iPad Mini {"ipadmi","padmin","admini"}
2 iPad
3 iWatch {"iwatch"}
4 iPhone {"iphone"}

Explorar soluções usando funções de ordem superior do Data Distiller higher-order-function-solutions

Funções de ordem superior são construções poderosas que permitem implementar "programação" como sintaxe no Data Distiller. Eles podem ser usados para iterar uma função sobre vários valores em uma matriz.

No contexto do Data Distiller, funções de ordem mais alta são ideais para criar n-gramas e iterar sequências de caracteres.

A função reduce, especialmente quando usada em sequências geradas por transform, fornece uma maneira de derivar valores cumulativos ou agregações, que podem ser fundamentais em vários processos analíticos e de planejamento.

Por exemplo, na instrução SQL abaixo, a função reduce() agrega elementos em uma matriz usando um agregador personalizado. Ele simula um loop for para criar as somas cumulativas de todos os números inteiros de um a cinco. 1, 1+2, 1+2+3, 1+2+3+4, 1+2+3+4.

SELECT transform(
    sequence(1, 5),
    x -> reduce(
        sequence(1, x),
        0,  -- Initial accumulator value
        (acc, y) -> acc + y  -- Higher-order function to add numbers
    )
) AS sum_result;

Veja a seguir uma análise da instrução SQL:

  • Linha 1: transform aplica a função x -> reduce em cada elemento gerado na sequência.

  • Linha 2: sequence(1, 5) gera uma sequência de números de um a cinco.

  • Linha 3: x -> reduce(sequence(1, x), 0, (acc, y) -> acc + y) executa uma operação de redução para cada elemento x na sequência (de 1 a 5).

    • A função reduce usa um valor de acumulador inicial de 0, uma sequência de um ao valor atual de x, e uma função de ordem superior (acc, y) -> acc + y para adicionar os números.
    • A função de ordem superior acc + y acumula a soma adicionando o valor atual y ao acumulador acc.
  • Linha 8: AS sum_result renomeia a coluna resultante como sum_result.

Para resumir, esta função de ordem superior pega dois parâmetros (acc e y) e define a operação a ser executada, que neste caso está adicionando y ao acumulador acc. Essa função de ordem superior é executada para cada elemento na sequência durante o processo de redução.

A saída desta instrução é uma única coluna (sum_result) que contém as somas cumulativas de números de um a cinco.

O valor de funções de ordem superior value-of-higher-order-functions

Esta seção analisa uma versão reduzida de uma instrução SQL de três gramas para entender melhor o valor de funções de ordem superior no Data Distiller para criar n-gramas com mais eficiência.

A instrução abaixo opera na coluna ProductName dentro da tabela featurevector1. Ele produz um conjunto de substrings de três caracteres derivadas dos nomes de produtos modificados na tabela, usando posições obtidas da sequência gerada.

SELECT
  transform(
    sequence(1, length(lower(replace(ProductName, ' ', ''))) - 2),
    i -> substring(lower(replace(ProductName, ' ', '')), i, 3)
  )
FROM
  featurevector1

Veja a seguir uma análise da instrução SQL:

  • Linha 2: transform aplica uma função de ordem superior a cada inteiro na sequência.

  • Linha 3: sequence(1, length(lower(replace(ProductName, ' ', ''))) - 2) gera uma sequência de inteiros de 1 até o comprimento do nome de produto modificado menos dois.

    • length(lower(replace(ProductName, ' ', ''))) calcula o comprimento de ProductName depois de colocar em minúsculas e remover espaços.
    • - 2 subtrai dois do comprimento para garantir que a sequência gere posições iniciais válidas para subcadeias de 3 caracteres. Subtrair 2 garante que você tenha caracteres suficientes após cada posição inicial para extrair uma substring de 3 caracteres. A função de subsequência de caracteres aqui funciona como um operador de lookahead.
  • Linha 4: i -> substring(lower(replace(ProductName, ' ', '')), i, 3) é uma função de ordem superior que opera em cada inteiro i na sequência gerada.

    • A função substring(...) extrai uma subcadeia de 3 caracteres da coluna ProductName.
    • Antes de extrair a subcadeia de caracteres, lower(replace(ProductName, ' ', '')) converte o ProductName em minúsculas e remove espaços para garantir a consistência.

A saída é uma lista de substrings de três caracteres de comprimento, extraídas dos nomes de produtos modificados, com base nas posições especificadas na sequência.

Filtrar os resultados filter-results

A função filter, com transformações de dados subsequentes, permite uma extração mais refinada e precisa de informações relevantes de dados de texto. Isso permite obter insights, melhorar a qualidade dos dados e facilitar melhores processos de tomada de decisão.

A função filter na instrução SQL a seguir serve para refinar e limitar a sequência de posições na cadeia de caracteres da qual as subsequências de caracteres são extraídas usando a função de transformação subsequente.

SELECT
  transform(
    filter(
      sequence(1, length(lower(replace(ProductName, ' ', ''))) - 6),
      i -> i + 6 <= length(lower(replace(ProductName, ' ', '')))
    ),
    i -> CASE WHEN length(substring(lower(replace(ProductName, ' ', '')), i, 7)) = 7
               THEN substring(lower(replace(ProductName, ' ', '')), i, 7)
               ELSE NULL
          END
  )
FROM
  featurevector1;

A função filter gera uma sequência de posições iniciais válidas dentro da ProductName modificada e extrai subsequências de um comprimento específico. Somente as posições iniciais que permitem a extração de uma subsequência de sete caracteres são permitidas.

A condição i -> i + 6 <= length(lower(replace(ProductName, ' ', ''))) garante que a posição inicial i mais 6 (o comprimento da subcadeia de sete caracteres desejada menos um) não exceda o comprimento da ProductName modificada.

A instrução CASE é usada para incluir ou excluir condicionalmente subsequências de caracteres com base em seu comprimento. Somente substrings de sete caracteres são incluídas; outras são substituídas por NULL. Essas subsequências de caracteres são usadas pela função transform para criar uma sequência de subsequências de caracteres a partir da coluna ProductName na tabela featurevector1.

TIP
Você pode usar o recurso modelos parametrizados para reutilizar e abstrair a lógica nas consultas. Por exemplo, ao criar funções de utilitário de uso geral (como a exibida acima para cadeias de caracteres de tokenização), você pode usar modelos parametrizados do Data Distiller em que o número de caracteres seria um parâmetro.

Calcular a junção cruzada de elementos únicos em dois vetores de recursos cross-join-unique-elements

Identificar as diferenças ou discrepâncias entre os dois conjuntos de dados com base em uma transformação específica dos dados é um processo comum para manter a precisão dos dados, melhorar a qualidade dos dados e garantir a consistência entre os conjuntos de dados.

Esta instrução SQL abaixo extrai os nomes de produtos exclusivos que estão presentes em featurevector2, mas não em featurevector1, após a aplicação das transformações.

SELECT lower(replace(ProductName, ' ', '')) FROM featurevector2
EXCEPT
SELECT lower(replace(ProductName, ' ', '')) FROM featurevector1;
TIP
Além do EXCEPT, você também pode usar o UNION e o INTERSECT, dependendo do seu caso de uso. Além disso, você pode experimentar as cláusulas ALL ou DISTINCT para ver a diferença entre incluir todos os valores e retornar apenas os valores únicos para as colunas especificadas.

Os resultados são mostrados na tabela abaixo:

Selecione para expandir
table 0-row-2 1-row-2 layout-auto
lower(replace(ProductName, ' ', ''))
1 macbookpro

Em seguida, execute uma junção cruzada para combinar elementos dos dois vetores de recursos para criar pares de elementos para comparação. A primeira etapa desse processo é criar um vetor tokenizado.

Um vetor tokenizado é uma representação estruturada de dados de texto em que cada palavra, frase ou unidade de significado (token) é convertida em um formato numérico. Essa conversão permite que algoritmos de processamento de linguagem natural entendam e analisem informações textuais.

O SQL abaixo cria um vetor tokenizado.

CREATE TABLE featurevector1tokenized AS SELECT
  DISTINCT(ProductName) AS featurevector1_distinct,
  transform(
    filter(
      sequence(1, length(lower(replace(ProductName, ' ', ''))) - 1),
      i -> i + 1 <= length(lower(replace(ProductName, ' ', '')))
    ),
    i -> CASE WHEN length(substring(lower(replace(ProductName, ' ', '')), i, 2)) = 2
               THEN substring(lower(replace(ProductName, ' ', '')), i, 2)
               ELSE NULL
          END
  ) AS tokens
FROM
  (SELECT lower(replace(ProductName, ' ', '')) AS ProductName FROM featurevector1);
SELECT * FROM featurevector1tokenized;
NOTE
Se você estiver usando o DbVisualizer, depois de criar ou excluir uma tabela, atualize a conexão de banco de dados para que o cache de metadados da tabela seja atualizado. O Data Distiller não envia atualizações de metadados.

Os resultados são mostrados na tabela abaixo:

Selecione para expandir
table 0-row-3 1-row-3 2-row-3 3-row-3 4-row-3 layout-auto
featurevetor1_distinct tokens
1 ipadmini {"ip","pa","ad","dm","mi","in","ni"}
2 ipad {"ip","pa","ad"}
3 iwatch {"iw","wa","at","tc","ch"}
4 iphone {"ip","ph","ho","on","ne"}

Em seguida, repita o processo para featurevector2:

CREATE TABLE featurevector2tokenized AS
SELECT
  DISTINCT(ProductName) AS featurevector2_distinct,
  transform(
    filter(
      sequence(1, length(lower(replace(ProductName, ' ', ''))) - 1),
      i -> i + 1 <= length(lower(replace(ProductName, ' ', '')))
    ),
    i -> CASE WHEN length(substring(lower(replace(ProductName, ' ', '')), i, 2)) = 2
               THEN substring(lower(replace(ProductName, ' ', '')), i, 2)
               ELSE NULL
          END
  ) AS tokens
FROM
(SELECT lower(replace(ProductName, ' ', '')) AS ProductName FROM featurevector2
);
SELECT * FROM featurevector2tokenized;

Os resultados são mostrados na tabela abaixo:

Selecione para expandir
table 0-row-3 1-row-3 2-row-3 3-row-3 layout-auto
featurevetor2_distinct tokens
1 ipadmini {"ip","pa","ad"}
2 macbookpro {"ma","ac","cb","bo","oo","ok","kp","pr","ro"}
3 iphone {"ip","ph","ho","on","ne"}

Com ambos os vetores tokenizados concluídos, agora é possível criar a associação cruzada. Isso é visto no SQL abaixo:

SELECT
    A.featurevector1_distinct AS SetA_ProductNames,
    B.featurevector2_distinct AS SetB_ProductNames,
    A.tokens AS SetA_tokens1,
    B.tokens AS SetB_tokens2
FROM
    featurevector1tokenized A
CROSS JOIN
    featurevector2tokenized B;

Veja a seguir um resumo do SQl usado para criar a junção cruzada:

  • Linha 2: A.featurevector1_distinct AS SetA_ProductNames seleciona a coluna featurevector1_distinct da tabela A e atribui a ela um alias SetA_ProductNames. Esta seção do SQL resulta em uma lista de nomes de produtos distintos do primeiro conjunto de dados.
  • Linha 4: A.tokens AS SetA_tokens1 seleciona a coluna tokens da tabela ou subconsulta A e atribui a ela um alias SetA_tokens1. Esta seção do SQL resulta em uma lista de valores tokenizados associados aos nomes de produtos do primeiro conjunto de dados.
  • Linha 8: a operação CROSS JOIN combina todas as combinações possíveis de linhas dos dois conjuntos de dados. Em outras palavras, ele emparelha cada nome de produto e seus tokens associados da primeira tabela (A) com cada nome de produto e seus tokens associados da segunda tabela (B). Isso resulta em um produto Cartesiano dos dois conjuntos de dados, em que cada linha na saída representa uma combinação de um nome de produto e seus tokens associados de ambos os conjuntos de dados.

Os resultados são mostrados na tabela abaixo:

Selecione para expandir
table 0-row-5 1-row-5 2-row-5 3-row-5 4-row-5 5-row-5 6-row-5 7-row-5 8-row-5 9-row-5 10-row-5 11-row-5 12-row-5 layout-auto
* SetA_ProductNames SetB_ProductNames SetA_tokens 1 SetB_tokens 2
1 ipadmini ipad {"ip","pa","ad","dm","mi","in","ni"} {"ip","pa","ad"}
2 ipadmini macbookpro {"ip","pa","ad","dm","mi","in","ni"} {"ma","ac","cb","bo","oo","ok","kp","pr","ro"}
3 ipadmini iphone {"ip","pa","ad","dm","mi","in","ni"} {"ip","ph","ho","on","ne"}
4 ipad ipad {"ip","pa","ad"} {"ip","pa","ad"}
5 ipad macbookpro {"ip","pa","ad"} {"ma","ac","cb","bo","oo","ok","kp","pr","ro"}
6 ipad iphone {"ip","pa","ad"} {"ip","ph","ho","on","ne"}
7 iwatch ipad {"iw","wa","at","tc","ch"} {"ip","pa","ad"}
8 iwatch macbookpro {"iw","wa","at","tc","ch"} {"ma","ac","cb","bo","oo","ok","kp","pr","ro"}
9 iwatch iphone {"iw","wa","at","tc","ch"} {"ip","ph","ho","on","ne"}
10 iphone ipad {"ip","ph","ho","on","ne"} {"ip","pa","ad"}
11 iphone macbookpro {"ip","ph","ho","on","ne"} {"ma","ac","cb","bo","oo","ok","kp","pr","ro"}
12 iphone iphone {"ip","ph","ho","on","ne"} {"ip","ph","ho","on","ne"}

Calcular a medida de similaridade de Jaccard compute-the-jaccard-similarity-measure

Em seguida, calcule usar o coeficiente de similaridade de Jaccard para executar uma análise de similaridade entre os dois conjuntos de nomes de produtos comparando suas representações tokenizadas. A saída do script SQL abaixo fornece o seguinte: nomes de produtos de ambos os conjuntos, suas representações tokenizadas, contagens de tokens únicos comuns e totais e o coeficiente de similaridade de Jaccard calculado para cada par de conjuntos de dados.

SELECT
    SetA_ProductNames,
    SetB_ProductNames,
    SetA_tokens1,
    SetB_tokens2,
    size(array_intersect(SetA_tokens1, SetB_tokens2)) AS token_intersect_count,
    size(array_union(SetA_tokens1, SetB_tokens2)) AS token_union_count,
    ROUND(
        CAST(size(array_intersect(SetA_tokens1, SetB_tokens2)) AS DOUBLE) /    size(array_union(SetA_tokens1, SetB_tokens2)), 2) AS jaccard_similarity
FROM
    (SELECT
        A.featurevector1_distinct AS SetA_ProductNames,
        B.featurevector2_distinct AS SetB_ProductNames,
        A.tokens AS SetA_tokens1,
        B.tokens AS SetB_tokens2
    FROM
        featurevector1tokenized A
    CROSS JOIN
        featurevector2tokenized B
    );

Veja a seguir um resumo do SQL usado para calcular o coeficiente de similaridade de Jaccard:

  • Linha 6: size(array_intersect(SetA_tokens1, SetB_tokens2)) AS token_intersect_count calcula o número de tokens comuns a SetA_tokens1 e SetB_tokens2. Esse cálculo é feito calculando o tamanho da interseção das duas matrizes de tokens.
  • Linha 7: size(array_union(SetA_tokens1, SetB_tokens2)) AS token_union_count calcula o número total de tokens únicos em SetA_tokens1 e SetB_tokens2. Essa linha calcula o tamanho da união das duas matrizes de tokens.
  • Linha 8-10: ROUND(CAST(size(array_intersect(SetA_tokens1, SetB_tokens2)) AS DOUBLE) / size(array_union(SetA_tokens1, SetB_tokens2)), 2) AS jaccard_similarity calcula a similaridade de Jaccard entre os conjuntos de tokens. Essas linhas dividem o tamanho da interseção do token pelo tamanho da união de tokens e arredondam o resultado para duas casas decimais. O resultado é um valor entre zero e um, onde um indica total similaridade.

Os resultados são mostrados na tabela abaixo:

Selecione para expandir
table 0-row-8 1-row-8 2-row-8 3-row-8 4-row-8 5-row-8 6-row-8 7-row-8 8-row-8 9-row-8 10-row-8 11-row-8 12-row-8 layout-auto
* SetA_ProductNames SetB_ProductNames SetA_tokens 1 SetB_tokens 2 token_intersect_count token_intersect_count Semelhança de Jaccard
1 ipadmini ipad {"ip","pa","ad","dm","mi","in","ni"} {"ip","pa","ad"} 3 7 0,43
2 ipadmini macbookpro {"ip","pa","ad","dm","mi","in","ni"} {"ma","ac","cb","bo","oo","ok","kp","pr","ro"} 0 16 0,0
3 ipadmini iphone {"ip","pa","ad","dm","mi","in","ni"} {"ip","ph","ho","on","ne"} 1 11 0,09
4 ipad ipad {"ip","pa","ad"} {"ip","pa","ad"} 3 3 1,0
5 ipad macbookpro {"ip","pa","ad"} {"ma","ac","cb","bo","oo","ok","kp","pr","ro"} 0 12 0,0
6 ipad iphone {"ip","pa","ad"} {"ip","ph","ho","on","ne"} 1 7 0,14
7 iwatch ipad {"iw","wa","at","tc","ch"} {"ip","pa","ad"} 0 8 0,0
8 iwatch macbookpro {"iw","wa","at","tc","ch"} {"ma","ac","cb","bo","oo","ok","kp","pr","ro"} 0 14 0,0
9 iwatch iphone {"iw","wa","at","tc","ch"} {"ip","ph","ho","on","ne"} 0 10 0,0
10 iphone ipad {"ip","ph","ho","on","ne"} {"ip","pa","ad"} 1 7 0,14
11 iphone macbookpro {"ip","ph","ho","on","ne"} {"ma","ac","cb","bo","oo","ok","kp","pr","ro"} 0 14 0,0
12 iphone iphone {"ip","ph","ho","on","ne"} {"ip","ph","ho","on","ne"} 5 5 1,0

Filtrar resultados com base no limite de Similaridade de Jacard similarity-threshold-filter

Por fim, filtre os resultados com base em um limite predefinido para selecionar apenas os pares que atendem aos critérios de similaridade. A instrução SQL abaixo filtra os produtos com um coeficiente de similaridade de Jaccard de pelo menos 0,4. Isso estreita os resultados para pares que exibem um grau substancial de similaridade.

SELECT
    SetA_ProductNames,
    SetB_ProductNames
FROM
(SELECT
    SetA_ProductNames,
    SetB_ProductNames,
    SetA_tokens1,
    SetB_tokens2,
    size(array_intersect(SetA_tokens1, SetB_tokens2)) AS token_intersect_count,
    size(array_union(SetA_tokens1, SetB_tokens2)) AS token_union_count,
    ROUND(
        CAST(size(array_intersect(SetA_tokens1, SetB_tokens2)) AS DOUBLE) / size(array_union(SetA_tokens1, SetB_tokens2)),
        2
    ) AS jaccard_similarity
FROM
    (SELECT
        A.featurevector1_distinct AS SetA_ProductNames,
        B.featurevector2_distinct AS SetB_ProductNames,
        A.tokens AS SetA_tokens1,
        B.tokens AS SetB_tokens2
    FROM
        featurevector1tokenized A
    CROSS JOIN
        featurevector2tokenized B
    )
)
WHERE jaccard_similarity>=0.4

Os resultados desta consulta fornecem as colunas para a junção de similaridade, conforme visto abaixo:

Selecione para expandir
table 0-row-3 1-row-3 2-row-3 3-row-3 layout-auto
SetA_ProductNames SetA_ProductNames
1 ipadmini ipad
2 ipad ipad
3 iphone iphone
accordion
:

Próximas etapas next-steps

Ao ler este documento, agora é possível usar essa lógica para realçar relações significativas ou sobreposições entre conjuntos de dados diferentes. A capacidade de identificar produtos de diferentes conjuntos de dados que têm uma semelhança significativa em suas características ou atributos tem várias aplicações reais. Essa lógica pode ser usada para cenários como:

  • Correspondência de produto: para agrupar ou recomendar produtos semelhantes aos clientes.
  • Limpeza de dados: para melhorar a qualidade dos dados.
  • Análise da cesta de compras: para fornecer informações sobre o comportamento do cliente, preferências e possíveis oportunidades de venda cruzada.

Caso ainda não o tenha feito, é recomendável ler a visão geral do pipeline de recursos de IA/ML. Use essa visão geral para saber como o Data Distiller e seu aprendizado de máquina preferido podem criar modelos de dados personalizados que apoiam seus casos de uso de marketing com dados de Experience Platform.

recommendation-more-help
ccf2b369-4031-483f-af63-a93b5ae5e3fb