Hämta liknande poster med funktioner i högre ordning
Använd högordningsfunktionerna i Data Distiller för att lösa många vanliga användningsområden. Om du vill identifiera och hämta liknande eller relaterade poster från en eller flera datauppsättningar använder du filtret, omformningen och reducerar funktioner enligt den här handboken. Mer information om hur funktioner i högre ordning kan användas för att bearbeta komplexa datatyper finns i dokumentationen om hur du hanterar datatyper för arrayer och kartor.
Använd den här vägledningen när du vill identifiera produkter från olika datauppsättningar som har en betydande likhet i deras egenskaper eller attribut. Den här metoden ger lösningar för bland annat: borttagning av datadubbletter, postkoppling, rekommendationssystem, informationshämtning och textanalys.
Dokumentet beskriver processen att implementera en likhetskoppling, som sedan använder högre ordningsfunktioner i Data Distiller för att beräkna likheterna mellan datauppsättningar och filtrera dem baserat på valda attribut. SQL-kodfragment och förklaringar tillhandahålls för varje steg i processen. Arbetsflödet implementerar likhetskopplingar med Jaccards likhetsmått och tokenisering med Data Distiller funktioner i högre ordning. Dessa metoder används sedan för att identifiera och hämta liknande eller relaterade poster från en eller flera datauppsättningar baserade på ett likhetsmått. Nyckelavsnitten i processen är: tokenisering med funktioner i högre ordning, korskopplingen för unika element, likhetsberäkningen för kort och tröskelbaserad filtrering.
Förhandskrav
Innan du fortsätter med det här dokumentet bör du känna till följande koncept:
-
En likhetskoppling är en åtgärd som identifierar och hämtar postpar från en eller flera tabeller baserat på ett mått på likhetsgraden mellan posterna. De viktigaste kraven för likhetsförening är följande:
- Likhetsmått: Ett likhetstecken som sammanfogning är beroende av ett fördefinierat likhetsmått eller mått. Exempel på sådana mått är Jaccard-likheter, cosinus-likheter, redigeringsavstånd och så vidare. Mätvärdet beror på datatypen och användningsfallet. Detta mått anger hur likartade eller avvikande två poster är.
- Tröskelvärde: Ett tröskelvärde för likhet används för att avgöra när de två posterna anses vara tillräckligt lika för att inkluderas i kopplingsresultatet. Poster med en likhetspoäng över tröskelvärdet räknas som träffar.
-
Indexet Jaccard-likhet, eller Jaccard-likhetsmätningen, är en statistik som används för att mäta likheter och mångfald i samplingsuppsättningar. Den definieras som skärningspunktens storlek dividerad med storleken på den förening som provuppsättningarna har. Jaccards likhetsmätning varierar från noll till ett. En Jaccard-likhet på noll innebär att det inte finns någon likhet mellan uppsättningarna, och en Jaccard-likhet på ett innebär att uppsättningarna är identiska.
-
Funktioner med högre ordning i Data Distiller är dynamiska textbundna verktyg som bearbetar och omformar data direkt i SQL-satser. De här mångsidiga funktionerna eliminerar behovet av flera steg vid databearbetning, särskilt när hanterar komplexa typer som arrayer och kartor. Högre ordningsfunktioner bidrar till smidigare analys och bättre beslutsfattande i olika affärsscenarier genom att effektivisera frågeprocessen och förenkla omvandlingar.
Komma igång
Data Distiller SKU krävs för att utföra de högre ordningsfunktionerna på dina Adobe Experience Platform-data. Om du inte har Data Distiller SKU kontaktar du Adobe kundtjänstrepresentanten för mer information.
Fastställ likhet establish-similarity
Det här användningsfallet kräver ett likhetsmått mellan textsträngar som kan användas senare för att fastställa ett tröskelvärde för filtrering. I det här exemplet representerar produkterna i Set A och Set B orden i två dokument.
Jaccards likhetsmått kan användas på ett stort antal datatyper, inklusive textdata, kategoriserade data och binära data. Den är även lämplig för realtids- eller batchbearbetning eftersom den kan vara beräkningsmässigt effektiv att beräkna för stora datamängder.
Produktgrupp A och B innehåller testdata för det här arbetsflödet.
- Produktuppsättning A:
{iPhone, iPad, iWatch, iPad Mini}
- Produktuppsättning B:
{iPhone, iPad, Macbook Pro}
Om du vill beräkna Jaccard-likhet mellan produktuppsättningarna A och B ska du först hitta skärningspunkten (gemensamma element) för produktuppsättningarna. I det här fallet {iPhone, iPad}
. Leta sedan reda på union (alla unika element) för båda produktuppsättningarna. I det här exemplet {iPhone, iPad, iWatch, iPad Mini, Macbook Pro}
.
Slutligen använder du Jaccard-likhetsformeln: J(A,B) = A∪B / A∩B
för att beräkna likheten.
J = Kontantavstånd
A = uppsättning 1
B = uppsättning 2
Jaccards likhet mellan produktuppsättningarna A och B är 0,4. Detta visar på en viss grad av likhet mellan de ord som används i de två dokumenten. Denna likhet mellan de två uppsättningarna definierar kolumnerna i likhetskopplingen. Dessa kolumner representerar information, eller egenskaper som är kopplade till data, som lagras i en tabell och används för att utföra likhetsberäkningar.
Parvis Jaccard-beräkning med stränglikhet pairwise-similarity
Om likheterna mellan strängar ska jämföras på ett mer exakt sätt måste den parvisa likheten beräknas. Med parvis likhet delas högdimensionella objekt upp i mindre dimensionella objekt för jämförelse och analys. För att göra detta delas en textsträng upp i mindre delar eller enheter (tokens). Det kan vara enskilda bokstäver, grupper av bokstäver (som stavelser) eller hela ord. Likheten beräknas för varje par av tokens mellan varje element i Set A med varje element i Set B. Denna tokenisering utgör grunden för analytiska och beräkningsmässiga jämförelser, relationer och insikter som ska hämtas från data.
För den parvisa likhetsberäkningen används i det här exemplet teckenbit i gram (två teckenvariabler) för att jämföra en likhetsmatchning mellan textsträngarna för produkterna i Uppsättning A och Uppsättning B. Ett bigram är en sekvens av två objekt eller element i en given sekvens eller text. Du kan generalisera detta till n-gram.
I det här exemplet antas att fallet inte har någon betydelse och att blanksteg inte ska tas med i beräkningen. Enligt dessa kriterier har set A och Set B följande bigram:
Produktgrupp A bigram:
- 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"
Bigram för produktgrupp B:
- iPhone (5): "ip", "ph", "ho", "on", "ne"
- iPad (3): "ip", "pa", "ad"
- Macbook Pro (9): "Ma", "ac", "cb", "bo", "oo", "ok", "kp", "pr", "ro"
Beräkna sedan Jaccards likhetskoefficient för varje par:
Skapa testdata med SQL create-test-data
Om du vill skapa en testtabell manuellt för produktuppsättningarna använder du SQL CREATE TABLE-satsen.
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;
I följande beskrivningar finns en beskrivning av SQL-kodblocket ovan:
- Rad 1:
CREATE TEMP TABLE featurevector1 AS
: Den här programsatsen skapar en temporär tabell med namnetfeaturevector1
. Tillfälliga tabeller är vanligtvis bara tillgängliga i den aktuella sessionen och tas automatiskt bort i slutet av sessionen. - Rad 1 och 2:
SELECT * FROM (...)
: Den här delen av koden är en underfråga som används för att generera data som infogas i tabellenfeaturevector1
.
I underfrågan kombineras fleraSELECT
-satser med kommandotUNION ALL
. VarjeSELECT
-sats genererar en rad med data med de angivna värdena för kolumnenProductName
. - Rad 3:
SELECT 'iPad' AS ProductName
: Detta genererar en rad med värdetiPad
i kolumnenProductName
. - Rad 5:
SELECT 'iPhone'
: Detta genererar en rad med värdetiPhone
i kolumnenProductName
.
SQL-satsen skapar en tabell enligt nedan:
ProductName
Använd följande SQL-sats för att skapa den andra funktionsvektorn:
CREATE TABLE featurevector2 AS SELECT *
FROM (
SELECT 'iPad' AS ProductName
UNION ALL
SELECT 'iPhone'
UNION ALL
SELECT 'Macbook Pro'
);
SELECT * FROM featurevector2;
Dataomvandlingar data-transformation
I det här exemplet måste flera åtgärder utföras för att uppsättningarna ska kunna jämföras korrekt. För det första tas alla blanksteg bort från funktionsvektorerna eftersom det antas att de inte bidrar till likhetsmåttet. Alla dubbletter som finns i funktionsvektorn tas sedan bort eftersom de tar bort databearbetning. Därefter extraheras tokens med två tecken (bigram) från funktionsvektorerna. I det här exemplet antas de överlappa varandra.
Följande avsnitt visar de nödvändiga dataomvandlingarna som borttagning av dubbletter, borttagning av tomt utrymme och konvertering av gemener innan tokeniseringsprocessen startas.
Deduplicering deduplication
Använd sedan satsen DISTINCT
för att ta bort dubbletter. Det finns inga dubbletter i det här exemplet, men det är ett viktigt steg att förbättra exaktheten i alla jämförelser. Nödvändig SQL visas nedan:
SELECT DISTINCT(ProductName) AS featurevector1_distinct FROM featurevector1
SELECT DISTINCT(ProductName) AS featurevector2_distinct FROM featurevector2
Borttagning av tomt utrymme whitespace-removal
I följande SQL-sats tas blanktecken bort från funktionsvektorerna. replace(ProductName, ' ', '') AS featurevector1_nospaces
-delen av frågan tar ProductName
-kolumnen från tabellen featurevector1
och använder funktionen replace()
. Funktionen REPLACE
ersätter alla förekomster av ett blanksteg (' ') med en tom sträng (''). Detta tar effektivt bort alla blanksteg från värdena ProductName
. Resultatet har alias som featurevector1_nospaces
.
SELECT DISTINCT(ProductName) AS featurevector1_distinct, replace(ProductName, ' ', '') AS featurevector1_nospaces FROM featurevector1
Resultaten visas i tabellen nedan:
SQL-satsen och dess resultat för den andra funktionsvektorn visas nedan:
code language-sql |
---|
|
Resultatet visas enligt nedan:
table 0-row-3 1-row-3 2-row-3 3-row-3 layout-auto | ||
---|---|---|
featurevector2_distinkt | featurevector2_nospaces | |
1 | iPad | iPad |
2 | Macbook Pro | MacbookPro |
3 | iPhone | iPhone |
Konvertera till gemener lowercase-conversion
Därefter har SQL förbättrats så att produktnamnen konverteras till gemener och blanksteg tas bort. Den nedre funktionen (lower(...)
) används på resultatet av funktionen replace()
. Den nedre funktionen konverterar alla tecken i de ändrade ProductName
-värdena till gemener. Detta garanterar att värdena är i gemener oavsett ursprungligt skiftläge.
SELECT DISTINCT(ProductName) AS featurevector1_distinct, lower(replace(ProductName, ' ', '')) AS featurevector1_transform FROM featurevector1;
Resultatet av programsatsen är:
SQL-satsen och dess resultat för den andra funktionsvektorn visas nedan:
code language-sql |
---|
|
Resultatet visas enligt nedan:
table 0-row-3 1-row-3 2-row-3 3-row-3 layout-auto | ||
---|---|---|
featurevector2_distinkt | featurevector2_transform | |
1 | iPad | ipad |
2 | Macbook Pro | macbookpro |
3 | iPhone | iphone |
Extrahera variabler med SQL tokenization
Nästa steg är tokenisering eller textdelning. Tokenisering är processen att ta text och bryta ned den till individuella termer. Vanligtvis innebär detta att meningar delas upp i ord. I det här exemplet delas strängar upp i bigram (och i högre ordning n-gram) genom att tokens extraheras med SQL-funktioner som regexp_extract_all
. Överlappande bigram måste genereras för effektiv tokenisering.
SQL har förbättrats ytterligare för att använda regexp_extract_all
. regexp_extract_all(lower(replace(ProductName, ' ', '')), '.{2}', 0) AS tokens:
Den här delen av frågan bearbetar de ändrade ProductName
-värdena som skapades i föregående steg. Funktionen regexp_extract_all()
används för att extrahera alla icke-överlappande delsträngar från ett till två tecken från de ändrade och gemena ProductName
-värdena. Det reguljära uttrycket .{2}
matchar delsträngar med två tecken. regexp_extract_all(..., '.{2}', 0)
-delen av funktionen extraherar sedan alla matchande delsträngar från indatatexten.
SELECT DISTINCT(ProductName) AS featurevector1_distinct, lower(replace(ProductName, ' ', '')) AS featurevector1_transform,
regexp_extract_all(lower(replace(ProductName, ' ', '')) , '.{2}', 0) AS tokens
FROM featurevector1;
Resultaten visas i tabellen nedan:
table 0-row-4 1-row-4 2-row-4 3-row-4 4-row-4 layout-auto | |||
---|---|---|---|
featurevector1_distinkt | featurevector1_transform | variabler | |
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"} |
Om du vill förbättra precisionen ytterligare måste du använda SQL för att skapa överlappande tokens. Strängen "iPad" ovan saknar till exempel variabeln "pa". Åtgärda detta genom att ändra framåtblickande operator (med substring
) i ett steg och generera bigram.
På liknande sätt som i föregående steg extraherar regexp_extract_all(lower(replace(substring(ProductName, 2), ' ', '')), '.{2}', 0):
sekvenser med två tecken från det ändrade produktnamnet, men börjar från det andra tecknet med metoden substring
för att skapa överlappande tokens. I rad 3-7 (array_union(...) AS tokens
) kombinerar funktionen array_union()
arrayerna för sekvenser med två tecken som hämtas av de två reguljära uttrycksextraktionerna. Detta garanterar att resultatet innehåller unika variabler från både icke-överlappande och överlappande sekvenser.
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;
Resultaten visas i tabellen nedan:
table 0-row-4 1-row-4 2-row-4 3-row-4 4-row-4 layout-auto | |||
---|---|---|---|
featurevector1_distinkt | featurevector1_transform | variabler | |
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"} |
Användningen av substring
som lösning på problemet har dock begränsningar. Om du skapar tokens från texten baserat på tre gram (tre tecken) måste du använda två substrings
för att se framåt två gånger för att få de ändringar som krävs. Om du vill göra 10 gram behöver du nio substring
-uttryck. Detta skulle göra att koden blottar och blir ohållbar. Användning av reguljära uttryck är inte lämpligt. Det krävs en ny strategi.
Justera för längden på produktnamnet length-adjustment
SQl kan förbättras med sekvens- och längdfunktionerna. I följande exempel genererar sequence(1, length(lower(replace(ProductName, ' ', ''))) - 3)
en nummersekvens från ett till längden på det ändrade produktnamnet minus tre. Om det ändrade produktnamnet till exempel är"ipadmini" med teckenlängden åtta, genereras nummer från ett till fem (åtta-tre).
Programsatsen nedan extraherar unika produktnamn och delar sedan upp varje namn i teckensekvenser (tokens) med fyra teckenlängder, exklusive blanksteg, och visar dem som två kolumner. En kolumn visar de unika produktnamnen och den andra kolumnen visar deras genererade tokens.
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;
Resultaten visas i tabellen nedan:
table 0-row-3 1-row-3 2-row-3 3-row-3 4-row-3 layout-auto | ||
---|---|---|
featurevector1_distinkt | variabler | |
1 | iPad Mini | {"ipad","padm","admi","dmin","mini"} |
2 | iPad | {"ipad"} |
3 | iWatch | {"wat","watc","atch"} |
4 | iPhone | {"ipho","phon","hone"} |
Ange tokenlängd ensure-set-token-length
Ytterligare villkor kan läggas till i programsatsen för att säkerställa att de genererade sekvenserna har en viss längd. Följande SQL-sats utökas på tokengenereringslogiken genom att göra funktionen transform
mer komplex. Programsatsen använder funktionen filter
i transform
för att säkerställa att de genererade sekvenserna har en längd på sex tecken. Den hanterar fall där det inte är möjligt genom att tilldela NULL-värden till dessa positioner.
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;
Resultaten visas i tabellen nedan:
table 0-row-3 1-row-3 2-row-3 3-row-3 4-row-3 layout-auto | ||
---|---|---|
featurevector1_distinkt | variabler | |
1 | iPad Mini | {"ipadmi","padmin","admini"} |
2 | iPad | |
3 | iWatch | {"iwatch"} |
4 | iPhone | {"iphone"} |
Utforska lösningar med Data Distiller funktioner för högre ordning higher-order-function-solutions
Funktioner i högre ordning är kraftfulla konstruktioner som gör att du kan implementera"programmering" som syntax i Data Distiller. De kan användas för att iterera en funktion över flera värden i en array.
I Data Distiller är funktioner med högre ordning idealiska för att skapa n-gram och iterera över teckensekvenser.
Funktionen reduce
, särskilt när den används i sekvenser som genereras av transform
, erbjuder ett sätt att härleda kumulativa värden eller aggregat, som kan vara avgörande i olika analys- och planeringsprocesser.
I SQl-satsen nedan aggregerar funktionen reduce()
element i en array med hjälp av en anpassad aggregator. Den simulerar en for-slinga för att skapa de kumulativa summorna för alla heltal från ett till fem. 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;
Här följer en analys av SQL-satsen:
-
Rad 1:
transform
använder funktionenx -> reduce
för varje element som genereras i sekvensen. -
Rad 2:
sequence(1, 5)
genererar en nummersekvens från en till fem. -
Rad 3:
x -> reduce(sequence(1, x), 0, (acc, y) -> acc + y)
utför en reduceringsåtgärd för varje element x i sekvensen (från 1 till 5).- Funktionen
reduce
tar det inledande ackumulatorvärdet 0, en sekvens från ett till det aktuella värdet förx
och en funktion(acc, y) -> acc + y
med högre ordning för att lägga till talen. - Funktionen
acc + y
med högre ordning ackumulerar summan genom att lägga till det aktuella värdety
till ackumulatornacc
.
- Funktionen
-
Rad 8:
AS sum_result
byter namn på den resulterande kolumnen till sum_result.
Sammanfattningsvis tar den här funktionen för högre ordning två parametrar (acc
och y
) och definierar åtgärden som ska utföras, vilket i det här fallet lägger till y
till ackumulatorn acc
. Den här funktionen för högre ordning körs för varje element i sekvensen under reduceringsprocessen.
Utdata för den här programsatsen är en enda kolumn (sum_result
) som innehåller den kumulativa summan av tal från ett till fem.
Värdet för funktioner i högre ordning value-of-higher-order-functions
I det här avsnittet analyseras en nedbantad version av en SQL-sats på tre gram för att bättre förstå värdet på funktioner i högre ordning i Data Distiller och skapa n-gram mer effektivt.
Programsatsen nedan fungerar på kolumnen ProductName
i tabellen featurevector1
. Den skapar en uppsättning treteckendelsträngar som härleds från de ändrade produktnamnen i tabellen, med hjälp av positioner som hämtas från den sekvens som genereras.
SELECT
transform(
sequence(1, length(lower(replace(ProductName, ' ', ''))) - 2),
i -> substring(lower(replace(ProductName, ' ', '')), i, 3)
)
FROM
featurevector1
Här följer en analys av SQL-satsen:
-
Rad 2:
transform
använder en funktion med högre ordning för varje heltal i sekvensen. -
Rad 3:
sequence(1, length(lower(replace(ProductName, ' ', ''))) - 2)
genererar en sekvens med heltal från1
till längden på det ändrade produktnamnet minus två.length(lower(replace(ProductName, ' ', '')))
beräknar längden påProductName
efter att ha gjort den med gemener och tagit bort blanksteg.- 2
subtraherar två från längden för att säkerställa att sekvensen genererar giltiga startpositioner för delsträngar med tre tecken. Genom att subtrahera 2 ser du till att du har tillräckligt många tecken efter varje startposition för att kunna extrahera en delsträng med 3 tecken. Delsträngsfunktionen här fungerar som en lookahead-operator.
-
Rad 4:
i -> substring(lower(replace(ProductName, ' ', '')), i, 3)
är en funktion i högre ordning som fungerar på varje heltali
i den genererade sekvensen.- Funktionen
substring(...)
extraherar en delsträng med 3 tecken från kolumnenProductName
. - Innan du extraherar delsträngen konverterar
lower(replace(ProductName, ' ', ''))
ProductName
till gemener och tar bort blanksteg för att säkerställa konsekvens.
- Funktionen
Resultatet är en lista med delsträngar med tre tecken i längd, som extraheras från de ändrade produktnamnen, baserat på de positioner som anges i sekvensen.
Filtrera resultaten filter-results
Funktionen filter
, med efterföljande dataomformningar, ger en mer detaljerad extrahering av relevant information från textdata. På så sätt kan ni få insikter, förbättra datakvaliteten och underlätta bättre beslutsprocesser.
Funktionen filter
i följande SQL-sats används för att förfina och begränsa positionssekvensen i strängen som delsträngar extraheras från med den efterföljande omformningsfunktionen.
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;
Funktionen filter
genererar en sekvens med giltiga startpositioner inom den ändrade ProductName
och extraherar delsträngar med en viss längd. Endast startpositioner som tillåter extrahering av en delsträng med sju tecken tillåts.
Villkoret i -> i + 6 <= length(lower(replace(ProductName, ' ', '')))
säkerställer att startpositionen i
plus 6
(längden på den önskade delsträngen med sju tecken minus ett) inte överskrider längden på den ändrade ProductName
.
Programsatsen CASE
används för att villkorligt inkludera eller exkludera delsträngar baserat på deras längd. Endast delsträngar med sju tecken ingår, andra ersätts med NULL. Dessa delsträngar används sedan av funktionen transform
för att skapa en sekvens av delsträngar från kolumnen ProductName
i tabellen featurevector1
.
Beräkna korskopplingen mellan unika element i två funktionsvektorer cross-join-unique-elements
Att identifiera skillnader eller avvikelser mellan de två datauppsättningarna baserat på en specifik omvandling av data är en vanlig process för att bibehålla datakvaliteten, förbättra datakvaliteten och säkerställa konsekvens mellan datauppsättningarna.
Den här SQL-satsen nedan extraherar de unika produktnamn som finns i featurevector2
men inte i featurevector1
efter att omformningarna har tillämpats.
SELECT lower(replace(ProductName, ' ', '')) FROM featurevector2
EXCEPT
SELECT lower(replace(ProductName, ' ', '')) FROM featurevector1;
EXCEPT
kan du även använda UNION
och INTERSECT
beroende på ditt användningsfall. Du kan också experimentera med ALL
- eller DISTINCT
-satser för att se skillnaden mellan att ta med alla värden och bara returnera de unika värdena för de angivna kolumnerna.Resultaten visas i tabellen nedan:
table 0-row-2 1-row-2 layout-auto | |
---|---|
lower(replace(ProductName, ', '')) | |
1 | macbookpro |
Utför sedan en korskoppling för att kombinera element från de två funktionsvektorerna och skapa par av element för jämförelse. Det första steget i den här processen är att skapa en tokeniserad vektor.
En tokeniserad vektor är en strukturerad representation av textdata där varje ord, fras eller meningsenhet (token) konverteras till ett numeriskt format. Med den här konverteringen kan naturliga språkbearbetningsalgoritmer förstå och analysera textinformation.
SQl nedan skapar en tokeniserad vektor.
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;
Resultaten visas i tabellen nedan:
table 0-row-3 1-row-3 2-row-3 3-row-3 4-row-3 layout-auto | ||
---|---|---|
featurevector1_distinkt | variabler | |
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"} |
Upprepa sedan processen för 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;
Resultaten visas i tabellen nedan:
table 0-row-3 1-row-3 2-row-3 3-row-3 layout-auto | ||
---|---|---|
featurevector2_distinkt | variabler | |
1 | ipadmini | {"ip","pa","ad"} |
2 | macbookpro | {"ma","ac","cb","bo","oo","ok","kp","pr","ro"} |
3 | iphone | {"ip","ph","ho","on","ne"} |
När båda tokeniserade vektorerna är klara kan du nu skapa krysset. Detta visas i SQL nedan:
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;
Här följer en sammanfattning av SQl som används för att skapa krysset:
- Rad 2:
A.featurevector1_distinct AS SetA_ProductNames
markerar kolumnenfeaturevector1_distinct
i tabellenA
och tilldelar den ett aliasSetA_ProductNames
. Det här avsnittet av SQL resulterar i en lista med olika produktnamn från den första datauppsättningen. - Rad 4:
A.tokens AS SetA_tokens1
markerar kolumnentokens
från tabellen eller underfråganA
och tilldelar den ett aliasSetA_tokens1
. Det här avsnittet av SQL resulterar i en lista med tokeniserade värden som är associerade med produktnamnen från den första datauppsättningen. - Rad 8: Åtgärden
CROSS JOIN
kombinerar alla möjliga kombinationer av rader från de två datauppsättningarna. Med andra ord paras varje produktnamn och tillhörande tokens från den första tabellen (A
) med varje produktnamn och tillhörande tokens från den andra tabellen (B
). Detta resulterar i en kartesisk produkt av de två datauppsättningarna, där varje rad i utdata representerar en kombination av ett produktnamn och tillhörande tokens från båda datauppsättningarna.
Resultaten visas i tabellen nedan:
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 | AngeB_Produktnamn | 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"} |
Beräkna likhetsmåttet för Jaccard compute-the-jaccard-similarity-measure
Beräkna sedan med Jaccards likhetskoefficient för att utföra en likhetsanalys mellan de två uppsättningarna produktnamn genom att jämföra deras tokeniserade representationer. Utdata från SQL-skriptet nedan ger följande: produktnamn från båda uppsättningarna, deras tokeniserade representationer, antal gemensamma och totala unika tokens samt den beräknade Jaccard-likhetskoefficienten för varje par med datauppsättningar.
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
);
Nedan följer en sammanfattning av den SQL som används för att beräkna likhetskoefficienten för Jaccard:
- Rad 6:
size(array_intersect(SetA_tokens1, SetB_tokens2)) AS token_intersect_count
beräknar antalet token som är gemensamma för bådeSetA_tokens1
ochSetB_tokens2
. Beräkningen görs genom att storleken på skärningspunkten för de två tokenarrayerna beräknas. - Rad 7:
size(array_union(SetA_tokens1, SetB_tokens2)) AS token_union_count
beräknar det totala antalet unika token för bådeSetA_tokens1
ochSetB_tokens2
. Den här raden beräknar storleken på unionen av de två tokenarrayerna. - Rad 8-10:
ROUND(CAST(size(array_intersect(SetA_tokens1, SetB_tokens2)) AS DOUBLE) / size(array_union(SetA_tokens1, SetB_tokens2)), 2) AS jaccard_similarity
beräknar Jaccard-likheterna mellan tokenuppsättningarna. Dessa rader dividerar storleken på tokenöverlappningen med storleken på tokenunionen och avrundar resultatet till två decimaler. Resultatet är ett värde mellan noll och ett, där ett värde anger fullständig likhet.
Resultaten visas i tabellen nedan:
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 | AngeB_Produktnamn | SetA_tokens 1 | SetB_tokens 2 | token_intersect_count | token_intersect_count | Jaccard-likhet |
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 |
Filtrera resultat baserat på tröskelvärdet för jacard-likhet similarity-threshold-filter
Filtrera slutligen resultaten baserat på ett fördefinierat tröskelvärde för att endast markera de par som uppfyller likhetskriterierna. SQL-satsen nedan filtrerar produkterna med en Jaccard-likhetskoefficient på minst 0,4. Detta minskar resultaten till par som uppvisar en avsevärd grad av likhet.
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
Resultatet av den här frågan ger kolumnerna för likhetskopplingen enligt nedan:
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 |
---|
: |
Nästa steg next-stepsGenom att läsa det här dokumentet kan du nu använda den här logiken för att framhäva meningsfulla relationer eller överlappningar mellan olika datauppsättningar. Möjligheten att identifiera produkter från olika datauppsättningar som har en betydande likhet i egenskaper och attribut har många verkliga program. Den här logiken kan användas för scenarier som:
Om du inte redan har gjort det rekommenderar vi att du läser översikten över funktionen AI/ML. Använd den översikten för att lära dig hur Data Distiller och den maskininlärning du föredrar kan skapa anpassade datamodeller som stöder era marknadsföringsfall med data från Experience Platform. |