Шта ако ваша онлине продавница зна шта клијент жели пре него што то учине?
Шта ако ваша онлине продавница зна шта клијент жели пре него што то учине?
Most recommendation engines are like helpful but slightly clueless assistants:они предлажу „популарне“ или „сличне“ ставке на основу ограничених, застарелих података.struggleкада су корисници нови (проблем хладног почетка), и ретко се довољно брзо прилагођавају када се корисничке преференције мењају у реалном времену.
Али шта ако ваш систем можеЗаправо мислимкао трговац – комбинујући статичке податке о производу и понашање корисника у реалном времену на површинуPravi predmetiU pravo vreme?
Заправо мислим
This guide walks you through building a modern recommendation engineКоришћењеSuperlinked, један који превазилази ове традиционалне недостатке тако што претвара ваше податке у акциони, еволуирајуће корисничке профиле користећи векторску инфраструктуру.
(Желите да скочите директно на код? Погледајте отворени код на ГитХубу овде. спремни да испробате системе за препоручивање за сопствени случај употребе?
ovdeovdeovdeovde
Такође можете пратити заједно са туторијалом у претраживачу са нашимКолаб
Др ; др :
Већина препоручивача е-трговине су или превише статични (на основу правила) или превише црне кутије (нејасни МЛ модели). Суперлинкед нуди средњи пут: флексибилне, препоруке у реалном времену које се могу прилагодити корисницима хладног старта комбиновањем метаподатака са живом понашањем - све без преиспитивања МЛ модела.
Постизање персонализације упркос изазовима уграђивања рецСис вектора
Док векторска уграђења могу значајно побољшати системе препоруке, ефикасна имплементација захтева рјешавање неколико изазова, укључујући:
- Квалитет и релевантност: Процес уграђивања генерације, архитектура и подаци морају се пажљиво размотрити.
- Спарсе и бучни подаци: Уграђивања су мање ефикасна када имају непотпуни или бучни улаз.
- Скалабилност: Потребне су ефикасне методе за велике сетове података; у супротном, латенција ће бити проблем.
Superlinked vam omogućava da rešite ove izazove tako što ćete kombinovati sve dostupne podatke o korisnicima i proizvodima u bogate multimodalne vektore.U našem primeru e-trgovine RecSys ispod, mi to radimo pomoću sledećih elemenata Superlinked biblioteke:
- min_max Бројне просторе: за разумевање рецензија купаца и информација о ценама
- текст-сличност Простор: за семантичко разумевање информација о производу
- Схема догађаја и ефекти за модификацију вектора
- Временске тежине упита - да дефинишете како желите да се подаци обрађују када покренете упит, омогућавајући вам да оптимизујете и скалирате без поновног уграђивања целог скупа података (латенција)
Уграђујући наше у почетку ретке податке специфичне за кориснике (почетне преференције производа корисника), можемо се носити са проблемом хладног старта.Хипер- персонализовање препорука тако што ћете уградити ове податке о догађају, стварајући петљу за повратне информације која вам омогућава да ажурирате векторе са корисничким преференцијама у реалном времену.Поред тога, Суперлинкед-ове временске тежине упита омогућавају вам да фино прилагодите резултате претраживања, прилагођавајући их да одговарају специфичним корисничким преференцијама.
Let's get started!
Изградња мотора за препоруку е-трговине са Суперлинкед-ом
Na početku razvoja imamo sledećeproduct data• :
- Број рецензента
- Рејтинг производа
- Текстски опис
- Назив производа (обично садржи бренд)
- Категорије
Takođe imamo sledećedata about users and products• :
- сваки корисник бира један од три понуђене производа приликом регистрације (тј. подаци о преференцијама производа)
- корисничко понашање (након регистрације) пружа додатне податке о догађају - преференције за текстуалне карактеристике производа (опис, име, категорија)
Такође, класична економија нам каже да, у просеку, сви корисници цетерис парибус преферирају производе који:
- Manje košta
- Ima mnogo recenzija
- Imaju veće ocene
Možemo da podesimo naše prostorije tako da uzmu u obzir ove podatke, tako da naši RecSys funkcionišu u scenarijima hladnog početka - preporučujući stavke korisnicima o kojima znamo veoma malo.Kada se naš RecSys pokrene i pokrene, takođe ćemo imati podatke o ponašanju: korisnici će kliknuti na određene proizvode, kupiti određene proizvode, itd. Možemo da uhvatimo i koristimo ove podatke o događaju da bismo kreirali povratne informacije, ažurirali naše vektore kako bismo odražavali preferencije korisnika i poboljšali kvalitet preporuka.
Постављање суперлинкова
Прво, морамо да инсталирамо Суперлинкед библиотеку и увеземо класе.
%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)
Такође дефинишемо наше скупове података и створимо константу за складиштење првих 10 ставки - видићелије 3U beležnici
Сада када су инсталиране библиотеке, увезене класе и локације сета података идентификоване, можемо погледати наш сет података како бисмо информисали како смо подесили наше просторе. У почетку, имамо податке из регистрације корисника - тј. који је од три производа user_1 и user_2 изабрао.
# 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
Такође можемо поставити детаљан преглед података о дистрибуцији наших производа - видићелије 5Ово вам даје слику о томе колико су производи на различитим ценама, имају различите бројеве прегледа и имају различите оцене (укључујући и где већина производа лежи у овим опсеговима).
Cene za proizvode su uglavnom ispod cene od 1000 dolara. Možda bismo želeli da postavimo raspon prostora na 25-1000 da bi bio reprezentativan, a da ne bude iskrivljen vanjskim vrednostima. Broj pregleda proizvoda je ravnomerno raspodeljen, a ocene pregleda su relativno ravnomerno raspodeljene, tako da nema potrebe za dodatnim tretmanom.Књиге 7-9. .
Изградња индекса за претрагу вектора
Библиотека Суперлинкед-а садржи скуп основних грађевинских блокова које користимо за изградњу индекса и управљање претрагом.ovde. .
Хајде да ставимо грађевинске блокове ове библиотеке за употребу у нашем ЕЦомм РецСис.define your Schemada kažete sistemu o vašim podacima.
# 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()
Затим користите Простране да бисте рекли како желите да третирате сваки део података приликом уграђивања. У Пространим дефиницијама описујемо како да уградите уносе тако да одражавају семантичке односе у нашим подацима. Сваки Пространи је оптимизован да угради податке како би вратио највиши могући квалитет резултата претраживања. Који Пространи се користе зависи од вашег типа података.
# 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])
Сада када имате своје податке дефинисане у просторима, спремни сте да се играте са својим подацима и оптимизујете резултате.Шта можемо учинити без догађаја- наше хладно-старт решење
Решавање проблема РеЦСИс хладног старта
Овде дефинишемо кориснички упит који претражује само вектор преференција корисника.Имамо контролу конфигурације над важношћу (тежинама) сваког типа уноса (простор).
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()
Резултати овог упита одражавају чињеницу да је user_1 изабрао торбу када се први пут регистровао на нашем сајту ecomm.
Такође је могуће препоручити производе кориснику_1 који суГенералнопривлачан - то јест, на основу њихове ниске цене и са пуно добрих рецензија. Наши резултати ће сада одражавати и избор производа корисника_1 при регистрацијииОпшта популарност производа. (Такође можемо играти са овим теговима да искривимо резултате у правцу једног простора или другог.)
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()
Претрага новог корисника уводи текст упита као унос за наше резултате препоруке - погледајтећелије 20. .
U našem primeru, user_1 je pretraživao po rečima "ženska odeća".Možemo da optimizujemo naše rezultate dajućiadditional 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()
Наша додатна категорија тежине производи више резултата женске одеће.
Такође можемо да подијелимо наше препоруке на најбоље оцењене производе (review_rating_weight=5
Резултати сада одражавају почетну преференцију корисника_1 за торбе и предмете који су генерално популарни, док се производи са ниским оценама у потпуности уклањају.Ћелија 22. .
Korišćenje podataka o događajima za kreiranje personalizovanih iskustava
Брзо напред месец дана. Наши корисници су комуницирали са нашом платформом - user_1 више, user_2 мање.behavioral data(погледајте испод), представљен као догађаји:
- корисник заинтересован за случајне и рекреативне производе (user_2)
- корисник заинтересован за елегантне производе за излазак и формалне радне прилике (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
Хајде да проценимо специфичне акције за регистрацију нивоа интересовања корисника за одређени производ и прилагодимо подешавање да би се узели у обзир догађаји приликом извођења претраге.
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()
Сада креирамо нови индекс који узима у обзир догађаје корисника, а затим персонализујемо препоруке сваком кориснику у складу с тим.
# 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"))
)
Можемо посматрати утицај укључивања догађаја у наше РецСис тежином персонализацијеsamo maloилиТешкоПрво, хајде да видимо ефекат (у поређењу са излазном линијом) тежине простора који су под утицајем ових (понашања података) догађаја.
# 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"]]
Са врло малом тежином која се ставља на Простор који утиче на догађаје, примећујемо промену, али углавном само у другој половини наше топ 10 у поређењу са претходним резултатима ("ид_басе", на десној страни).
Али ако тежимо просторе погођене догађајима теже, на листи препорука наносимо потпуно нове ставке.
# 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"]]
Такође, наравно, можемо користити тегове за персонализацију наших препорука на основу понашања одређеног корисника (подаци о догађајима) иистовремено даје приоритет другим атрибутима производаНа пример, цена (погледајтећелије 31)
Закључак
Implementacija eComm RecSys Superlinked biblioteke (iznad) pokazuje vam kako da ostvarite moć vektorskih ugrađivanja tako što ćete integrisati semantičko značenje korisničkih upita i podataka o ponašanju. Koristeći naše min_max brojeve i tekstovne sličnosti, sheme događaja i efekte, kao i vremenske težine upita, možete da rešite izazove hladnog početka, kvaliteta i relevantnosti i skalabilnosti RecSys-a i da pružite veoma precizne, korisnicima prilagođene preporuke u proizvodnji.
Сада је твој ред!Покушајте сами да имплементирате Суперлинкед библиотеку користећи наш нотебоок. .
Try It Yourself – Get the Code & Demo!
Покушајте сами - добити код и демо!- Ухватите код: Погледајте пуну имплементацију у нашем ГитХуб репо-у овде.Форк га, подесите га и направите га својим!
- Гледајте га у акцији: Желите да видите да ово ради у реалном свету? резервишите брзу демо и истражите како Суперлинкед може преоптеретити ваше препоруке.
Мотори за препоруке обликују начин на који откривамо садржај, било да се ради о популарним панталонама, музици или другим производима,vector search is the future— и сада имате алате за изградњу своје.