quinta-feira, 28 de março de 2024

Consulta com Python à API pública do DataJud (Base de Dados do Poder Judiciário) do CNJ

O Conselho Nacional de Justiça - CNJ disponibiliza uma API pública que fornece os metadados e movimentações dos processos judiciais não gravados de sigilo. A documentação da ferramenta está disponível aqui.

A API permite pesquisas pelo número de processo ou por classe processual e órgão julgador. A resposta pode conter até 10.000 registros por página.

Cada tribunal tem seu "endpoint" específico. Na documentação da API encontramos a URL do TJSP e a chave pública para a consulta. Usando o Python, criamos uma solicitação POST para obter os dados sobre ANPPs.

Sabendo que a API utiliza o Elasticsearch - uma linguagem de consulta que permite recuperar informações segundo determinados critérios de pesquisa - restringimos a requisição à classe 12729 (que corresponde à "Execução de Medidas Alternativas"). Com o método response.json(), convertemos a resposta da API (em JSON) em dicionário Python, facilitando a criação do dataframe.
Mais à frente, utilizamos a busca pela string "Acordo de Não Persecução Penal" na coluna "assuntos" para restringir o dataframe ao que, de fato, nos interessava (dados sobre os ANPPs).

O código também converteu todos os horários para o fuso de São Paulo.

A partir desse ponto, foi possível agrupar as informações por períodos de tempo e horários, para as devidas análises e plotagens.
Descobrimos, assim, que; - 23,31% dos ajuizamentos de ANPP ocorrem fora do horário de expediente.
- De agosto de 2023 para cá houve uma sensível queda do número de ANPPs ajuizados no Estado de São Paulo, o que talvez se explique em razão da nova regulamentação do ANPP que foi estabelecida no âmbito do MPSP.

O notebook com o código usado na análise pode ser acessado a partir do meu GitHub. Experimente rodá-lo no Colab.

Uma vez que a coluna "movimentos" do dataframe pode conter o Cód: 12735, relativo à extinção da punibilidade pelo cumprimento do ANPP, pode ser interessante, num projeto futuro, verificar qual a porcentagem de acordos cumpridos e o tempo médio para que isso ocorra.










segunda-feira, 20 de novembro de 2023

Gerenciando ambientes virtuais com Conda

O Conda – que vem com o Anaconda ou Miniconda – facilita o gerenciamento de ambientes virtuais para os diferentes projetos em Python.

Uma vez disponível (para conferir se está ok: conda --version), podemos construir, ativar, alternar ou deletar os ambientes com os seguintes comandos:


1. Criar novo ambiente virtual:

conda create --name meu_ambiente python=3.8

conda create --name meu_ambiente


2. Ativar o ambiente virtual:

conda activate meu_ambiente


3. Instalar pacotes:

conda install numpy

ou

pip install numpy


4. Listar ambientes:

conda env list


5. Desativar ambiente:

conda deactivate


6. Remover um ambiente:

conda env remove --name meu_ambiente


Outras dicas:


7. Criação de um arquivo yml com as dependências do ambiente: 

conda env export > environment.yml (recomendo excluir a linha iniciada por “prefix”, que se refere ao caminho local do seu sistema de arquivos)

ou

pip freeze > requirements.txt (padrão do pip)


Obs. : para recriar ambiente a partir de environment.yml:

conda env create -f environment.yml


8. Mantenha o Conda atualizado: 

conda update conda


quinta-feira, 9 de novembro de 2023

Em breve, nós promotores de justiça compartilharemos nossos próprios GPTs

Quando ingressei no Ministério Público, era comum recebermos dos Centros de Apoio (CAOs) alguns CDs (de 650 MB) com modelos de peças e jurisprudência. 

Com a expansão da Internet e a implantação do portal institucional, a forma de compartilhar conhecimento no âmbito do MPSP mudou completamente. Nossa capacidade atual de fazer o reuso de teses e reaproveitar as peças elaboradas pelos colegas está diretamente relacionada à organização do site e à eficácia do mecanismo buscador. 

Há um “game changing” acontecendo nessa área. 

No evento “DevDay” do último dia 6, a primeira conferência direcionada a desenvolvedores promovida pela OpenAI, foram anunciadas inovações ao ChatGPT que permitirão, mesmo aos não desenvolvedores, criar versões customizadas do bot, denominadas GPTs (Generative Pre-trained Transformers), para tarefas específicas. 

O ChatGPT poderá, agora, se conectar a bases de dados, aprender com dados pessoais e acessar a internet. Não será preciso escrever código para que criemos soluções próprias destinadas a minutar denúncias, alegações finais e outras manifestações... e com o nosso estilo. Esses bots poderão ser publicados numa plataforma – a “GPT Store” – e compartilhados. 

É urgente, portanto, que conheçamos a política de privacidade dessas soluções e que a alta gestão do MPSP se atente ao tema.

Pensando no MPSP como um todo, precisaremos, também, ter em nossos quadros engenheiros de dados (para coletar, preparar e organizar as informações corporativas para treinamento de IAs) e engenheiros de softwares (para implementar as soluções em produção). 

Para saber mais: https://openai.com/blog/introducing-gpts

quarta-feira, 26 de julho de 2023

Operações com datas e horas usando Python

Com Python, fazemos operações com datas e horas usando as bibliotecas datetime e relativedelta.

A biblioteca datetime possui as seguintes classes principais: date, time, datetime e timedelta

A classe date representa uma data, a classe time representa um horário e a classe datetime representa uma combinação de data e horário. A classe timedelta é usada para realizar operações matemáticas com datas e tempos. Representa, portanto, um intervalo de tempo (com dias, horas, minutos e segundos).

Uma estratégia bastante usada nos programas é converter, previamente, as strings representativas de datas em objetos datetime para em seguida realizar as operações desejadas. Vamos fazer isso, calculando há quantos dias estou vivo.


Primeiro obtemos a data de hoje:

>>> from datetime import datetime, timedelta

>>> hoje = datetime.now()

>>> print(hoje)

2023-07-26 07:01:20.328655


Depois, convertemos a string em objeto datetime:

>>> nascimento = '24/03/1966'

>>> data_nasc = datetime.strptime(nascimento, "%d/%m/%Y")

>>> print(type(data_nasc))

<class 'datetime.datetime'>


Agora, é só calcular…

>>> dias_vividos = hoje - data_nasc

>>> print(dias_vividos)

20943 days, 7:01:20.328655

>>> print(dias_vividos.days)

20943


A classe relativedelta é mais poderosa que a timedelta, pois permite lidar com unidades de tempo maiores, como meses e anos, além dos componentes habituais de tempo, como dias, horas e minutos. Deve ser importada de from dateutil.relativedelta.

Com ela podemos, por exemplo, adicionar ou subtrair uma semana, um mês ou um ano de uma determinada data, considerando as diferenças de dias contidos nos meses e com anos bissextos.


Usando a classe relativedelta, poderíamos obter o seguinte resultado para o tempo vivido.

>>> from dateutil.relativedelta import relativedelta

>>> relativedelta(data_nasc, hoje)

relativedelta(years=-57, months=-4, days=-2, hours=-7, minutes=-1, seconds=-21, microseconds=+671345)


Poderíamos calcular o termo final de um prazo penal (contando o dia do início e excluindo o dia do fim) de 1 ano e 6 meses a partir de hoje da seguinte forma:

>>> termo_final = hoje + relativedelta(years=1, months=6) + relativedelta(days= -1)

>>> print(termo_final)

2025-01-25 07:01:20.328655


Ou, com uma saída mais amigável:

>>> print(termo_final.strftime("%d/%m/%Y"))

25/01/2025


domingo, 9 de julho de 2023

Roteiro para a criação de contêiner Docker para uma aplicação com Python

Quero rodar uma aplicação escrita em Python com suas dependências em um contêiner Docker, construído do zero.

Para isso, preciso:

1 - Definir um diretório de trabalho na máquina local.

2 - Construir a imagem Docker, a partir das instruções do arquivo "Dockerfile" (sem extensão) e das dependências listadas no arquivo "requirements.txt".

3 - Construir a imagem. Nesta fase, são instaladas as dependências encontradas em "requirements.txt".

4 - Executar o contêiner, mapeando a pasta local com a pasta do contêiner onde roda a aplicação.

Só isso!

domingo, 11 de junho de 2023

Machine Learning: escolha dos hiperparâmetros e ensamble

Introdução

Nesta semana, implementamos uma solução de machine learning para o conhecido problema "Titanic - Machine Learning From Disaster", disponibilizado em forma de competição permanente no Kaggle, conhecido portal com conteúdo voltado para a Ciência de Dados. 

Seguimos os seguintes passos: 1) importação das bibliotecas necessárias; 2) leitura do dataset (disponibilizado no Kaggle); 3) pré-processamento dos dados; 4) criação de "features"; 5) seleção de "features"; 6) visualização; 7) agrupamento por sobreviventes (o que permitiu observar quais "features" eram mais relevantes para o resultado); 8) criação da tabela pivô (em relação à "feature" "Pclass"); 9) padronização das variáveis; 10 ) utilização dos modelos (Logistic Regression, Naive Bayes para Classificação, KNN para Classificação, SVM para Classificação, Decision Tree e Random Forest) e avaliação de seus respectivos desempenhos, obtidos por validação cruzada (método sklearn.model_selection.cross_val_score).

Dois aspectos do trabalho mereceram maior atenção: a escolha dos hiperparâmetros (tuning) e o e ensamble (conjugação) dos modelos.

Escolha dos hiperparâmetros

A otimização dos hiperparâmetros (tuning) foi feita com o método gp_minize da biblioteca scikit-optimize (skop). O método implementa a otimização bayesiana, usando processos gaussianos , para encontrar os hiperparâmetros ótimos, sendo computacionalmente mais eficiente do que a classe GridSearchCV, do Sklearn, que faz a busca exaustiva.

A biblioteca pode ser instalada com:

!pip install scikit-optimize

A função que nos retorna a métrica e a lista da parâmetros ótimos é a seguinte:

def treinar_modelo_dtc (parametros_dtc):

  model_dtc = DecisionTreeClassifier(criterion = parametros_dtc[0], 

                                     max_depth = parametros_dtc[1],

                                     min_samples_split = parametros_dtc[2], 

                                     min_samples_leaf = parametros_dtc[3],

                                     random_state = 0)  

  score = cross_val_score(model_dtc, X_train_sc, y_train, cv = 10)  

  mean_score = np.mean(score)

  print(np.mean(score))

  return -mean_score

parametros_dtc= [['gini', 'entropy', 'log_loss'], 

                  (2, 6), 

                  (2, 5), 

                  (1, 3),

                  ]

otimos_dtc = gp_minimize(treinar_modelo_dtc, parametros_dtc, random_state = 0, verbose = 1, n_calls = 30, n_random_starts = 10)

print(otimos_dtc.fun, otimos_dtc.x)

# -0.8181772784019975 ['entropy', 3, 3, 2]


Ensamble dos modelos

Para o ensamble dos modelos, após a obtenção dos hiperparâmetros ótimos, usamos a classe VotingClassifier.

A implementação foi feita da seguinte forma:

from sklearn.ensemble import VotingClassifier

model_voting = VotingClassifier(estimators = [('RF', model_rf),

                                              ('SVC', model_svc),

                                              ('DTC', model_dtc)], 

                                weights=[1, 2, 1],

                                voting='hard' )

model_voting.fit(X_train_sc, y_train)

score = cross_val_score(model_voting, X_train_sc, y_train, cv = 10)

print(np.mean(score))

# sem weights: 0.8339200998751561

# com weights: 0.8350062421972535


Resultado

O modelo combinado obteve o score de 0.77751 no Kaggle, conferindo-nos a posição nº 4499 no ranking,  às 11h54min de 9 jun. 2023.



Referências

ANIFOWOSE, Fatai. Ensemble Machine Learning Explained in Simple Terms. Disponível em: <https://jpt.spe.org/twa/ensemble-machine-learning-explained-simple-terms>. Acesso em 10 jun. 2023.

CODERSCOLUMN. Scikit-Optimize: Simple Guide to Hyperparameters Tunning / Optimization. Disponível em: <https://coderzcolumn.com/tutorials/machine-learning/scikit-optimize-guide-to-hyperparameters-optimization>. Acesso em 10 jun. 2023.

KUMAR, Satyam. Use Voting Classifier to improve the performance of your ML model [Towardsdatascience]. Disponível em: <https://towardsdatascience.com/use-voting-classifier-to-improve-the-performance-of-your-ml-model-805345f9de0e>. Acesso em: 10 jun. 2023.

SCIKIT-LEARN. Ensemble Methods. Disponível em: <https://scikit-learn.org/stable/modules/ensemble.html>. Acesso em 10 jun. 2023.

SCIKIT-OPTIMIZE. Disponível em <https://scikit-optimize.github.io/stable/modules/generated/skopt.gp_minimize.html#>. Acesso em 10 jun. 2023.

VALENTE, Domingos Sárvio Magalhães. ELT579 - Aula 8 VotingModel. Disponível em: <https://youtu.be/Fo5QLR8fyZw> . Acesso em 10 jun. 2023.