Alura > Cursos de Dados > Cursos de Engenharias e Arquiteturas de Dados > Conteúdos de Engenharias e Arquiteturas de Dados > Primeiras aulas do curso Feature Store: criação, materialização e serving com Feast

Feature Store: criação, materialização e serving com Feast

Por que precisamos de uma Feature Store? - Apresentação

Apresentando o curso e objetivos

Olá! Seja bem-vinde ao curso de Feature Store (repositório de atributos) da Alura. Meu nome é Fabrício Zillig e serei a pessoa instrutora ao longo do curso.

Audiodescrição: Eu sou um homem branco, de cabelo preto curto e barba curta. Visto uma camiseta cinza. Atrás de mim há uma parede com uma prateleira com alguns itens e iluminação, além de uma parede branca.

Neste curso, vamos entender o que é uma Feature Store (repositório de atributos), como utilizá-la e quais problemas ela resolve no dia a dia de uma pessoa engenheira de Machine Learning (aprendizado de máquina).

Vamos aprender a calcular e registrar as features (atributos) utilizando uma Feature Store (repositório de atributos), a recuperá-las para treinar modelos de Machine Learning (aprendizado de máquina), a recuperá-las para realizar previsões utilizando modelos já treinados, a atualizar informações já cadastradas no ambiente e, por fim, a utilizá-las expondo os dados por meio de uma API (interface de programação de aplicações).

Apresentando o projeto prático

Ao longo do curso, vamos trabalhar em um projeto de aplicativo T-Libre com uma premissa simples. As pessoas usuárias fazem pedidos, e nosso sistema precisa identificar a probabilidade de esse pedido atrasar e, caso ultrapasse um limiar, nosso aplicativo informará que o pedido pode atrasar.

O foco aqui não é o modelo em si, e sim como as features são criadas, gerenciadas e disponibilizadas tanto para o treinamento quanto para a inferência desse modelo.

Espero você nas próximas aulas.

Por que precisamos de uma Feature Store? - Por que precisamos de uma feature store?

Configurando o ambiente e iniciando o jupyter lab

Vamos começar. Você já deve ter criado no ambiente uma pasta semelhante a esta, na qual teremos a pasta "data", onde estão os dados que utilizaremos durante o curso para desenvolver o projeto, e a pasta "notebooks", que inicialmente estará vazia. Ao longo do curso, criaremos notebooks para utilizar conforme avançarmos.

No terminal, dentro dessa pasta, depois de executar o comando uv sync (por exemplo) para instalar todas as bibliotecas,
Para instalar as dependências, execute o comando abaixo:

uv sync

podemos executar uv run jupyter lab.
Em seguida, para iniciar o JupyterLab, rode:

uv run jupyter lab

Isso inicializa o servidor do JupyterLab e podemos abri-lo no navegador clicando no link exibido.

Ao abrir o JupyterLab, visualizamos o ambiente e as pastas. Temos os dados de pedidos e a pasta "notebooks". Já há um primeiro notebook com o qual vamos trabalhar nesta primeira aula, mas também podemos clicar em Novo e escolher Python 3 para criar um novo Jupyter Notebook. Para facilitar, utilizaremos o que já está disponível. Vamos pressionar F11 para melhorar a visualização.

Compreendendo features e uso do modelo

A primeira etapa para entendermos o que é uma feature store (repositório de características) e qual é sua utilidade é compreender o que é uma feature (característica). Em um processo, um pipeline (fluxo de processamento) de desenvolvimento de qualquer modelo de Machine Learning (aprendizado de máquina), criamos modelos que aprendem a partir de exemplos e passam a prever algum tipo de resultado desejado com base nas relações que extraem desses dados e exemplos.

Geralmente, trabalhamos com um dataset (conjunto de dados) no qual cada coluna é chamada de feature (característica) — isto é, as informações que temos sobre cada exemplo — e há uma coluna chamada alvo ou target (variável alvo), que representa o que queremos que o modelo preveja. Isso vale para problemas de classificação, regressão etc.

Temos, por exemplo, um dataset (conjunto de dados) que podemos utilizar para treinar modelos que estimam o preço de imóveis. As features (características) desse exemplo — ou seja, as informações referentes a cada entidade, neste caso, casas — podem incluir: metragem da casa, quantidade de quartos e distância do centro (em quilômetros). Por fim, temos a variável alvo, o preço desse imóvel. Assim, para um imóvel de 70 metros quadrados, poderíamos ter um preço de 480 mil reais, por exemplo.

Durante o treinamento, o modelo de Machine Learning (aprendizado de máquina) observa tanto as features (características) quanto a variável alvo. Dessa forma, aprende relações e como, a partir das features (características), consegue estimar o valor da target (variável alvo). Após o treinamento, ao partir para a etapa de previsão — isto é, de utilização do modelo já treinado, frequentemente chamada de serving (serviço de previsão) — fornecemos apenas as features (características); não fornecemos a variável alvo, pois é justamente o que desejamos estimar. Esse é um processo padrão em treinamento e uso de modelos de Machine Learning (aprendizado de máquina).

Definindo e padronizando features

Essas features (características) que criamos podem ter diferentes naturezas:

No curso, utilizaremos principalmente features (características) de agregação, que são bastante comuns, combinadas com atributos, que também são frequentes. Agregações aparecem com frequência em modelos de Machine Learning (aprendizado de máquina). Considerando um exemplo com registros de pedidos (como pedidos feitos em um restaurante ou em um aplicativo), podemos realizar um cálculo — por exemplo, contar quantos pedidos são feitos por dia — e isso dá origem a uma feature (característica), como “pedidos por dia”.

Essas features (características) não são simplesmente nomes de colunas; ao defini-las, em geral precisamos responder a quatro perguntas:

  1. De quem a feature (característica) faz referência? (Entidade)
  2. Qual cálculo é realizado?
  3. Qual é a janela temporal (quando houver)?
  4. Qual é a disponibilidade? (Quando a feature passa a estar disponível)

Por exemplo, em um aplicativo de entrega, ao criar uma feature (característica) de “quantos pedidos por dia” para um determinado restaurante:

Como o dia ainda não terminou, se a feature (atributo) conta quantos pedidos ocorreram em um dia inteiro, precisamos de um dia completo para calculá-la. Se, ao responder algumas perguntas sobre essa feature, obtivermos respostas diferentes, provavelmente temos dois atributos distintos, mesmo que tenham o mesmo nome. Por exemplo, se temos pedidos dias e, em vez de considerar o dia inteiro como janela, contamos os pedidos apenas do dia atual, já estamos diante de outro atributo, que traz outra informação. Eles podem ter o mesmo nome, mas são essencialmente atributos diferentes, e é nesse ponto que os problemas podem surgir.

No mesmo exemplo de pedidos de um restaurante, vamos supor que estamos trabalhando com dois times. O time A entende que o atributo pedidos dias está relacionado aos pedidos feitos no dia anterior. Ele cria o atributo pedidos dias e treina um modelo com esse atributo. O time B pode treinar outro modelo ou utilizar o modelo feito pelo time A e, ao observar pedidos dias, pode interpretar que esse atributo representa os pedidos feitos no dia corrente, naquele momento em que o modelo está sendo usado, contabilizando quantos ocorreram até aquele instante no mesmo dia. Reparem: pode ser o mesmo nome de coluna e conceitos semelhantes, mas eles trarão valores diferentes, porque, em um caso, estamos considerando os pedidos feitos no dia anterior e, no outro, os pedidos feitos no mesmo dia em andamento. É o mesmo nome, mas são informações e contagens diferentes.

Cada um desses times que utilizou esse atributo trouxe informações distintas, realizou cálculos diferentes e precisou refazer etapas que o outro time já havia executado. Quando ocorre essa diferença entre o que um time que treinou o modelo definiu e o que o outro time, que está fazendo o serving (serviço) desse modelo, considerou, chamamos essa divergência de Training-Serving Skew (distorção entre treino e serviço). Mesmo sendo o mesmo atributo no nome e trazendo informações semelhantes, os contextos e, por consequência, os números são diferentes, o que afeta a performance do modelo.

Centralizando atributos na feature store

É aí que a Feature Store (repositório de atributos) entra. A Feature Store auxilia na centralização das informações. Em vez de cada time treinar e criar seus próprios atributos, nós criamos uma única vez os atributos, definimos como são calculados, quando ficam disponíveis e qual é a janela que vamos utilizar. Os times que forem usar os atributos não precisarão recriá-los nem tentar inferir o que significam ou como são calculados; simplesmente os consomem diretamente na Feature Store. A Feature Store funciona como uma prateleira onde temos todos os atributos disponíveis para os times utilizarem, tanto para treinamento de modelos quanto para fazer a inferência de modelos já treinados. Ela garante que estamos usando os mesmos atributos, calculados da mesma maneira e disponibilizados de forma consistente. É por isso que utilizamos a Feature Store.

A Feature Store é muito utilizada principalmente quando temos empresas com vários times treinando diversos modelos, e o time que treina um modelo não é necessariamente o mesmo que coloca esse modelo em produção. Para evitar o Training-Serving Skew (ou seja, treinar com certos atributos e características e, depois, usar o modelo em inferência com outros atributos calculados de outra maneira), utilizamos a Feature Store para centralizar definições e uso. Reparem: a Feature Store não vai calcular as métricas nem os atributos, não vai dizer quais atributos são os melhores para determinado problema, nem definir a janela ou a disponibilidade corretas. Ela funciona como uma grande biblioteca, um centralizador de definições que facilita o uso. Nosso trabalho, como pessoas cientistas de dados e pessoas engenheiras de Machine Learning (Aprendizado de Máquina), continua sendo pensar nos atributos, defini-los e realizar seus cálculos.

A diferença é que fazemos isso uma única vez e disponibilizamos para qualquer outra pessoa, seja do nosso time ou de outro, utilizar.

É isso que vamos fazer aqui no curso: vamos implementar um projeto e uma Feature Store para utilizar tanto no treino desse modelo quanto no serving (serviço) dele.

Vamos começar na próxima aula.

Por que precisamos de uma Feature Store? - Conhecendo o projeto e os dados

Apresentando o projeto e os dados

Vamos conhecer o projeto que desenvolveremos ao longo do curso e os dados que temos disponíveis. O projeto é um aplicativo de delivery (entrega) que, na base de dados, terá cerca de 40 restaurantes cadastrados. Usuários podem utilizar esse aplicativo para pedir comida. Quando os pedidos são realizados, o aplicativo promete um horário de entrega, isto é, uma previsão de quando o usuário receberá o pedido; esse pedido pode atrasar ou não.

Nosso papel é desenvolver um modelo de machine learning (aprendizado de máquina) que consiga, a partir do momento em que o usuário faz um pedido, estimar se esse pedido poderá sofrer atraso, ou seja, se o usuário receberá após o horário informado pelo aplicativo. Temos pedidos que já foram entregues e uma base de dados com histórico: vários restaurantes, pedidos realizados em determinados horários, as previsões desses pedidos e, por fim, o horário efetivo em que cada pedido foi entregue.

Com base nesse histórico, vamos calcular features (características) para cada restaurante e treinar um modelo que prevê a chance de atraso. Caso a chance de atraso para um pedido seja maior que 50%, o aplicativo exibirá um alerta: “seu pedido pode atrasar”. Trata-se de um modelo simples de previsão de atraso.

Planejando janelas de treino e produção

Estamos trabalhando com dados que vão de dezembro até março de 2026. Para este projeto, vamos considerar que esse modelo é treinado a cada três meses. Assim, a cada três meses, treinamos um modelo com três meses de histórico e utilizamos esse modelo nos meses seguintes. Vamos utilizar os dados de dezembro a fevereiro para o treino do modelo. O dia 1º de março será considerado o primeiro dia de uso desse modelo; temos esses dados na nossa base e vamos utilizá-los como se fossem dados de produção, para simular o que acontece em produção. Portanto, treinaremos com os dados de dezembro a fevereiro e, no dia 1º de março, vamos simular como se já tivéssemos treinado o modelo e publicado em produção nessa data.

Teremos dois times nesse contexto:

Detalhando as colunas do dataset

Quanto aos dados, temos um dataset (conjunto de dados) no arquivo pedidos.parquet, localizado na pasta "data". Esse Parquet contém um dataset (conjunto de dados) com cinco colunas:

Observando os dados, temos pedidos realizados entre 11 horas da manhã e 10 horas da noite. Todos os pedidos são entregues no mesmo dia em que foram feitos; não há diferença de dias. Assim, se o pedido foi realizado no dia 3, ele foi entregue em algum momento do dia 3.

Explorando os dados iniciais

Para finalizar, vamos apenas verificar os dados disponíveis. Vamos importar algumas bibliotecas que utilizaremos ao longo do projeto: Pandas, Seaborn e scikit-learn.

Estamos lendo o arquivo em formato Parquet (formato colunar de arquivo) com os pedidos para visualizar o nosso dataset (conjunto de dados). Em código, a leitura e a visualização inicial podem ser feitas assim:

pedidos = pd.read_parquet("data/pedidos.parquet")
pedidos.head()

Temos os IDs dos pedidos, que são identificadores únicos sem informação adicional, e os IDs dos restaurantes (por exemplo, restaurante 13, restaurante 30, restaurante 37, e assim por diante). Também temos a informação de quando o pedido foi feito, no campo criado em. No exemplo, o restaurante 13 recebeu um pedido no dia 1º de dezembro de 2025, às 11 horas e 49 minutos. Há, ainda, a previsão de entrega; para esse pedido, a previsão era no mesmo dia, às 11 horas e 55 minutos. Quanto à entrega efetiva, o pedido foi entregue ao cliente no dia 1º de dezembro, às 11 horas e 40 minutos. A previsão era 11 horas e 55 minutos, e o recebimento ocorreu às 11 horas e 40 minutos; portanto, esse pedido não sofreu atraso, mas sim adiantamento.

Dimensionando o volume e o período dos pedidos

Para quantificar o volume de pedidos e o número de restaurantes únicos, podemos consultar o tamanho do dataframe e a contagem de IDs distintos de restaurante:

len(pedidos), pedidos.restaurante_id.nunique()

Conseguimos ver que temos 124 mil pedidos no histórico, distribuídos entre 43 restaurantes únicos (43 IDs diferentes). Para entender o intervalo temporal coberto, também podemos checar as datas mínima e máxima do campo de criação:

pedidos.criado_em.min(), pedidos.criado_em.max()

A primeira data de registro é 1º de dezembro, às 11 horas e 49 minutos, e a última é 1º de março, às 21 horas e 59 minutos.

Separando treino e produção

Vamos treinar o modelo utilizando o histórico de dezembro a fevereiro, e usar o dia 1º de março para simular o modelo treinado em produção. É como se, nesse momento, rodasse a pipeline (fluxo de processamento) de treinamento, o modelo fosse treinado e utilizássemos os dados desse dia como se fossem dados de produção.

Definimos, então, a data de corte. Para isso, criamos um timestamp correspondente a 1º de março de 2026:

CORTE = pd.Timestamp("2026-03-01", tz="UTC")

O histórico que vamos utilizar para treinamento compreende todos os pedidos cujo campo criado em é anterior à data de corte. Produção corresponde a todos os pedidos com datas maiores ou iguais à data de corte. Em código, fazemos o recorte em dois dataframes:

historico = pedidos[pedidos.criado_em < CORTE]
producao = pedidos[pedidos.criado_em >= CORTE]

Nesse recorte, temos 122 mil pedidos para treinamento (histórico) e 1.700 pedidos feitos no dia 1º, que compõem os dados de produção. Podemos conferir essas quantidades diretamente:

len(historico), len(producao)

Para finalizar e ter uma ideia do que esses dados indicam, calculamos o atraso de cada pedido como a data de entrega menos a previsão de entrega. Convertendo esse resultado para segundos e dividindo por 60, obtemos o valor em minutos. Definimos a coluna atraso_min, que traz, para cada registro, quanto tempo atrasou; valores negativos indicam entrega adiantada. Em código, o cálculo do atraso em minutos pode ser feito assim:

atraso_min = (historico.entregue_em - historico.previsao_entrega).dt.total_seconds() / 60
atraso_min

Visualizando a distribuição dos atrasos

Com esses dados, plotamos um gráfico para visualizar melhor a distribuição:

grafico = sns.histplot(atraso_min, bins=60)
grafico.axvline(0, color="red")

Na linha vermelha em zero, todos os pedidos à direita sofreram algum tipo de atraso — inclusive acima de 40 minutos. Todos à esquerda foram entregues adiantados. A maioria corresponde a entregas adiantadas, mas há um número significativo de pedidos entregues com atraso. São esses dados que queremos prever. Na próxima aula, vamos começar a montar o dataset (conjunto de dados) de treinamento.

Sobre o curso Feature Store: criação, materialização e serving com Feast

O curso Feature Store: criação, materialização e serving com Feast possui 286 minutos de vídeos, em um total de 52 atividades. Gostou? Conheça nossos outros cursos de Engenharias e Arquiteturas de Dados em Dados, ou leia nossos artigos de Dados.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda Engenharias e Arquiteturas de Dados acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas