First commit
Browse files- app.py +134 -0
- requirements.txt +16 -0
app.py
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
import pandas as pd
|
| 3 |
+
import numpy as np
|
| 4 |
+
import streamlit as st
|
| 5 |
+
import tensorflow as tf
|
| 6 |
+
from sklearn.preprocessing import LabelEncoder, StandardScaler
|
| 7 |
+
from sklearn.model_selection import train_test_split
|
| 8 |
+
from tensorflow.keras.layers import Input, Embedding, Flatten, Concatenate, Dense, BatchNormalization, Dropout
|
| 9 |
+
from tensorflow.keras.models import Model
|
| 10 |
+
import matplotlib.pyplot as plt
|
| 11 |
+
|
| 12 |
+
# Título
|
| 13 |
+
st.title("Provisionamento de Indenizações - Modelo de Deep Learning")
|
| 14 |
+
|
| 15 |
+
# Upload de Dados
|
| 16 |
+
st.sidebar.header("Upload de Dados")
|
| 17 |
+
uploaded_file = st.sidebar.file_uploader("Envie seu arquivo Excel", type=["xlsx"])
|
| 18 |
+
|
| 19 |
+
if uploaded_file:
|
| 20 |
+
# Carregar os dados
|
| 21 |
+
base_final = pd.read_excel(uploaded_file)
|
| 22 |
+
|
| 23 |
+
# Preprocessamento
|
| 24 |
+
st.sidebar.subheader("Configurações de Pré-processamento")
|
| 25 |
+
date_columns = st.sidebar.multiselect("Colunas de Data a Remover", options=base_final.columns, default=['data', 'data_presumida'])
|
| 26 |
+
base_final = base_final.drop(columns=date_columns, errors='ignore')
|
| 27 |
+
|
| 28 |
+
base_final['indenizacao'] = base_final['indenizacao'].replace('Valor Não Previsto/Mencionado', np.nan).astype(float)
|
| 29 |
+
base_final['remuneracao_magistrado'] = base_final['remuneracao_magistrado'].fillna(base_final['remuneracao_magistrado'].mean())
|
| 30 |
+
base_final['entrancia'] = base_final['entrancia'].fillna('Desconhecido')
|
| 31 |
+
base_final['latitude'] = base_final['latitude'].fillna(base_final['latitude'].mean())
|
| 32 |
+
base_final['longitude'] = base_final['longitude'].fillna(base_final['longitude'].mean())
|
| 33 |
+
base_final['count'] = base_final['count'].fillna(base_final['count'].mean())
|
| 34 |
+
base_final['tempo_por_comarca'] = base_final['tempo_meses'] * base_final['count']
|
| 35 |
+
base_final['tempo_por_comarca'] = base_final['tempo_por_comarca'].fillna(0)
|
| 36 |
+
|
| 37 |
+
base_final = base_final[base_final['indenizacao'].notna()]
|
| 38 |
+
|
| 39 |
+
# Separar variáveis categóricas, numéricas e alvo
|
| 40 |
+
categorical_columns = ['classe', 'assunto', 'magistrado', 'comarca', 'foro', 'vara', 'decisao', 'resultado', 'danos', 'entrancia']
|
| 41 |
+
numerical_columns = ['ano_processo', 'tempo_meses', 'remuneracao_magistrado', 'latitude', 'longitude', 'count']
|
| 42 |
+
target = 'indenizacao'
|
| 43 |
+
|
| 44 |
+
label_encoders = {}
|
| 45 |
+
for col in categorical_columns:
|
| 46 |
+
le = LabelEncoder()
|
| 47 |
+
base_final[col] = le.fit_transform(base_final[col])
|
| 48 |
+
label_encoders[col] = le
|
| 49 |
+
|
| 50 |
+
scaler = StandardScaler()
|
| 51 |
+
base_final[numerical_columns + ['tempo_por_comarca']] = scaler.fit_transform(base_final[numerical_columns + ['tempo_por_comarca']])
|
| 52 |
+
|
| 53 |
+
X = base_final[categorical_columns + numerical_columns + ['tempo_por_comarca']]
|
| 54 |
+
y = base_final[target].values
|
| 55 |
+
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
|
| 56 |
+
|
| 57 |
+
# Construção do Modelo
|
| 58 |
+
inputs = []
|
| 59 |
+
encoded_layers = []
|
| 60 |
+
|
| 61 |
+
for col in categorical_columns:
|
| 62 |
+
input_cat = Input(shape=(1,), name=f"input_{col}")
|
| 63 |
+
inputs.append(input_cat)
|
| 64 |
+
num_unique_vals = base_final[col].nunique()
|
| 65 |
+
embedding_dim = min(50, num_unique_vals // 2)
|
| 66 |
+
embedding = Embedding(input_dim=num_unique_vals + 1, output_dim=embedding_dim, name=f"embedding_{col}")(input_cat)
|
| 67 |
+
flatten = Flatten()(embedding)
|
| 68 |
+
encoded_layers.append(flatten)
|
| 69 |
+
|
| 70 |
+
tempo_por_comarca_input = Input(shape=(1,), name="tempo_por_comarca_input")
|
| 71 |
+
inputs.append(tempo_por_comarca_input)
|
| 72 |
+
encoded_layers.append(tempo_por_comarca_input)
|
| 73 |
+
|
| 74 |
+
input_num = Input(shape=(len(numerical_columns),), name="input_numerical")
|
| 75 |
+
inputs.append(input_num)
|
| 76 |
+
encoded_layers.append(input_num)
|
| 77 |
+
|
| 78 |
+
concat = Concatenate()(encoded_layers)
|
| 79 |
+
x = Dense(128, activation="relu")(concat)
|
| 80 |
+
x = BatchNormalization()(x)
|
| 81 |
+
x = Dropout(0.3)(x)
|
| 82 |
+
x = Dense(64, activation="relu")(x)
|
| 83 |
+
x = BatchNormalization()(x)
|
| 84 |
+
x = Dropout(0.3)(x)
|
| 85 |
+
output = Dense(1, activation="linear", name="output")(x)
|
| 86 |
+
|
| 87 |
+
model = Model(inputs=inputs, outputs=output)
|
| 88 |
+
model.compile(optimizer="adam", loss="mse", metrics=["mae"])
|
| 89 |
+
|
| 90 |
+
# Preparar os dados para o modelo
|
| 91 |
+
input_data = [X_train[col].values.reshape(-1, 1) for col in categorical_columns]
|
| 92 |
+
input_data.append(X_train['tempo_por_comarca'].values.reshape(-1, 1))
|
| 93 |
+
input_data.append(X_train[numerical_columns].values)
|
| 94 |
+
|
| 95 |
+
val_data = (
|
| 96 |
+
[X_test[col].values.reshape(-1, 1) for col in categorical_columns]
|
| 97 |
+
+ [X_test['tempo_por_comarca'].values.reshape(-1, 1)]
|
| 98 |
+
+ [X_test[numerical_columns].values],
|
| 99 |
+
y_test
|
| 100 |
+
)
|
| 101 |
+
|
| 102 |
+
# Treinamento
|
| 103 |
+
st.sidebar.subheader("Treinamento")
|
| 104 |
+
epochs = st.sidebar.slider("Épocas", min_value=10, max_value=100, value=50, step=10)
|
| 105 |
+
batch_size = st.sidebar.slider("Tamanho do Batch", min_value=16, max_value=128, value=32, step=16)
|
| 106 |
+
|
| 107 |
+
with st.spinner("Treinando o modelo..."):
|
| 108 |
+
history = model.fit(
|
| 109 |
+
input_data[:12],
|
| 110 |
+
y_train,
|
| 111 |
+
validation_data=(val_data[0][:12], val_data[1]),
|
| 112 |
+
epochs=epochs,
|
| 113 |
+
batch_size=batch_size,
|
| 114 |
+
callbacks=[tf.keras.callbacks.EarlyStopping(monitor="val_loss", patience=5, restore_best_weights=True)],
|
| 115 |
+
verbose=0
|
| 116 |
+
)
|
| 117 |
+
|
| 118 |
+
st.success("Modelo treinado com sucesso!")
|
| 119 |
+
|
| 120 |
+
# Avaliação
|
| 121 |
+
st.subheader("Resultados do Modelo")
|
| 122 |
+
results = model.evaluate([val_data[0][i] for i in range(12)], val_data[1], verbose=0)
|
| 123 |
+
st.write(f"Loss (MSE): {results[0]:.4f}")
|
| 124 |
+
st.write(f"MAE: {results[1]:.4f}")
|
| 125 |
+
|
| 126 |
+
# Gráfico de Treinamento
|
| 127 |
+
st.subheader("Curva de Treinamento")
|
| 128 |
+
plt.figure(figsize=(10, 6))
|
| 129 |
+
plt.plot(history.history['loss'], label='Loss de Treinamento')
|
| 130 |
+
plt.plot(history.history['val_loss'], label='Loss de Validação')
|
| 131 |
+
plt.xlabel('Épocas')
|
| 132 |
+
plt.ylabel('Loss')
|
| 133 |
+
plt.legend()
|
| 134 |
+
st.pyplot(plt.gcf())
|
requirements.txt
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
openpyxl
|
| 2 |
+
matplotlib
|
| 3 |
+
scikit-learn
|
| 4 |
+
pydantic==1.10.13
|
| 5 |
+
tiktoken
|
| 6 |
+
tensorflow
|
| 7 |
+
pandas
|
| 8 |
+
uvicorn
|
| 9 |
+
sse_starlette
|
| 10 |
+
hypercorn
|
| 11 |
+
apscheduler
|
| 12 |
+
python-jose
|
| 13 |
+
python-multipart
|
| 14 |
+
bcrypt
|
| 15 |
+
passlib
|
| 16 |
+
pyjwt
|