Leia nosso artigo sobre

.

Filtrar o data usando ID == ‘string’ no Pandas é algo que o senhor deve evitar, pois o operador scalar_compare leva a gargalos de desempenho. Há muitas maneiras de contornar isso, por exemplo, particionando o quadro Data em um dicionário usando o ID em questão como chave.

Introdução | Filtros de string no pandas

A simplificação do gerenciamento de hardware, proporcionada pelas soluções cloud, faz com que cada vez mais nos afastemos dos problemas de otimização de código.

The simplification of hardware management, brought by cloud solutions, pushes us more and more to turn away from the problems of code optimisation.

Mas o aumento de escala e aumentar a capacidade de computação nem sempre é a solução pois isso leva a um aumento dos custos e a capacidade de computação não é infinita.

Ao me desafiar a encaixar toda a minha preparação para o data em um contêiner simples, percebi rapidamente que, com o conhecimento de alguns truques, o senhor pode fazer o que quiser, otimizar seu código às vezes pode ser tão simples quanto instanciar uma instância maior.

Neste artigo, gostaria de voltar a uma única alteração de código que me permitiu reduzir drasticamente o tempo gasto no cálculo dos recursos durante a fase de desenvolvimento de um modelo de propensão. Essa alteração é comum o suficiente para ser aplicada a muitas outras situações.

Ele não tem como objetivo ser a solução mais ideal, mas procura ser uma opção rápida para diminuir o tempo de computação de forma eficiente, no espírito do Princípio de Pareto.

Contexto

Durante essa missão, fui encarregado de automatizar o processo de preparação do data e a previsão de modelos desenvolvidos por nossa equipe de cientistas do Data. Para simplificar o fluxo do data, o data transacional era carregado todos os dias e tinha de passar por uma primeira Pré-processamento seguida de uma segunda etapa de Recurso Computação antes de chegar à última etapa do Previsão de modelo usando o modelo treinado.

The Feature computation phase is the one that took the longest time to execute: indeed many features were computed at the customer level

O Computação de recursos é a fase que levou mais tempo para ser executada: na verdade, muitos recursos foram computados no nível do cliente, o que resultou na execução recorrente de uma linha surpreendentemente demorada no código:

which resulted in the recurrent execution of a surprisingly time-consuming line in the code :

Essa única linha foi cronometrada em 18 ms, o que significa que, com meus 33.717 clientes para avaliar diariamente, eu estava gastando cerca de 10 minutos de tempo bruto de computação por recursos de nível de cliente, reduzido para 1 minuto e 16 segundos por recurso graças à paralelização da operação em minhas 8 CPUs disponíveis.

Como estávamos trabalhando com o B2B data, foi necessário computar os recursos no nível do cliente, pois um cliente representava, na verdade, uma empresa com, às vezes, vários pedidos por dia.

Experimentação | Filtros de string no pandas

Depois de investigar um pouco usando o %%prun Consegui identificar a origem desse gargalo de processamento: o pandas._libs.ops.scalar_compare que estava subotimizado na minha versão do Pandas (1.3.1).

Simplesmente substituindo esse “==” pelo operador “isin”, o que não é muito intuitivo, pois eu estava comparando uma única string, já dividi o tempo de computação por 2,5 vezes, passando de 18ms por operação para 7,95ms.

Ainda em busca de otimização, deparei-me com um Stackoverflow post promovendo o uso de Tipo categórico para melhorar ainda mais a operação.

Essa última implementação me permitiu dividir o tempo de computação em mais de 36 vezes. No entanto, pude observar uma nuance nesse truque, pois o tipo de categoria não se comporta como um str clássico durante todas as operações (veja o exemplo abaixo ao usar .groupby() no pandas), então tive que convertê-lo de volta para str em um ponto.

Hipótese

Mas por que isso acontece? Como pode um simples == entre duas strings leva mais tempo do que uma operação de isin() comparando listas, ou uma operação categórica um ?
Bem, para responder à primeira pergunta, precisaríamos definitivamente descobrir o código por trás da execução do scalar_compare que usa principalmente Cython e compará-lo com o código por trás do isin() método.

Felizmente, a resposta para a segunda parte parece ser mais intuitiva: ao comparar dois valores de cadeia de caracteres, estamos comparando um número infinito de possibilidades juntas, enquanto que ao comparar duas categorias, o o número de opções é definido pelas diferentes categorias exclusivas que existem. Parece muito é mais fácil comparar duas entidades quando nosso número de opções é fixo.

Como minha sede por otimização ainda não estava saciada, decidi dar um passo atrás em relação ao método atual. Criei uma nova abordagem: Particionar meu Dataframe em um dicionário que usarei para filtrar meus clientes ao calcular meus recursos.
Em termos de código, isso se traduziu simplesmente nas seguintes linhas:

lista_de_clientes = lista(df.ID_Customer.unique()) df_dict = {elem: df[df.ID_Customer == elem] for elem in customers_list}

A criação desse dicionário me custou 32 segundos de tempo de computação, mas usando esse quadro Data particionado, consegui filtrar meu data em alguns nanossegundos.

Conclusão | Filtros de string no pandas

Depois de passar algumas horas na fase de experimentação, fiquei satisfeito com o resultado:

After spending a couple of hours in the experimentation phase, I was happy with the result :

O tempo inicial de computação por filtragem de cliente foi agora dividido 348 000 vezes, indo de 18ms a 51,7ns, ou de 10min a 2,65ms por recurso calculado no meu caso, levando em conta o tempo gasto no particionamento.

Immediately, the impact of this small change allowed me to reduce the calculation time of my complete Feature computation phase by 90%, from 40'49" to 7'27".

Imediatamente, o impacto dessa pequena mudança me permitiu reduzir o tempo de cálculo da minha fase completa de computação de recursos em 90%, de 40’49” para 7’27”. Usando um método de estimativa de CO2eq que detalharei em meu próximo artigo, essa modificação economizou pelo menos 170$/ano + 22kgCO2/ano e potencialmente muito mais com a crescente lista de clientes e a implementação do projeto em outros países.

Medium Blog por Artefact.

Este artigo foi publicado inicialmente no Medium.com.
Siga-nos em nosso Medium Blog !