să să Ce-ar fi dacă magazinul dvs. online ar ști ce dorește un client înainte de a-l face? Ce-ar fi dacă magazinul dvs. online ar ști ce dorește un client înainte de a-l face? sugerează elemente „populare” sau „similare” bazate pe date limitate, depășite. atunci când utilizatorii sunt noi (problema de pornire rece) și rareori se adaptează suficient de repede atunci când preferințele unui utilizator se schimbă în timp real. Most recommendation engines are like helpful but slightly clueless assistants: struggle Dar dacă sistemul dumneavoastră ar putea ca un merchandiser – combinând datele statice ale produsului și comportamentul utilizatorului în timp real la suprafață La momentul potrivit? De fapt, gândesc Articolele potrivite De fapt, gândesc Utilizarea , unul care depășește aceste deficiențe tradiționale, transformând datele în profiluri de utilizator acționabile, în evoluție, folosind o infrastructură nativă vectorială. This guide walks you through building a modern recommendation engine Superlinked (Vrei să sari direct la cod? Verificați codul open source pe GitHub aici. gata să încercați sistemele de recomandare pentru propriul dvs. caz de utilizare? Obțineți o demonstrație aici.) Aici Aici Aici Aici Puteți urmări, de asemenea, împreună cu tutorialul în browser cu Colabă . Răspunde dr: Majoritatea recomandatorilor de comerț electronic sunt fie prea statice (bazate pe reguli), fie prea cutii negre (modele ML opace). Superlinked oferă o cale de mijloc: recomandări flexibile, în timp real, care se pot adapta la utilizatorii cu start rece prin combinarea metadatelor cu comportamentul live - toate fără a re-antrenarea modelelor ML. Realizarea personalizării în ciuda provocărilor legate de încorporarea vectorului RecSys În timp ce integrările vectoriale pot îmbunătăți foarte mult sistemele de recomandare, implementarea lor eficientă necesită abordarea mai multor provocări, inclusiv: să să să să Calitate și relevanță: Procesul de generare încorporată, arhitectura și datele trebuie luate în considerare cu atenție. Date slabe și zgomotoase: Încorporările sunt mai puțin eficiente atunci când au intrări incomplete sau zgomotoase. Scalabilitate: Sunt necesare metode eficiente pentru seturi mari de date; în caz contrar, latența va fi o problemă. Superlinked vă permite să abordați aceste provocări combinând toate datele disponibile despre utilizatori și produse în vectori multimodali bogați. În exemplul nostru de comerț electronic RecSys de mai jos, facem acest lucru folosind următoarele elemente ale bibliotecii Superlinked: să să să să să min_max Număr de spații: pentru a înțelege recenziile clienților și informațiile despre prețuri text-similarity Spațiu: pentru înțelegerea semantică a informațiilor despre produs Schema evenimentelor și efectele pentru a modifica vectorii cântărirea timpului de interogare - pentru a defini modul în care doriți ca datele să fie tratate atunci când rulați interogarea, permițându-vă să optimizați și să scalați fără a reîncorpora întregul set de date (latență) Prin încorporarea datelor noastre inițial rare specifice utilizatorului (preferința inițială a produsului utilizatorului), putem face față problemei de pornire rece. - Personalizarea recomandărilor prin încorporarea acestor date de eveniment, crearea unei bucle de feedback care vă permite să actualizați vectorii cu preferințele utilizatorului în timp real. Hiper Let's get started! Construirea unui motor de recomandare a comerțului electronic cu Superlinked La începutul dezvoltării, avem următoarele : din product data să să să să să să Numărul de recenzii Evaluarea produselor Descrierea textului Denumirea produsului (care conține de obicei denumirea mărcii) Categorii De asemenea, avem următoarele : din data about users and products să să să fiecare utilizator alege unul dintre cele trei produse oferite atunci când se înregistrează (adică date despre preferințele produselor) comportamentul utilizatorului (după înregistrare) furnizează date suplimentare de eveniment - preferințe pentru caracteristicile textuale ale produselor (descriere, nume, categorie) De asemenea, economia clasică ne spune că, în medie, toți utilizatorii ceteris paribus preferă produse care: să să să să Costă mai puțin Avem multe recenzii Câștigă ratinguri mai mari Putem seta spațiile noastre pentru a lua în considerare aceste date, astfel încât RecSys funcționează în scenarii de start rece - recomandând elemente pentru utilizatorii despre care știm foarte puțin. odată ce RecSys este în funcțiune și funcționează, vom avea, de asemenea, date comportamentale: utilizatorii vor face clic pe anumite produse, vor cumpăra anumite produse etc. Putem captura și utiliza aceste date de eveniment pentru a crea fluxuri de feedback, pentru a actualiza vectorii noștri pentru a reflecta preferințele utilizatorilor și pentru a îmbunătăți calitatea recomandărilor. Crearea unui superlink În primul rând, trebuie să instalați biblioteca Superlinked și să importați clasele. %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) De asemenea, definim seturile noastre de date și creăm o constantă pentru stocarea celor mai bune 10 elemente - vezi în notebook. Celulă 3 Acum că bibliotecile au fost instalate, clasele importate și locațiile seturilor de date identificate, putem arunca o privire la setul nostru de date pentru a informa modul în care ne-am configurat spațiile. Inițial, avem date din înregistrarea utilizatorilor - adică care dintre cele trei produse user_1 și user_2 au ales. # 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 De asemenea, putem stabili o examinare atentă a datelor de distribuție ale produselor noastre - vezi Acest lucru vă oferă o imagine a numărului de produse care se află la diferite puncte de preț, au număruri diferite de recenzii și au evaluări diferite (inclusiv în cazul în care majoritatea produselor se află în aceste intervale). celulă 5 Prețurile pentru produse sunt în mare parte sub prețul de 1000 $. Este posibil să dorim să stabilim intervalul spațial la 25-1000 pentru a-l face reprezentativ, nedistorsionat de valorile exterioare. Cifrele de revizuire a produselor sunt distribuite în mod egal, iar ratingurile de revizuire sunt distribuite relativ uniform, astfel încât nu este necesară nicio tratament suplimentar. . . Celulele 7-9 Crearea indexului pentru căutarea vectorilor Biblioteca Superlinked conține un set de blocuri de bază pe care le folosim pentru a construi indexul și pentru a gestiona recuperarea. . . Aici Să punem blocurile de construcție ale acestei biblioteci pentru a fi utilizate în EComm RecSys. pentru a spune sistemului despre datele dvs. define your Schema # 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() Apoi, utilizați spații pentru a spune cum doriți să tratați fiecare parte a datelor atunci când încorporați. În definițiile spațiului, descriem cum să încorporați intrările astfel încât acestea să reflecte relațiile semantice din datele noastre. Fiecare spațiu este optimizat pentru a încorpora datele pentru a returna cea mai înaltă calitate posibilă a rezultatelor de recuperare. # 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]) Acum că aveți datele definite în spații, sunteți gata să vă jucați cu datele și să optimizați rezultatele. Soluția noastră de start rece. Ce se poate face fără evenimente Rezolvarea problemei de pornire la rece a RecSys Aici, definim o interogare de utilizator care caută numai cu vectorul preferințelor utilizatorului. 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() Rezultatele acestei interogări reflectă faptul că user_1 a ales o geantă atunci când s-a înregistrat pentru prima dată pe site-ul nostru ecomm. De asemenea, este posibil să recomandați produse utilizatorului_1 care sunt atractive - adică bazate pe prețul lor fiind scăzut, și având o mulțime de recenzii bune. rezultatele noastre vor reflecta acum atât alegerea produsului user_1 la înregistrare popularitatea generală a produselor. (Putem juca și cu aceste greutăți pentru a distorsiona rezultatele în direcția unui spațiu sau a altuia.) în general şi 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() Căutarea unui utilizator nou introduce textul interogării ca intrare pentru rezultatele recomandărilor noastre - a se vedea . . Celulă 20 În cazul nostru de exemplu, user_1 a căutat "pantofi pentru femei". ne putem optimiza rezultatele oferind (în ), pentru a recomanda mai multe produse „jachetele de îmbrăcăminte pentru femei”. additional weight to the category space category_weight = 10 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() Greutatea noastră suplimentară de categorie produce mai multe rezultate de îmbrăcăminte pentru femei. Putem, de asemenea, să împărtășim recomandările noastre pentru produsele de top ( Rezultatele reflectă acum preferința inițială a user_1 pentru genți și articole care sunt în general populare, în timp ce produsele cu evaluări scăzute sunt eliminate complet. . . review_rating_weight=5 Celulă 22 Utilizarea datelor despre evenimente pentru a crea experiențe personalizate Utilizatorii noștri au interacționat cu platforma noastră - user_1 mai mult, user_2 mai puțin. (a se vedea mai jos), reprezentate ca evenimente: behavioral data să să să un utilizator interesat de produse casual și de agrement (user_2) un utilizator interesat de produse elegante pentru excursii și ocazii formale de lucru (user_1) 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 Să cântărim acțiunile specifice pentru a înregistra nivelul de interes al utilizatorului pentru un anumit produs și să ajustăm setarea pentru a ține seama de evenimente atunci când efectuați recuperarea. 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() Acum creăm un nou index pentru a ține cont de evenimentele utilizatorilor și apoi personalizăm recomandările fiecărui utilizator în consecință. # 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")) ) Putem observa impactul încorporării evenimentelor în RecSys prin ponderarea personalizării sau Mai întâi, să vedem efectul (în comparație cu baza) de cântărire a spațiilor care sunt influențate de aceste (date comportamentale) evenimente. doar uşor greață # 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"]] Cu foarte puțină greutate pusă pe Spații afectate de evenimente, observăm o schimbare, dar în principal numai în a doua jumătate a top 10, în comparație cu rezultatele anterioare ("id_base", în dreapta). Dar dacă cântărim mai mult spațiile afectate de evenimente, vom înfățișa elemente complet noi în lista noastră de recomandări. # 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"]] De asemenea, putem, desigur, să folosim ponderile pentru a personaliza recomandările noastre pe baza comportamentului unui anumit utilizator (date despre evenimente) și De exemplu, prețul (a se vedea ) din prioritizează în același timp alte atribute ale produsului Celulă 31 Concluzie Implementarea eComm RecSys a bibliotecii Superlinked (de mai sus) vă arată cum să realizați puterea încorporărilor vectoriale prin încorporarea semnificației semantice a interogărilor utilizatorilor și a datelor comportamentale. Folosind spațiile noastre min_max de număr și text-similaritate, schema de evenimente și efecte și ponderile timpului de interogare, puteți aborda provocările de început rece, calitate și relevanță și scalabilitate ale RecSys și puteți oferi recomandări extrem de precise, personalizate de utilizator în producție. Acum e rândul tău! . . Încercați să implementați biblioteca Superlinked folosind notebook-ul nostru Try It Yourself – Get the Code & Demo! Încercați-l singur - Obțineți codul și demo-ul! să să să Prindeți codul: Verificați implementarea completă în repo-ul nostru GitHub aici.Fork-o, ajustați-o și faceți-o pe a voastră! Vezi în acțiune: Vrei să vezi acest lucru funcționând într-o setare reală? Rezervați o demonstrație rapidă și explorați cum Superlinked vă poate supraîncărca recomandările. Obțineți o demonstrație acum! Aici Aici . . Motoarele de recomandare modelează modul în care descoperim conținutul, fie că este vorba de pantaloni populari, muzică sau alte produse, – și acum aveți instrumentele pentru a vă construi propriul. vector search is the future