Como construir sistemas de recomendação simples com ML

1. Fundamentos de Sistemas de Recomendação

1.1 Conceitos básicos: o que é um sistema de recomendação e por que usá-lo

Sistemas de recomendação são algoritmos que preveem a preferência de um usuário por um item específico, ajudando a filtrar grandes volumes de dados para sugerir conteúdo relevante. Eles são amplamente utilizados em plataformas como Netflix, Amazon e Spotify para personalizar a experiência do usuário, aumentar o engajamento e impulsionar vendas.

1.2 Tipos de abordagens: filtragem colaborativa, baseada em conteúdo e híbrida

Existem três abordagens principais:
- Filtragem Colaborativa (FC): baseia-se em interações passadas de usuários similares para fazer recomendações.
- Filtragem Baseada em Conteúdo (FBC): utiliza atributos dos itens (gênero, descrição) e o histórico do usuário.
- Híbrida: combina ambas para mitigar limitações como cold start.

1.3 Métricas de avaliação: precisão, revocação, RMSE e MAP@K

  • RMSE (Root Mean Square Error): mede o erro médio entre avaliações previstas e reais.
  • Precisão@K: proporção de itens relevantes entre os K recomendados.
  • Revocação@K: proporção de itens relevantes recuperados entre todos os relevantes.
  • MAP@K: média da precisão média em diferentes níveis de K.

2. Preparação e Exploração dos Dados

2.1 Coleta e limpeza de dados de interação usuário-item

Vamos usar um dataset fictício de avaliações de filmes (usuário, filme, nota).

# Exemplo de dados brutos
usuario_id,filme_id,nota,timestamp
1,101,4.0,2023-01-01
1,102,3.5,2023-01-05
2,101,5.0,2023-02-10
2,103,2.0,2023-02-15
3,102,4.5,2023-03-01

Limpeza: remover duplicatas, tratar valores nulos e normalizar timestamps.

2.2 Análise exploratória: distribuição de usuários, itens e esparsidade

A esparsidade da matriz usuário-item é calculada como:

esparsidade = 1 - (num_interacoes / (num_usuarios * num_itens))

Se tivermos 1000 usuários, 500 filmes e 10.000 avaliações, a esparsidade é 98%.

2.3 Criação de matriz usuário-item e tratamento de dados faltantes

# Criando matriz esparsa
import pandas as pd
from scipy.sparse import csr_matrix

df = pd.read_csv('avaliacoes.csv')
matriz = df.pivot(index='usuario_id', columns='filme_id', values='nota').fillna(0)
matriz_esparsa = csr_matrix(matriz.values)

3. Filtragem Colaborativa com Memória

3.1 Similaridade entre usuários (cosseno, Pearson) e predição baseada em vizinhos

A similaridade de cosseno entre dois usuários u e v é:

similaridade(u,v) = (u · v) / (||u|| * ||v||)

3.2 Similaridade entre itens e recomendação item-item

Para recomendar itens similares a um item i:

# Calcular similaridade entre itens
from sklearn.metrics.pairwise import cosine_similarity
sim_itens = cosine_similarity(matriz_esparsa.T)

3.3 Implementação prática: cálculo de vizinhos mais próximos

from sklearn.neighbors import NearestNeighbors

# Encontrar 5 vizinhos mais próximos para cada usuário
modelo_knn = NearestNeighbors(metric='cosine', n_neighbors=5)
modelo_knn.fit(matriz_esparsa)

# Recomendar para um novo usuário
distancias, indices = modelo_knn.kneighbors(matriz_esparsa[0:1])

4. Filtragem Baseada em Conteúdo

4.1 Representação de itens por atributos

Cada filme pode ser representado por um vetor de gêneros:

# Exemplo: one-hot encoding de gêneros
filmes = {
    101: {'acao': 1, 'aventura': 1, 'comedia': 0},
    102: {'comedia': 1, 'romance': 1, 'drama': 0},
    103: {'acao': 0, 'drama': 1, 'terror': 1}
}

4.2 Criação de perfis de usuário a partir de itens consumidos

O perfil do usuário é a média dos vetores dos itens que ele avaliou positivamente:

# Perfil do usuário 1 (avaliou bem filmes 101 e 102)
perfil_usuario1 = {
    'acao': (1 + 0)/2,
    'aventura': (1 + 0)/2,
    'comedia': (0 + 1)/2,
    'romance': (0 + 1)/2,
    'drama': (0 + 0)/2,
    'terror': (0 + 0)/2
}

4.3 Combinação de similaridade de conteúdo com preferências do usuário

# Calcular similaridade entre perfil do usuário e itens não avaliados
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np

perfil = np.array([1, 1, 0.5, 0.5, 0, 0]).reshape(1, -1)
itens = np.array([[1,1,0,0,0,0], [0,0,1,1,0,0], [0,0,0,0,1,1]])
similaridades = cosine_similarity(perfil, itens)

5. Modelos de Fatoração de Matrizes

5.1 Introdução à decomposição SVD e redução de dimensionalidade

SVD decompõe a matriz R (usuário x item) em três matrizes: U, Σ, V^T. Reduzimos para k fatores latentes.

5.2 Implementação de SVD para predição de avaliações faltantes

from sklearn.decomposition import TruncatedSVD

svd = TruncatedSVD(n_components=10)
matriz_reduzida = svd.fit_transform(matriz_esparsa)

# Predizer avaliação do usuário 0 para o filme 101
predicao = np.dot(matriz_reduzida[0], svd.components_[:, 0])

5.3 Vantagens sobre métodos de memória: escalabilidade e generalização

SVD reduz a dimensionalidade, captura padrões latentes e funciona bem com dados esparsos, ao contrário da FC baseada em memória que exige armazenar toda a matriz.

6. Recomendação com Aprendizado de Máquina Clássico

6.1 Transformação do problema em classificação/regressão

Criamos features combinando atributos do usuário e do item:

# Features: idade do usuário, gênero do filme, nota média do usuário
X = [[25, 1, 3.8], [30, 0, 4.2], [22, 1, 3.5]]
y = [4.0, 5.0, 2.0]  # notas reais

6.2 Uso de regressão logística, Random Forest ou Gradient Boosting

from sklearn.ensemble import RandomForestRegressor

modelo_rf = RandomForestRegressor(n_estimators=100)
modelo_rf.fit(X, y)
predicao = modelo_rf.predict([[28, 1, 4.0]])

6.3 Engenharia de features: one-hot encoding, normalização

from sklearn.preprocessing import StandardScaler, OneHotEncoder

scaler = StandardScaler()
X_normalizado = scaler.fit_transform(X)

7. Avaliação, Otimização e Deploy Simples

7.1 Divisão temporal dos dados: treino, validação e teste

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

7.2 Ajuste de hiperparâmetros

from sklearn.model_selection import GridSearchCV

param_grid = {'n_estimators': [50, 100], 'max_depth': [5, 10]}
grid = GridSearchCV(RandomForestRegressor(), param_grid, cv=5)
grid.fit(X_train, y_train)

7.3 Estratégias de deploy: API simples com Flask/FastAPI

from flask import Flask, request, jsonify
import joblib

app = Flask(__name__)
modelo = joblib.load('modelo_recomendacao.pkl')

@app.route('/recomendar', methods=['POST'])
def recomendar():
    dados = request.json
    predicao = modelo.predict([dados['features']])
    return jsonify({'nota_prevista': predicao[0]})

if __name__ == '__main__':
    app.run(debug=True)

8. Boas Práticas e Próximos Passos

8.1 Lidando com cold start: novos usuários e novos itens

Para novos usuários, use recomendações populares ou baseadas em conteúdo. Para novos itens, colete metadados e use FBC.

8.2 Considerações sobre escalabilidade e atualização do modelo

Modelos baseados em memória não escalam bem. Prefira fatoração de matrizes ou modelos de ML com atualização incremental.

8.3 Ferramentas e bibliotecas recomendadas

  • Surprise: especializada em sistemas de recomendação com SVD, KNN e métricas.
  • scikit-learn: para modelos de ML clássicos e pré-processamento.
  • implicit: para recomendação com dados implícitos (cliques, visualizações).

Referências