Frete dinâmico
Time IA Front
Otimização do frete
-
Frete depende do destino e da origem
-
Última barreira na decisão de compra
-
O custo varia muito
Difícil de otimizar
=
Problemas
Muitas variáveis
Baixa coesão
Alta dispersão
}
Restrições legais
Impedem a personaização
Inferência mais difícil
Abordagens
Classificação
Regressão
- Baixa coesão
- Desbalanceamento
- Modelo não injetivo
- Alta dispersão
- Coeficiente de Pearson ruim
- Sem semântica
Alternativa
Aprendizagem sem modelo
- Sem suposições sobre a função
- Baseado em comportamentos
- Baseado em aumentar a recompensa
- Aprende a imitar as decisões de negócio
Problemas
- Departamentos são grandes, e ids são pequenos
- Os Analistas não tem critérios para otimizar o frete
- O ciclo de treinamento no site seria muito lento
- Processar os dados no Stuart é muito custoso
- Não tínhamos estrutura para servir pipelines de IA complexos
- Não tínhamos estrutura para treinar pipelines de IA complexos
Resolvendo os problemas
Departamentos são grandes, e ids são pequenos
Clusters semânticos
- Particiona o hiperespaço
- Busca conversão similar
- Interpreta a percepção do cliente
- Cria semântica relacional para análises
Clusters semânticos
// Categóricos
visita.marca,
visita.departamento,
visita.linha,
// Numéricos
visita.preco,
visita.prazo,
// numéricos (localização)
cep_geocodes.latitude,
cep_geocodes.longitude,
- Busca a visão do usuário
- Usa campos ligados ao produto
- Usa coordenadas do usuário
- considera prazo e preço
Clusters semânticos
object VisitsClustering extends App {
val parsed = new BaseParser(args, Some("TreeFeatureClustering"))
implicit def spark: SparkSession = createSession(parsed.confs.get("sparkMaster"))
spark.setupS3
implicit def sparkContext: SparkContext = spark.sparkContext
(...)
val segmentModel =
VisitsClusterModelGenerator
.run(visitsByFilter(minData, maxData, filter, limit))
private val departamentos =
AthenaSource
.fieldValues[String]("departamento", minData, maxData, filter)
private val regioes =
AthenaSource
.fieldValues[String]("regiao", minData, maxData, filter)
TreeFeatureExperiment
.rules2Df(segmentModel, identificador)
.withColumn("ensaio", lit(essay))
.withColumn("filtro_inicial", lit(filter.getOrElse("")))
.withColumn("data_maxima", lit(maxData.getOrElse("")))
.withColumn("data_minima", lit(minData.getOrElse("")))
.withColumn("departamentos", typedLit(departamentos))
.withColumn("regioes", typedLit(regioes))
.write
.partitionBy("identificador", "ensaio", "profundidade")
.mode(SaveMode.Append)
.json(outputPath)
spark.close
- Escrito em Spark
- Adapta MLLib
Clusters semânticos
import org.apache.spark.sql.SparkSession
import com.b2w.ml.spark.athena._
val spark = SparkSession
.builder
.appName("Athena JDBC test")
.master("local[*]")
.getOrCreate
val stagingDir = "s3://bucket/athena-query-results"
val query =
"""
|SELECT data from my table LIMIT 10
""".stripMargin
val df1 = spark
.read
.athena(query, stagingDir)
Criamos o athena-spark-driver para conectar o spark ao Athena
Clusters semânticos
applications:
- name: clustering-bot
master: local[*]
deployMode: client
mainClass: com.b2w.iafront.clustering.jobs.VisitsClustering
appArgs: [
"-o", "s3a://ia-front-jobs-data/visits-clustering",
"-c", "minData=2019-10-01",
"-c", "maxData=2019-11-01",
"-c", "filtro=(departamento IN ('Fun Kitchen')) AND (estado IN ('MT', 'GO', 'MS', 'DF'))",
"-c", "identificador=Eletroportáteis Centro-Oeste 2019-10-01 ate 2019-11-01"
]
appResource: local:///startup.jar
confs:
spark.executor.memory: 1g
spark.executor.instances: "3"
spark.driver.host: sinfony
spark.kubernetes.container.image: gcr.io/master-sector-247616/ia-front/clustering:latest
spark.kubernetes.authenticate.driver.serviceAccountName: spark
spark.kubernetes.namespace: spark
Criamos o SparkSinfony, para orquestrar jobs spark no k8s
Clusters semânticos
Temos uma semântica simplificada para análise
Problemas
- Departamentos são grandes, e ids são pequenos
- Os Analistas não tem critérios para otimizar o frete
- O ciclo de treinamento no site seria muito lento
- Processar os dados no Stuart é muito custoso
- Não tínhamos estrutura para treinar pipelines de IA complexos
- Não tínhamos estrutura para servir pipelines de IA complexos
Os Analistas não tem critérios para otimizar o frete
Simulador de Monte Carlo
- Simula cenários iniciais a partir dos dados anteriores
- Busca o maior frete que afeta a conversão dentro de um limite
Simulador de Monte Carlo
Consiste em vários jobs spark com o objetivo de preparar dados de simulação e gerar gráficos para análise
Simulador de Monte Carlo
Gera gráficos das métricas de frete contra a receita média dos clusters
Simulador de Monte Carlo
Usa os centroides para determinar cenários iniciais de fretes possíveis
Simulador de Monte Carlo
Gera o relatório completo para análise da equipe de negócios
Problemas
- Departamentos são grandes, e ids são pequenos
- Os Analistas não tem critérios para otimizar o frete
- O ciclo de treinamento no site seria muito lento
- Processar os dados no Stuart é muito custoso
- Não tínhamos estrutura para treinar pipelines de IA complexos
- Não tínhamos estrutura para servir pipelines de IA complexos
O ciclo de treinamento no site seria muito lento
Modelo de sonho
- Aprende uma distribuição de probabilidade de conversão
- É um modelo de mistura de densidade
- Usado para simular o universo do site
Modelo de sonho
- Usado no modelo de reforço como parte do ambiente
- Escrito em tensorflow
class Mixture(PersistensedModel):
def __init__(self, layers_sizes: Sequence[int], components: int, learning_rate: float, name=None):
super().__init__(name=name)
self.layers_sizes = layers_sizes
self.components = components
self._setup_model(components)
self.learning_rate = learning_rate
self.optimizer = tf.keras.optimizers.Adam(learning_rate=learning_rate)
def _setup_model(self, components: int):
input_size = self.layers_sizes[-1]
with self.name_scope:
self.model: tf.keras.Sequential =\
tf.keras.Sequential([dense_layer(neurons,
activation=tf.nn.tanh,
initializer=tf.keras.initializers.GlorotNormal())
for neurons in self.layers_sizes],
name="dense_layers")
self.alfas = dense_layer(components, activation=tf.nn.softmax, name="alpha")
self.alfas.build([None, input_size])
self.mus = dense_layer(components, activation=tf.nn.sigmoid, name="mu")
self.mus.build([None, input_size])
self.sigmas = dense_layer(components, activation=nnelu, name="sigma")
self.sigmas.build([None, input_size])
Problemas
- Departamentos são grandes, e ids são pequenos
- Os Analistas não tem critérios para otimizar o frete
- O ciclo de treinamento no site seria muito lento
- Processar os dados no Stuart é muito custoso
- Não tínhamos estrutura para treinar pipelines de IA complexos
- Não tínhamos estrutura para servir pipelines de IA complexos
Sistema de reforço
- Ambiente encapsula o modelo de mistura
- recompensa baseada em métricas dos clusters
- Replica as ações tomadas pelo usuário
Sistema de reforço
Estado
métricas do cluster
recompensa
kpi baseado nas métricas do cluster
Ação
frete do cluster
Sistema de reforço
- Escrito em Tensorflow
- Usa o sonho para transfer learning
- Devolve como saída a recompensa média associada ao valor de frete
Sistema de reforço
Com base nos resultados, temos um valor de frete para o cluster
Arquitetura
frete.visitas
Clustering
Evil tree
Monte carlo
ETL + crawler no Glue que extrai visitas a partir de cálculos de frete
Job Spark que calcula regras de separação para entidades semânticas
Geram relatórios para a equipe de negócios decidir quais clusters serão utilizados e preços iniciais
Preparação de clusters
Tagger
freight bot mixture
freight bot reinforcement
Job que marca as visitas associadas a cada cluster posto em produção
Treina o modelo de sonho para usarmos no sistema de reforço
Reforço e dashboards
Treina o sistema de reforço com base nos sonhos e visitas do cluster
Dashboards
Relatórios no Stuart com as métricas de frete
Compilador de regras
freight bot inference
API de frete
Stuart
Compila as regras dos grupos em regras de inferência com frete
API que usa o resultado do compilador de regras para servir funções que inferem o frete de uma visita
Retroalimento o Stuart com os novos cálculos associados aos clusters e reinicia o processo
Inferência
Repassa para o bot quando cair na política dinâmic
Problemas
- Departamentos são grandes, e ids são pequenos
- Os Analistas não tem critérios para otimizar o frete
- O ciclo de treinamento no site seria muito lento
- Processar os dados no Stuart é muito custoso
- Não tínhamos estrutura para treinar pipelines de IA complexos
- Não tínhamos estrutura para servir pipelines de IA complexos
Infra de treino
Ferramentas criadas
- Driver Athena para Spark
- Orquestrador de Spark no k8s
- Reader Tensorflow+Python para resultados particionados (sem spark)
- Reader Tensorflow para Athena
- Imagens base para Spark
- Imagens base para Tensorflow (com e sem GPU)
- Runner de consultas Athena
- Runner kubeflow para Spark
Código aberto
Interno
Kubeflow + Gitlab
- Treinamos pipelines complexos facilmente
- Acompanhamos relatórios de treino para melhorias futuras
- Permite transferir a responsabilidade para o usuário
- Executamos jobs complexos que não podem executar no Glue
- Permite criar interfaces para o usuário analisar resultados
- Permite criar relatórios para o usuário
- Dá ao usuário a decisão de quando treinar o modelo, sem conhecimento de IA.
Desenvolvimento
Usuário
Resultados
- Treinamos pipelines complexos facilmente
- Acompanhamos relatórios de treino para melhorias futuras
- Permite transferir a responsabilidade para o usuário
- Executamos jobs complexos que não podem executar no Glue
- Permite criar interfaces para o usuário analisar resultados
- Permite criar relatórios para o usuário
- Dá ao usuário a decisão de quando treinar o modelo, sem conhecimento de IA.
Desenvolvimento
Usuário
Problemas
- Departamentos são grandes, e ids são pequenos
- Os Analistas não tem critérios para otimizar o frete
- O ciclo de treinamento no site seria muito lento
- Processar os dados no Stuart é muito custoso
- Não tínhamos estrutura para treinar pipelines de IA complexos
- Não tínhamos estrutura para servir pipelines de IA complexos
Resultados
Resultados
Resultados
Perguntas?
deck
By André Claudino
deck
- 157