Optimal prissättning för maximal vinst med Amazon SageMaker PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Optimal prissättning för maximal vinst med Amazon SageMaker

Detta är ett gästinlägg av Viktor Enrico Jeney, Senior Machine Learning Engineer på Adspert.

adspert är en Berlin-baserad ISV som utvecklat ett budhanteringsverktyg utformat för att automatiskt optimera prestandamarknadsföring och reklamkampanjer. Företagets kärnprincip är att automatisera vinstmaximering av e-handelsannonsering med hjälp av artificiell intelligens. Den kontinuerliga utvecklingen av annonsplattformar banar väg för nya möjligheter, som Adspert på ett sakkunnigt sätt utnyttjar för sina kunders framgång.

Adsperts primära mål är att förenkla processen för användarna och samtidigt optimera annonskampanjer över olika plattformar. Detta inkluderar användningen av information som samlats in över de olika plattformarna balanserad mot den optimala budgeten som ställts in på en nivå ovanför varje plattform. Adsperts fokus är att optimera en kunds måluppfyllelse, oavsett vilken plattform som används. Adspert fortsätter att lägga till plattformar efter behov för att ge våra kunder betydande fördelar.

I det här inlägget delar vi hur Adspert skapade prissättningsverktyget från grunden med hjälp av olika AWS-tjänster som Amazon SageMaker och hur Adspert samarbetade med AWS Data Lab att påskynda detta projekt från design till byggande på rekordtid.

Prissättningsverktyget ompriser en säljarvald produkt på en e-handelsmarknad baserat på synlighet och vinstmarginal för att maximera vinsten på produktnivå.

Som säljare är det viktigt att dina produkter alltid är synliga eftersom det kommer att öka försäljningen. Den viktigaste faktorn vid e-handelsförsäljning är helt enkelt om ditt erbjudande är synligt för kunderna istället för en konkurrents erbjudande.

Även om det säkert beror på den specifika e-handelsplattformen, har vi funnit att produktpriset är en av de viktigaste nyckeltalen som kan påverka synligheten. Men priserna ändras ofta och snabbt; av denna anledning måste prissättningsverktyget agera i nästan realtid för att öka synligheten.

Översikt över lösningen

Följande diagram illustrerar lösningsarkitekturen.

Lösningen innehåller följande komponenter:

  1. Amazon Relational Database Service (Amazon RDS) för PostgreSQL är huvudkällan till data, som innehåller produktinformation som lagras i en RDS för Postgres-databas.
  2. Information om produktförändringar anländer i realtid i en Amazon enkel kötjänst (Amazon SQS) kö.
  3. Produktinformation som lagras i Amazon RDS matas in i nästan realtid i rålagret med hjälp av ändringsdatainsamlingsmönstret (CDC) som finns i AWS Database Migration Service (AWS DMS).
  4. Produktlistningsmeddelanden som kommer från Amazon SQS tas in i nästan realtid i rålagret med hjälp av en AWS Lambda funktion.
  5. Den ursprungliga källdata lagras i Amazon enkel lagringstjänst (Amazon S3) rålagerhink med parkettdataformat. Detta lager är den enda källan till sanning för datasjön. Partitioneringen som används på denna lagring stöder inkrementell behandling av data.
  6. AWS-lim extrahera, transformera och ladda (ETL) jobb rensar produktdata, tar bort dubbletter och tillämpar datakonsolidering och generiska transformationer som inte är knutna till ett specifikt affärscase.
  7. Amazon S3-stegskiktet tar emot förberedd data som lagras i Apache Parkett-format för vidare bearbetning. Den partitionering som används i scenarkivet stöder den inkrementella bearbetningen av data.
  8. AWS Glue-jobben som skapas i det här lagret använder de data som är tillgängliga i Amazon S3-stegslagret. Detta inkluderar tillämpning av användningsfallsspecifika affärsregler och beräkningar som krävs. Resultatdata från dessa jobb lagras i Amazon S3-analysskiktet.
  9. Amazon S3-analysskiktet används för att lagra data som används av ML-modellerna för träningsändamål. Den partitionering som används i den kurerade butiken är baserad på den förväntade dataanvändningen. Detta kan skilja sig från den partitionering som används på scenlagret.
  10. Den återkommande ML-modellen är en Scikit-Learn Random Forest-implementering i SageMaker Script Mode, som tränas med hjälp av data tillgänglig i S3-bucket (analyslagret).
  11. Ett AWS Glue-databearbetningsjobb förbereder data för realtidsslutningen. Jobbet bearbetar data som tas in i S3-bucket (stagelager) och anropar SageMaker slutpunkten. Uppgifterna är förberedda för att användas av SageMakers prissättningsmodell. AWS Glue föredrogs framför Lambda, eftersom slutsatsen kräver olika komplexa databearbetningsoperationer som kopplingar och fönsterfunktioner på en stor datamängd (miljarder dagliga transaktioner). Resultatet från återprismodellens anrop lagras i S3-hinken (inferensskiktet).
  12. SageMaker-utbildningsjobbet distribueras med hjälp av en SageMaker-slutpunkt. Denna slutpunkt åberopas av AWS Glue-inferensprocessorn och genererar prisrekommendationer i nästan realtid för att öka produktens synlighet.
  13. Förutsägelserna som genereras av SageMaker-slutpunkten lagras i Amazon S3-inferensskiktet.
  14. Lambda-förutsägelseoptimeringsfunktionen bearbetar rekommendationerna som genereras av SageMaker slutpunkten och genererar en ny prisrekommendation som fokuserar på att maximera säljarens vinst, och tillämpar en avvägning mellan försäljningsvolym och försäljningsmarginal.
  15. Prisrekommendationerna som genereras av Lambdas förutsägelseoptimerare skickas till API:et för omprissättning, som uppdaterar produktpriset på marknadsplatsen.
  16. De uppdaterade prisrekommendationerna som genereras av Lambdas förutsägelseoptimerare lagras i Amazon S3-optimeringsskiktet.
  17. AWS Glue prediction loader-jobbet laddar om till RDS-källan för Postgres SQL-databasen de förutsägelser som genereras av ML-modellen för revisions- och rapporteringsändamål. AWS Glue Studio användes för att implementera denna komponent; det är ett grafiskt gränssnitt som gör det enkelt att skapa, köra och övervaka ETL-jobb i AWS Glue.

Dataförberedelse

Datauppsättningen för Adsperts synlighetsmodell skapas från en SQS-kö och matas in i det råa lagret av vår datasjö i realtid med Lambda. Efteråt saneras rådata genom att utföra enkla transformationer, som att ta bort dubbletter. Denna process är implementerad i AWS Glue. Resultatet lagras i iscensättningslagret i vår datasjö. Aviseringarna ger konkurrenterna för en viss produkt, med deras priser, uppfyllelsekanaler, leveranstider och många fler variabler. De tillhandahåller också ett plattformsberoende synlighetsmått, som kan uttryckas som en boolesk variabel (synlig eller ej). Vi får ett meddelande varje gång ett erbjudande ändras, vilket lägger till upp till flera miljoner händelser per månad över alla våra kunders produkter.

Från denna datauppsättning extraherar vi träningsdata enligt följande: för varje avisering parar vi de synliga erbjudandena med alla icke synliga erbjudanden, och vice versa. Varje datapunkt representerar en tävling mellan två säljare, där det finns en tydlig vinnare och förlorare. Detta bearbetningsjobb implementeras i ett AWS-limjobb med Spark. Den förberedda träningsdatauppsättningen skjuts till analytics S3-hinken för att användas av SageMaker.

Träna modellen

Vår modell klassificerar för varje par erbjudanden, om ett givet erbjudande kommer att synas. Denna modell gör det möjligt för oss att beräkna det bästa priset för våra kunder, öka synlighet baserat på konkurrens och maximera deras vinst. Utöver det kan denna klassificeringsmodell ge oss djupare insikter om orsakerna till att våra listor är synliga eller inte. Vi använder följande funktioner:

  • Förhållandet mellan vårt pris och konkurrenternas priser
  • Skillnad i uppfyllelsekanaler
  • Mängd feedback för varje säljare
  • Feedback betyg för varje säljare
  • Skillnad i minimileveranstider
  • Skillnad i maximala leveranstider
  • Tillgänglighet för varje säljares produkt

Adspert använder SageMaker för att träna och vara värd för modellen. Vi använder Scikit-Learn Random Forest-implementering i SageMaker skriptläge. Vi inkluderar också förbearbetning av vissa funktioner direkt i Scikit-Learn-pipelinen i utbildningsskriptet. Se följande kod:

import numpy as np

def transform_price(X):
    X = X.to_numpy()
    return np.log(
        X[:, 0] / np.nanmin([X[:, 1], X[:, 2]], axis=0),
    ).reshape(-1, 1)

def difference(X):
    X = X.to_numpy()
    return (X[:, 0] - X[:, 1]).reshape(-1, 1)

def fulfillment_difference(X):
    X = X.astype(int)
    return difference(X)

En av de viktigaste förbearbetningsfunktionerna är transform_price, som dividerar priset med minimivärdet av konkurrentpriset och en extern priskolumn. Vi har upptäckt att denna funktion har en relevant inverkan på modellens noggrannhet. Vi tillämpar även logaritmen för att låta modellen avgöra utifrån relativa prisskillnader, inte absoluta prisskillnader.

I training_script.py skript, definierar vi först hur man bygger Scikit-Learn ColumnTransformer för att tillämpa de angivna transformatorerna på kolumnerna i en dataram:

import argparse
import os
from io import StringIO

import joblib
import numpy as np
import pandas as pd
from custom_transformers import difference
from custom_transformers import fulfillment_difference
from custom_transformers import transform_price
from sklearn.compose import ColumnTransformer
from sklearn.ensemble import RandomForestClassifier
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import FunctionTransformer
from sklearn.preprocessing import OneHotEncoder

def make_preprocessor():
    return ColumnTransformer([
        ('price_by_smallest_cp', FunctionTransformer(transform_price),
         ['price', 'competitor_price', 'external_price']),
        (fulfillment_difference, FunctionTransformer(fulfillment_difference),
         ['fulfillment', 'competitor_'fulfillment']),
        ('feedback_count', 'passthrough',
         ['feedback_count', 'competitor_feedback_count']),
        ('feedback_rating', 'passthrough',
         ['feedback_rating', 'competitor_feedback_rating']),
        (
            'availability_type',
            OneHotEncoder(categories=[['NOW'], ['NOW']],
                          handle_unknown='ignore'),
            ['availability_type', 'competitor_availability_type'],
        ),
        ('min_shipping', FunctionTransformer(difference),
         ['minimum_shipping_hours', 'competitor_min_shipping_hours']),
        ('max_shipping', FunctionTransformer(difference),
         ['maximum_shipping_hours', 'competitor_max_shipping_hours']),
    ], remainder='drop')

I träningsskriptet laddar vi in ​​data från Parquet till en Pandas dataram, definierar pipelinen för ColumnTranformer och RandomForestClassifieroch träna modellen. Efteråt serialiseras modellen med hjälp av joblib:

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--output-data-dir', type=str,
                        default=os.environ['SM_OUTPUT_DATA_DIR'])
    parser.add_argument('--model-dir', type=str,
                        default=os.environ['SM_MODEL_DIR'])
    parser.add_argument('--train', type=str,
                        default=os.environ['SM_CHANNEL_TRAIN'])

    args = parser.parse_args()

    # load training data
    input_files = [os.path.join(args.train, file)
                   for file in os.listdir(args.train)]
    if len(input_files) == 0:
        raise ValueError
    raw_data = [pd.read_parquet(file) for file in input_files]
    train_data = pd.concat(raw_data)

    # split data set into x and y values
    train_y = train_data.loc[:, 'is_visible']

    if train_y.dtype != 'bool':
        raise ValueError(f'Label 'is_visible' has to be dtype bool but is'
                         f' {train_y.dtype}')

    train_X = train_data.drop('is_visible', axis=1)

    # fit the classifier pipeline and store the fitted model
    clf = Pipeline([
        ('preprocessor', make_preprocessor()),
        ('classifier', RandomForestClassifier(random_state=1)),
    ])
    clf.fit(train_X, train_y)
    joblib.dump(clf, os.path.join(args.model_dir, 'model.joblib'))

I träningsskriptet måste vi också implementera funktioner för slutledning:

  • input_fn – Är ansvarig för att tolka data från nyttolastens begärandekropp
  • modell_fn – Laddar och returnerar modellen som har dumpats i utbildningsdelen av skriptet
  • förutsäga_fn – Innehåller vår implementering för att begära en förutsägelse från modellen med hjälp av data från nyttolasten
  • predict_proba – För att rita predikterade siktkurvor returnerar vi klasssannolikheten med hjälp av predict_proba funktion, istället för klassificerarens binära förutsägelse

Se följande kod:

def input_fn(request_body, request_content_type):
    """Parse input data payload"""
    if request_content_type == 'text/csv':
        df = pd.read_csv(StringIO(request_body))
        return df
    else:
        raise ValueError(f'{request_content_type} not supported by script!')


def predict_fn(input_data, model):
    """Predict the visibilities"""
    classes = model.classes_

    if len(classes) != 2:
        raise ValueError('Model has more than 2 classes!')

    # get the index of the winning class
    class_index = np.where(model.classes_ == 1)[0][0]

    output = model.predict_proba(input_data)
    return output[:, class_index]


def model_fn(model_dir):
    """Deserialized and return fitted model

    Note that this should have the same name as the serialized model in the
    main method
    """
    clf = joblib.load(os.path.join(model_dir, 'model.joblib'))
    return clf

Följande figur visar de föroreningsbaserade egenskapernas betydelser som returneras av Random Forest Classifier.

Optimal prissättning för maximal vinst med Amazon SageMaker PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Med SageMaker kunde vi träna modellen på en stor mängd data (upp till 14 miljarder dagliga transaktioner) utan att belasta våra befintliga instanser eller behöva ställa in en separat maskin med tillräckligt med resurser. Dessutom, eftersom instanserna omedelbart stängs av efter träningsjobbet, var utbildning med SageMaker extremt kostnadseffektiv. Modellinstallationen med SageMaker fungerade utan någon extra arbetsbelastning. Ett enda funktionsanrop i Python SDK är tillräckligt för att vara värd för vår modell som en slutpunkt för slutledning, och det kan enkelt begäras från andra tjänster som också använder SageMaker Python SDK. Se följande kod:

from sagemaker.sklearn.estimator import SKLearn

FRAMEWORK_VERSION = "0.23-1"
script_path = 'training_script.py'
output_location = f's3://{bucket}/{folder}/output'
source_dir = 'source_dir'

sklearn = SKLearn(
    entry_point=script_path,
    source_dir=source_dir,
    framework_version=FRAMEWORK_VERSION,
    instance_type='ml.m5.large',
    role=role,
    sagemaker_session=sagemaker_session,
    output_path=output_location)

sklearn.fit({'train': training_path})

Modellartefakten lagras i Amazon S3 med passningsfunktionen. Som framgår av följande kod kan modellen laddas som en SKLearnModel objekt med hjälp av modellartefakten, skriptsökvägen och några andra parametrar. Efteråt kan den distribueras till önskad instanstyp och antal instanser.

model = sagemaker.sklearn.model.SKLearnModel(
    model_data=f'{output_location}/sagemaker-scikit-learn-2021-02-23-11-13-30-036/output/model.tar.gz',
    source_dir=source_dir,
    entry_point=script_path,
    framework_version=FRAMEWORK_VERSION,
    sagemaker_session=sagemaker_session,
    role=role
)
ENDPOINT_NAME = 'visibility-model-v1'
model.deploy(
    initial_instance_count=1,
    instance_type='ml.m5.large',
    endpoint_name=ENDPOINT_NAME
)

Utvärdera modellen i realtid

När en ny avisering skickas för en av våra produkter vill vi beräkna och skicka in det optimala priset. För att beräkna optimala priser skapar vi en förutsägelsedatauppsättning där vi jämför vårt eget erbjudande med varje konkurrents erbjudande för en rad möjliga priser. Dessa datapunkter skickas till SageMaker-slutpunkten, som returnerar den förutsagda sannolikheten att vara synlig mot varje konkurrent för varje givet pris. Vi kallar sannolikheten att vara synlig för förutspådd sikt. Resultatet kan visualiseras som en kurva för varje konkurrent, som visar förhållandet mellan vårt pris och synlighet, som visas i följande figur.

Optimal prissättning för maximal vinst med Amazon SageMaker PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

I det här exemplet är synligheten mot konkurrent 1 nästan en styckvis konstant funktion, vilket tyder på att vi främst måste sänka priset under en viss tröskel, ungefär konkurrentens pris, för att bli synliga. Däremot minskar inte sikten mot konkurrent 2 lika brant. Utöver det har vi fortfarande 50 % chans att synas även med ett mycket högt pris. Att analysera indata visade att konkurrenten har en låg mängd betyg, som råkar vara mycket dåliga. Vår modell lärde sig att denna specifika e-handelsplattform ger en nackdel för säljare med dåliga feedbackbetyg. Vi upptäckte liknande effekter för de andra funktionerna, som uppfyllnadskanal och leveranstider.

De nödvändiga datatransformationerna och slutsatserna mot SageMaker-slutpunkten implementeras i AWS Glue. AWS Glue-jobbet fungerar i mikrobatcher på realtidsdata som tas in från Lambda.

Slutligen vill vi beräkna den aggregerade siktkurvan, som är den förutsagda sikten för varje möjligt pris. Vårt erbjudande syns om det är bättre än alla andra säljares erbjudanden. Om man antar oberoende mellan sannolikheterna att vara synliga mot varje säljare givet vårt pris, är sannolikheten att vara synlig mot alla säljare produkten av respektive sannolikhet. Det betyder att den aggregerade siktkurvan kan beräknas genom att multiplicera alla kurvor.

Följande figurer visar de förutspådda synligheterna som returneras från SageMaker-slutpunkten.

Optimal prissättning för maximal vinst med Amazon SageMaker PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Följande figur visar den aggregerade siktkurvan.

Optimal prissättning för maximal vinst med Amazon SageMaker PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

För att beräkna det optimala priset jämnas först siktkurvan ut och multipliceras sedan med marginalen. För att beräkna marginalen använder vi varukostnaderna och avgifterna. Kostnaden för sålda varor och avgifter är den statiska produktinformationen som synkroniseras via AWS DMS. Utifrån vinstfunktionen beräknar Adspert det optimala priset och skickar in det till e-handelsplattformen genom plattformens API.

Detta är implementerat i AWS Lambda-prediktionsoptimerare.

Följande figur visar sambandet mellan förutspådd synlighet och pris.

Optimal prissättning för maximal vinst med Amazon SageMaker PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Följande figur visar förhållandet mellan pris och vinst.

Optimal prissättning för maximal vinst med Amazon SageMaker PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Slutsats

Adsperts befintliga syn på vinstmaximering är fokuserad på budhantering för att öka avkastningen från annonsering. För att uppnå överlägsen prestanda på e-handelsmarknader måste dock säljare överväga både reklam och konkurrenskraftiga priser på sina produkter. Med denna nya ML-modell för att förutsäga synlighet kan vi utöka vår funktionalitet till att även anpassa kundernas priser.

Det nya prissättningsverktyget måste kunna automatisera träning av ML-modellen på en stor mängd data, såväl som realtidsdatatransformationer, förutsägelser och prisoptimeringar. I det här inlägget gick vi igenom huvudstegen i vår prisoptimeringsmotor och AWS-arkitekturen som vi implementerade i samarbete med AWS Data Lab för att uppnå dessa mål.

Att ta ML-modeller från idé till produktion är vanligtvis komplext och tidskrävande. Du måste hantera stora mängder data för att träna modellen, välja den bästa algoritmen för att träna den, hantera beräkningskapaciteten medan du tränar den och sedan distribuera modellen i en produktionsmiljö. SageMaker minskade denna komplexitet genom att göra det mycket enklare att bygga och distribuera ML-modellen. Efter att vi valt rätt algoritmer och ramverk från det breda utbudet av tillgängliga val, hanterade SageMaker all underliggande infrastruktur för att träna vår modell och distribuera den till produktion.

Om du vill börja bekanta dig med SageMaker, Immersion Day workshop kan hjälpa dig att få en heltäckande förståelse för hur man bygger ML-användningsfall från funktionsteknik, de olika inbyggda algoritmerna och hur man tränar, ställer in och distribuerar ML-modellen i ett produktionsliknande scenario. Den vägleder dig att ta med din egen modell och utföra en lokal ML-arbetsbelastningslyft-och-skift till SageMaker-plattformen. Den demonstrerar ytterligare avancerade koncept som modellfelsökning, modellövervakning och AutoML, och hjälper dig att utvärdera din ML-arbetsbelastning genom AWS ML Well-Architected-objektivet.

Om du vill ha hjälp med att påskynda implementeringen av användningsfall som involverar data, analys, AI och ML, serverlös och containermodernisering, vänligen kontakta AWS Data Lab.


Om författarna

Optimal prissättning för maximal vinst med Amazon SageMaker PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.Viktor Enrico Jeney är en Senior Machine Learning Engineer på Adspert baserad i Berlin, Tyskland. Han skapar lösningar för prognos- och optimeringsproblem för att öka kundernas vinster. Viktor har en bakgrund inom tillämpad matematik och älskar att arbeta med data. På fritiden tycker han om att lära sig ungerska, träna kampsport och spela gitarr.

Optimal prissättning för maximal vinst med Amazon SageMaker PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.Ennio Pastore är en dataarkitekt i AWS Data Lab-teamet. Han är entusiast för allt som har att göra med ny teknik som har en positiv inverkan på företag och allmänt försörjning. Ennio har över 9 års erfarenhet av dataanalys. Han hjälper företag att definiera och implementera dataplattformar över branscher, såsom telekommunikation, bank, spel, detaljhandel och försäkring.

Tidsstämpel:

Mer från AWS maskininlärning