dieWat as jou aanlynwinkel geweet het wat 'n kliënt wou hê voordat hulle gedoen het?
die
Wat as jou aanlynwinkel geweet het wat 'n kliënt wou hê voordat hulle gedoen het?
Most recommendation engines are like helpful but slightly clueless assistants:hulle voorstel “populêre” of “soortgelyk” items gebaseer op beperkte, verouderde data.strugglewanneer gebruikers nuut is (die koud-start probleem), en hulle pas selde vinnig genoeg aan wanneer 'n gebruiker se voorkeure in werklike tyd verander.
Maar wat as jou stelsel kanEintlik dinksoos 'n merchandiser - kombineer statische produkdata en real-time gebruikersgedrag na die oppervlakDie regte itemsOp die regte tyd?
Eintlik dink
This guide walks you through building a modern recommendation enginegebruikSuperlinked, een wat hierdie tradisionele tekortkominge oorkom deur jou data te verander in aksieerbare, ontwikkelende gebruikersprofiele met behulp van vektor-natiewe infrastruktuur.
(Wil jy reguit na die kode spring? kyk na die oop bron kode op GitHub hier. Klaar om te probeer aanbeveel stelsels vir jou eie gebruik geval? kry 'n demo hier.)
hierhierhierhier
Jy kan ook volg saam met die tutorial in-browser met onsdie kolab.
Die dr:
Die meeste e-handel aanbevelers is óf te statiese (reëlgebaseerde) óf te swart boks (opak ML-modelle). Superlinked bied 'n middelweg: buigsaam, real-time aanbevelings wat kan aanpas by koud-start gebruikers deur metadata te kombineer met lewendige gedrag - alles sonder om ML-modelle te heroplei.
Persoonlikheid te bereik ten spyte van RecSys-vektor embedding uitdagings
Terwyl vektor embeddings aansienlik aanbevelingstelsels kan verbeter, vereis die effektiewe implementering van hulle verskeie uitdagings, insluitend:
- die
- Kwaliteit en relevansie: Die embedding generasie proses, argitektuur en data moet versigtig oorweeg word. die
- Sparse en lawaaierige data: Embeddings is minder effektief wanneer hulle onvolledige of lawaaierige invoer het. die
- Skalbaarheid: Effektiewe metodes vir groot datasette is nodig; anders sal latensie 'n probleem wees. die
Superlinked kan jy hierdie uitdagings aanpak deur al die beskikbare data oor gebruikers en produkte te kombineer in ryk multimodale vektore.
- die
- min_max aantal spasies: vir die begrip van kliënt resensies en pryse inligting die
- teks-soortgelykheid Ruimte: vir semantiese begrip van produkinligting die
- Gebeurtenis skema en effekte om vektore te verander die
- query tyd gewigte - om te definieer hoe jy wil dat die data behandel word wanneer jy die query uitvoer, wat jou toelaat om te optimaliseer en te skaal sonder om die hele dataset weer in te voeg (latensie) die
Deur ons aanvanklik skaars gebruikers spesifieke data (die gebruiker se aanvanklike produkvoorkeure) te integreer, kan ons die koud-start-probleem hanteer.Hyper-Personalisering van aanbevelings deur hierdie gebeurtenis data in te voeg, skep 'n terugvoer loop wat jou toelaat om vektorne met gebruikersvoorkeure in werklike tyd te actualiseer.Daarbenewens, Superlinked se query tyd gewigte laat jou toelaat om jou vind resultate te verfijn, vooroordeel hulle aan spesifieke gebruikersvoorkeure te pas.
Let's get started!
Bouw 'n e-handel aanbevelingsmotor met Superlinked
Aan die begin van die ontwikkeling het ons die volgendeproduct data: die
- die
- Aantal beoordelaars die
- produk beoordelings die
- Tekstbeskrywing die
- Naam van die produk (gewoonlik bevat die handelsnaam) die
- kategorieë die
Ons het ook die volgendedata about users and products: die
- die
- elke gebruiker kies een van drie produkte wat aangebied word wanneer hulle registreer (dws produkvoorkeure data) die
- gebruikersgedrag (na registrasie) bied bykomende gebeurtenis data - voorkeure vir tekskenmerke van produkte (beskrywing, naam, kategorie) die
Ook, klassieke ekonomie vertel ons dat, gemiddeld, al die gebruikers ceteris paribus verkies produkte wat:
- die
- Dit kos minder die
- Jy het baie beoordelings die
- Het hoër ratings die
Ons kan ons Spaces opstel om hierdie data in ag te neem, sodat ons RecSys in koud-start-scenario's werk - items aanbeveel aan gebruikers waarvan ons baie min weet. Sodra ons RecSys oop is en hardloop, sal ons ook gedragsgegevens hê: gebruikers sal op sekere produkte klik, sekere produkte koop, ens. Ons kan hierdie gebeurtenisdata vang en gebruik om terugvoerloops te skep, ons vektore te actualiseer om gebruikersvoorkeure te weerspieël en die kwaliteit van aanbevelings te verbeter.
Opstel van 'n superlink
Eerstens moet ons die Superlinked-biblioteek installeer en die klasse importeer.
%pip install superlinked==6.0.0
import altair as alt
import os
import pandas as pd
import sys
from superlinked.framework.common.embedding.number_embedding import Mode
from superlinked.framework.common.schema.schema import schema
from superlinked.framework.common.schema.event_schema import event_schema
from superlinked.framework.common.schema.schema_object import String, Integer
from superlinked.framework.common.schema.schema_reference import SchemaReference
from superlinked.framework.common.schema.id_schema_object import IdField
from superlinked.framework.common.parser.dataframe_parser import DataFrameParser
from superlinked.framework.dsl.executor.in_memory.in_memory_executor import (
InMemoryExecutor,
InMemoryApp,
)
from superlinked.framework.dsl.index.index import Index
from superlinked.framework.dsl.index.effect import Effect
from superlinked.framework.dsl.query.param import Param
from superlinked.framework.dsl.query.query import Query
from superlinked.framework.dsl.source.in_memory_source import InMemorySource
from superlinked.framework.dsl.space.text_similarity_space import TextSimilaritySpace
from superlinked.framework.dsl.space.number_space import NumberSpace
alt.renderers.enable(get_altair_renderer())
pd.set_option("display.max_colwidth", 190)
Ons definieer ook ons dataset, en skep 'n konstante vir die stoor van die top 10 items - sienDie cel 3In die notasie.
Nou dat die biblioteek se geïnstalleerde, geïmporteerde klasse en datasetlokasies geïdentifiseer is, kan ons na ons dataset kyk om te informer hoe ons ons Spaces instel. Aanvanklik het ons data van gebruikersregistrasie - dit wil sê, watter van die drie produkte user_1 en user_2 gekies het.
# the user preferences come from the user being prompted to select a product out of 3 - those will be the initial preferences
# this is done in order to give somewhat personalised recommendations
user_df: pd.DataFrame = pd.read_json(USER_DATASET_URL)
user_df
Ons kan ook 'n noukeurige ondersoek van die verspreidingsdata van ons produkte opstel - sienSelfoon 5Dit gee jou 'n beeld van hoeveel produkte op verskillende pryspunte is, verskillende beoordelings het en verskillende ratings het (insluitend waar die meerderheid van produkte in hierdie reeks lê).
Die prysbakke vir produkte is meestal onder die $1000-pryspunt. Ons wil dalk die ruimtebereik op 25-1000 stel om dit representatief te maak, onverwrigbaar deur buitelandse waardes. Produkte se beoordelingsrekeninge word gelyktydig verdeel, en beoordelingsrekenings word relatief gelyktydig verdeel, sodat geen bykomende behandeling vereis word nie.Sorteer 7-9Die
Opbou van die indeks vir vektor soek
Superlinked se biblioteek bevat 'n stel kernboublokke wat ons gebruik om die indeks te bou en die opname te bestuur.hierDie
Laat ons die boublokke van hierdie biblioteek gebruik in ons EComm RecSys.define your SchemaOm die stelsel te vertel oor jou data.
# schema is the way to describe the input data flowing into our system - in a typed manner
@schema
class ProductSchema:
description: String
name: String
category: String
price: Integer
review_count: Integer
review_rating: Integer
id: IdField
@schema
class UserSchema:
preference_description: String
preference_name: String
preference_category: String
id: IdField
@event_schema
class EventSchema:
product: SchemaReference[ProductSchema]
user: SchemaReference[UserSchema]
event_type: String
id: IdField
# we instantiate schemas as follows
product = ProductSchema()
user = UserSchema()
event = EventSchema()
Vervolgens gebruik jy Spaces om te sê hoe jy elke deel van die data wil behandel wanneer jy insluit. In Spatiese definisies beskryf ons hoe om inputs te insluit sodat hulle die semantiese verhoudings in ons data weerspieël.
# textual inputs are embedded in a text similarity space powered by a sentence_transformers model
description_space = TextSimilaritySpace(
text=[user.preference_description, product.description],
model="sentence-transformers/all-distilroberta-v1",
)
name_space = TextSimilaritySpace(
text=[user.preference_name, product.name],
model="sentence-transformers/all-distilroberta-v1",
)
category_space = TextSimilaritySpace(
text=[user.preference_category, product.category],
model="sentence-transformers/all-distilroberta-v1",
)
# NumberSpaces encode numeric input in special ways to reflect a relationship
# here we express relationships to price (lower the better), or ratings and review counts (more/higher the better)
price_space = NumberSpace(
number=product.price, mode=Mode.MINIMUM, min_value=25, max_value=1000
)
review_count_space = NumberSpace(
number=product.review_count, mode=Mode.MAXIMUM, min_value=0, max_value=100
)
review_rating_space = NumberSpace(
number=product.review_rating, mode=Mode.MAXIMUM, min_value=0, max_value=4
)
# create the index using the defined spaces
product_index = Index(
spaces=[
description_space,
name_space,
category_space,
price_space,
review_count_space,
review_rating_space,
]
)
# parse our data into the schemas - not matching column names can be conformed to schemas using the mapping parameter
product_df_parser = DataFrameParser(schema=product)
user_df_parser = DataFrameParser(
schema=user, mapping={user.preference_description: "preference_desc"}
)
# setup our application
source_product: InMemorySource = InMemorySource(product, parser=product_df_parser)
source_user: InMemorySource = InMemorySource(user, parser=user_df_parser)
executor: InMemoryExecutor = InMemoryExecutor(
sources=[source_product, source_user], indices=[product_index]
)
app: InMemoryApp = executor.run()
# load the actual data into our system
source_product.put([products_df])
source_user.put([user_df])
Nou dat jy jou data in Spaces gedefinieer het, is jy gereed om met jou data te speel en die resultate te optimaliseer.Wat ons kan doen sonder gebeurtenisse- ons koud-start oplossing
Om die RecSys koud-start probleem te hanteer
Hier, ons definieer 'n gebruiker query wat soek met slegs die gebruiker se voorkeur vektor. Ons het konfigurasie beheer oor die belangrikheid (gewigte) van elke invoer tipe (Space).
user_query = (
Query(
product_index,
weights={
description_space: Param("description_weight"),
name_space: Param("name_weight"),
category_space: Param("category_weight"),
price_space: Param("price_weight"),
review_count_space: Param("review_count_weight"),
review_rating_space: Param("review_rating_weight"),
},
)
.find(product)
.with_vector(user, Param("user_id"))
.limit(Param("limit"))
)
# simple recommendations for our user_1
# these are based only on the initial product the user chose when first entering our site
simple_result = app.query(
user_query,
user_id="user_1",
description_weight=1,
name_weight=1,
category_weight=1,
price_weight=1,
review_count_weight=1,
review_rating_weight=1,
limit=TOP_N,
)
simple_result.to_pandas()
Die resultate van hierdie query weerspieël die feit dat user_1 'n handtas gekies het toe hulle vir die eerste keer op ons ecomm-webwerf geregistreer het.
Dit is ook moontlik om produkte aan te beveel aan gebruiker_1 watIn die algemeenaantreklik - dit is, gebaseer op hul prys is laag, en het 'n baie goeie resensies. ons resultate sal nou weerspieël beide user_1 se produk keuse by registrasieendie algemene gewildheid van produkte. (Ook kan ons met hierdie gewigte speel om resultate in die rigting van een ruimte of 'n ander te skeur.)
general_result = app.query(
user_query,
user_id="user_1",
description_weight=0,
name_weight=0,
category_weight=0,
price_weight=1,
review_count_weight=1,
review_rating_weight=1,
limit=TOP_N,
)
general_result.to_pandas()
'N Nuwe gebruiker se soektog stel query teks in as 'n invoer vir ons aanbevelingsresultate - sienDie cel 20Die
In ons voorbeeld geval het user_1 gesoek na "vrouenshoes". Ons kan ons resultate optimaliseer deur te geeadditional weight to the category space( diecategory_weight = 10
), aan te beveel meer "vroue klere rokke" produkte.
women_cat_result = app.query(
search_query,
user_id="user_1",
query_text="women clothing jackets",
description_weight=1,
name_weight=1,
category_weight=10,
price_weight=1,
review_count_weight=1,
review_rating_weight=1,
limit=TOP_N,
)
women_cat_result.to_pandas()
Ons bykomende kategorie gewig produseer meer vroue klere resultate.
Ons kan ook ons aanbevelings aan top-gewaardeerde produkte voorsien (review_rating_weight=5
Die resultate weerspieël nou die gebruiker_1 se aanvanklike voorkeur vir handtasse en items wat algemeen gewild is, terwyl produkte met lae ratings heeltemal verwyder word.Selfoon 22Die
Gebruik gebeurtenis data om persoonlike ervarings te skep
Ons gebruikers het interaksie met ons platform - user_1 meer, user_2 minder so.behavioral data(sien hieronder), verteenwoordig as gebeurtenisse:
- die
- 'n gebruiker wat belangstel in toevallige en ontspanningsprodukte (user_2) die
- 'n gebruiker wat belangstel in elegante produkte vir uitgaan en formele werksgeleenthede (user_1) die
events_df = (
pd.read_json(EVENT_DATASET_URL)
.reset_index()
.rename(columns={"index": "id"})
.head(NROWS)
)
events_df = events_df.merge(
products_df[["id"]], left_on="product", right_on="id", suffixes=("", "r")
).drop("idr", axis=1)
events_df = events_df.assign(created_at=1715439600)
events_df
Kom ons weeg spesifieke aksies om die gebruiker se vlak van belangstelling in 'n spesifieke produk te registreer, en pas die instelling aan om gebeurtenisse in ag te neem wanneer die opname uitgevoer word.
event_weights = {
"clicked_on": 0.2,
"buy": 1,
"put_to_cart": 0.5,
"removed_from_cart": -0.5,
}
# adjust the setup to events
product_index_with_events = Index(
spaces=[
description_space,
category_space,
name_space,
price_space,
review_count_space,
review_rating_space,
],
effects=[
Effect(
description_space,
event.user,
event_weight * event.product,
event.event_type == event_type,
)
for event_type, event_weight in event_weights.items()
]
+ [
Effect(
category_space,
event.user,
event_weight * event.product,
event.event_type == event_type,
)
for event_type, event_weight in event_weights.items()
]
+ [
Effect(
name_space,
event.user,
event_weight * event.product,
event.event_type == event_type,
)
for event_type, event_weight in event_weights.items()
],
)
event_df_parser: DataFrameParser = DataFrameParser(schema=event)
source_event: InMemorySource = InMemorySource(schema=event, parser=event_df_parser)
executor_with_events: InMemoryExecutor = InMemoryExecutor(
sources=[source_product, source_user, source_event],
indices=[product_index_with_events],
)
app_with_events: InMemoryApp = executor_with_events.run()
Nou skep ons 'n nuwe indeks om gebruikersgebeurtenisse in ag te neem, en persoonlike aanbevelings aan elke gebruiker dienovereenkomstig.
# for a new index, all data has to be put into the source again
source_product.put([products_df])
source_user.put([user_df])
source_event.put([events_df])
# a query only searching with the user's vector the preferences are now much more personalised thanks to the events
personalised_query = (
Query(
product_index_with_events,
weights={
description_space: Param("description_weight"),
category_space: Param("category_weight"),
name_space: Param("name_weight"),
price_space: Param("price_weight"),
review_count_space: Param("review_count_weight"),
review_rating_space: Param("review_rating_weight"),
},
)
.find(product)
.with_vector(user, Param("user_id"))
.limit(Param("limit"))
)
Ons kan die impak van die insluiting van gebeure in ons RecSys waarneem deur die gewig van personaliseringNet 'n bietjieofswaarEerstens, laat ons kyk na die effek (vergelyk aan die baseline) van die gewig van die ruimtes wat beïnvloed word deur hierdie (gedragsgegevens) gebeure.
# with small weight on event-affected spaces, we mainly just alter the results below position 4
general_event_result = app_with_events.query(
personalised_query,
user_id="user_1",
description_weight=1,
category_weight=1,
name_weight=1,
price_weight=1,
review_count_weight=1,
review_rating_weight=1,
limit=TOP_N,
)
general_event_result.to_pandas().join(
simple_result.to_pandas(), lsuffix="", rsuffix="_base"
)[["description", "id", "description_base", "id_base"]]
Met baie min gewig op Spaces wat deur gebeure beïnvloed word, sien ons 'n verandering, maar hoofsaaklik slegs in die laaste helfte van ons top 10, in vergelyking met die vorige resultate ("id_base", aan die regterkant).
Maar as ons die gebeurtenis-geaffekteerde ruimtes swaarder weeg, maak ons heeltemal nuwe items in ons aanbevelingslys.
# with larger weight on the the event-affected spaces, more totally new items appear in the TOP10
event_weighted_result = app_with_events.query(
personalised_query,
user_id="user_1",
query_text="",
description_weight=5,
category_weight=1,
name_weight=1,
price_weight=1,
review_count_weight=1,
review_rating_weight=1,
limit=TOP_N,
)
event_weighted_result.to_pandas().join(
simple_result.to_pandas(), lsuffix="", rsuffix="_base"
)[["description", "id", "description_base", "id_base"]]
Ons kan natuurlik ook gewigte gebruik om ons aanbevelings te persoonliker op grond van 'n spesifieke gebruikersgedrag (gebeurtenis data) enPrioriteer ander produk eienskappe- byvoorbeeld die prys (sienDie cel 31die
Konklusie
Die eComm RecSys implementasie van die Superlinked biblioteek (bo) wys jou hoe om die krag van vektor embeddings te realiseer deur die semantiese betekenis van gebruikersquêtes en gedragsgegevens te integreer. Met behulp van ons min_max nommer en teks-soortgelykheidspasies, gebeure skema en effekte, en query tyd gewigte, kan jy die koud-start, kwaliteit en relevansie, en skaalbaarheid uitdagings van RecSys aanpak en hoogs akkurate, gebruikers-geassosieerde aanbevelings in produksie bied.
Nou is dit jou beurt!Probeer die Superlinked-biblioteek self te implementeer met behulp van ons notisboekDie
Try It Yourself – Get the Code & Demo!
Probeer dit jouself - kry die Kode & Demo!- die
- Grab the Code: Kyk na die volledige implementering in ons GitHub-repo hier.Fork dit, tweak dit, en maak dit jou eie! die
- See It in Action: Wil jy dit in 'n werklike instelling sien werk? Boek 'n vinnige demo en verken hoe Superlinked jou aanbevelings kan oorlaai. die
Aanbevelingsmotors vorm die manier waarop ons inhoud ontdek. Of dit nou gewilde broek, musiek of ander produkte is,vector search is the future- en nou het jy die gereedskap om jou eie te bou.