Chore: fix
Browse files- .gitignore +2 -0
- app.py +120 -117
.gitignore
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
env/
|
| 2 |
+
.dist/
|
app.py
CHANGED
|
@@ -8,127 +8,130 @@ 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 |
-
#
|
| 13 |
-
|
|
|
|
|
|
|
|
|
|
| 14 |
|
| 15 |
-
#
|
| 16 |
-
|
| 17 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
|
| 19 |
if uploaded_file:
|
| 20 |
# Carregar os dados
|
| 21 |
base_final = pd.read_excel(uploaded_file)
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 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 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 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())
|
|
|
|
| 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 |
+
# app.py
|
| 12 |
|
| 13 |
+
# Função de Preprocessamento
|
| 14 |
+
def preprocess_data(base_final):
|
| 15 |
+
# Convertendo indenização e tempo para numéricos
|
| 16 |
+
base_final['indenizacao_num'] = pd.to_numeric(base_final['indenizacao'], errors='coerce')
|
| 17 |
+
base_final['tempo_num'] = pd.to_numeric(base_final['tempo_meses'], errors='coerce')
|
| 18 |
|
| 19 |
+
# Identificar variáveis categóricas e numéricas
|
| 20 |
+
categorical_cols = ['classe', 'comarca', 'danos', 'resultado']
|
| 21 |
+
numerical_cols = base_final.select_dtypes(include=['float64', 'int64']).columns
|
| 22 |
+
|
| 23 |
+
# Imputação para variáveis categóricas
|
| 24 |
+
from sklearn.impute import SimpleImputer
|
| 25 |
+
imputer_cat = SimpleImputer(strategy='most_frequent')
|
| 26 |
+
base_final[categorical_cols] = imputer_cat.fit_transform(base_final[categorical_cols])
|
| 27 |
+
|
| 28 |
+
# Imputação para variáveis numéricas
|
| 29 |
+
imputer_num = SimpleImputer(strategy='mean')
|
| 30 |
+
base_final[numerical_cols] = imputer_num.fit_transform(base_final[numerical_cols])
|
| 31 |
+
|
| 32 |
+
# Criar dummies para todas as variáveis categóricas
|
| 33 |
+
from sklearn.preprocessing import OneHotEncoder
|
| 34 |
+
encoder = OneHotEncoder(drop='first', sparse_output=False)
|
| 35 |
+
dummies = pd.DataFrame(
|
| 36 |
+
encoder.fit_transform(base_final[categorical_cols]),
|
| 37 |
+
columns=encoder.get_feature_names_out(categorical_cols),
|
| 38 |
+
index=base_final.index
|
| 39 |
+
)
|
| 40 |
+
|
| 41 |
+
# Combinar variáveis contínuas com dummies
|
| 42 |
+
base_final_preprocessed = pd.concat([base_final, dummies], axis=1)
|
| 43 |
+
base_final_preprocessed.drop(columns=categorical_cols, inplace=True)
|
| 44 |
+
base_final_preprocessed = base_final_preprocessed.select_dtypes(include=[np.number])
|
| 45 |
+
|
| 46 |
+
return base_final_preprocessed
|
| 47 |
+
|
| 48 |
+
# Função de Modelagem para Indenização
|
| 49 |
+
def model_indenizacao(base_final_preprocessed):
|
| 50 |
+
X = base_final_preprocessed.drop(columns=['tempo_num', 'indenizacao_num'], errors='ignore')
|
| 51 |
+
y_indenizacao = base_final_preprocessed['indenizacao_num']
|
| 52 |
+
|
| 53 |
+
# Divisão entre treino e teste
|
| 54 |
+
X_train, X_test, y_train_indenizacao, y_test_indenizacao = train_test_split(X, y_indenizacao, test_size=0.3, random_state=42)
|
| 55 |
+
|
| 56 |
+
rf_model_indenizacao = RandomForestRegressor(n_estimators=100, random_state=42)
|
| 57 |
+
rf_model_indenizacao.fit(X_train, y_train_indenizacao)
|
| 58 |
+
y_pred_indenizacao = rf_model_indenizacao.predict(X_test)
|
| 59 |
+
rmse_indenizacao = np.sqrt(mean_squared_error(y_test_indenizacao, y_pred_indenizacao))
|
| 60 |
+
|
| 61 |
+
return rf_model_indenizacao, rmse_indenizacao
|
| 62 |
+
|
| 63 |
+
# Função de Modelagem para Tempo
|
| 64 |
+
def model_tempo(base_final_preprocessed):
|
| 65 |
+
X = base_final_preprocessed.drop(columns=['tempo_num', 'indenizacao_num'], errors='ignore')
|
| 66 |
+
y_tempo = base_final_preprocessed['tempo_num']
|
| 67 |
+
|
| 68 |
+
# Divisão entre treino e teste
|
| 69 |
+
X_train, X_test, y_train_tempo, y_test_tempo = train_test_split(X, y_tempo, test_size=0.3, random_state=42)
|
| 70 |
+
|
| 71 |
+
rf_model_tempo = RandomForestRegressor(n_estimators=100, random_state=42)
|
| 72 |
+
rf_model_tempo.fit(X_train, y_train_tempo)
|
| 73 |
+
y_pred_tempo = rf_model_tempo.predict(X_test)
|
| 74 |
+
rmse_tempo = np.sqrt(mean_squared_error(y_test_tempo, y_pred_tempo))
|
| 75 |
+
|
| 76 |
+
return rf_model_tempo, rmse_tempo
|
| 77 |
+
|
| 78 |
+
# Função de Classificação de Risco
|
| 79 |
+
def model_risco(base_final, X_test, rf_model_indenizacao, rf_model_tempo):
|
| 80 |
+
logistic_model = LogisticRegression(max_iter=500)
|
| 81 |
+
logistic_model.fit(X_test, (base_final['resultado'] == 'Procedente').astype(int))
|
| 82 |
+
y_pred_proba = logistic_model.predict_proba(X_test)[:, 1]
|
| 83 |
+
provisionamento_esperado = (y_pred_indenizacao * y_pred_proba).sum()
|
| 84 |
+
|
| 85 |
+
# Classificação de Risco
|
| 86 |
+
X_test_df = base_final.loc[X_test.index].copy()
|
| 87 |
+
X_test_df['prob_perda'] = y_pred_proba
|
| 88 |
+
X_test_df['risco'] = np.select(
|
| 89 |
+
[X_test_df['prob_perda'] < 0.3,
|
| 90 |
+
(X_test_df['prob_perda'] >= 0.3) & (X_test_df['prob_perda'] < 0.7),
|
| 91 |
+
X_test_df['prob_perda'] >= 0.7],
|
| 92 |
+
['Remoto', 'Possível', 'Provável'],
|
| 93 |
+
default='Desconhecido'
|
| 94 |
+
)
|
| 95 |
+
|
| 96 |
+
return provisionamento_esperado, X_test_df
|
| 97 |
+
|
| 98 |
+
# Título do App
|
| 99 |
+
st.title("Sistema Jurídico - Modelagem de Indenização e Tempo de Processo")
|
| 100 |
+
|
| 101 |
+
# Upload de arquivo
|
| 102 |
+
uploaded_file = st.file_uploader("Faça o upload do arquivo Excel", type=["xlsx"])
|
| 103 |
|
| 104 |
if uploaded_file:
|
| 105 |
# Carregar os dados
|
| 106 |
base_final = pd.read_excel(uploaded_file)
|
| 107 |
+
|
| 108 |
+
st.subheader("Passo 1: Preprocessamento")
|
| 109 |
+
base_final_preprocessed = preprocess_data(base_final)
|
| 110 |
+
st.write("Dados preprocessados:", base_final_preprocessed.head())
|
| 111 |
+
|
| 112 |
+
st.subheader("Passo 2: Modelos Preditivos")
|
| 113 |
+
rf_model_indenizacao, rmse_indenizacao = model_indenizacao(base_final_preprocessed)
|
| 114 |
+
st.write(f"RMSE (Indenização): {rmse_indenizacao:.2f}")
|
| 115 |
+
|
| 116 |
+
rf_model_tempo, rmse_tempo = model_tempo(base_final_preprocessed)
|
| 117 |
+
st.write(f"RMSE (Tempo do Processo): {rmse_tempo:.2f}")
|
| 118 |
+
|
| 119 |
+
st.subheader("Passo 3: Provisionamento e Classificação de Risco")
|
| 120 |
+
provisionamento_esperado, X_test_df = model_risco(base_final, base_final_preprocessed, rf_model_indenizacao, rf_model_tempo)
|
| 121 |
+
st.write(f"Provisionamento esperado: R$ {provisionamento_esperado:.2f}")
|
| 122 |
+
st.write("Classificação de Risco:", X_test_df[['risco', 'indenizacao_num']].head())
|
| 123 |
+
|
| 124 |
+
st.subheader("Passo 4: Classificação de Tempo do Processo")
|
| 125 |
+
X_test_df['tempo_estimado'] = rf_model_tempo.predict(X_test_df)
|
| 126 |
+
X_test_df['categoria_tempo'] = np.select(
|
| 127 |
+
[X_test_df['tempo_estimado'] < 6,
|
| 128 |
+
(X_test_df['tempo_estimado'] >= 6) & (X_test_df['tempo_estimado'] < 12),
|
| 129 |
+
X_test_df['tempo_estimado'] >= 12],
|
| 130 |
+
['Curto', 'Moderado', 'Longo'],
|
| 131 |
+
default='Desconhecido'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 132 |
)
|
| 133 |
+
st.write("Classificação de Tempo:", X_test_df[['categoria_tempo', 'tempo_meses']].head())
|
| 134 |
+
|
| 135 |
+
# Gráficos opcionais
|
| 136 |
+
st.subheader("Distribuição de Previsões")
|
| 137 |
+
st.bar_chart(X_test_df['risco'].value_counts())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|