{"metadata":{"kernelspec":{"name":"python3","display_name":"Python 3","language":"python"},"language_info":{"name":"python","version":"3.11.11","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":50160,"databundleVersionId":7921029,"sourceType":"competition"}],"dockerImageVersionId":31040,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"from sklearn.preprocessing import LabelEncoder\nfrom sklearn.model_selection import train_test_split, StratifiedKFold\nfrom sklearn.metrics import confusion_matrix, accuracy_score, classification_report, ConfusionMatrixDisplay, roc_auc_score  \nfrom lightgbm import LGBMClassifier\nimport pandas as pd\nimport numpy as np\nimport os # Para listar os arquivos\nfrom tqdm import tqdm # Barra de Progresso\nimport gc # Garbage Collector para liberar memória\nimport warnings\nwarnings.filterwarnings(\"ignore\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T13:47:49.087438Z","iopub.execute_input":"2025-08-06T13:47:49.087706Z","iopub.status.idle":"2025-08-06T13:47:56.838724Z","shell.execute_reply.started":"2025-08-06T13:47:49.087683Z","shell.execute_reply":"2025-08-06T13:47:56.837850Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Funções para Extração dos Dados","metadata":{}},{"cell_type":"markdown","source":"- **Função principal para carregamento dos arquivos e filtragem de colunas relevantes como:**\n- *Colunas com menos valores nulos para consistência nas análises*\n- *Colunas com variância significativa para eliminação de redundâncias*","metadata":{}},{"cell_type":"code","source":"def carregar_dados_merge_filtrado(\n    diretorio_base: str,\n    threshold_null: float = 0.5,\n    min_variancia: float = 1e-5,\n    relatorio: bool = True\n) -> pd.DataFrame:\n    \"\"\"\n    Carrega 'train_base' e agrega arquivos auxiliares com merge, \n    filtrando colunas com muitos nulos antes do carregamento completo,\n    e incluindo colunas categóricas.\n\n    Parâmetros:\n    ------------\n    diretorio_base : str\n        Caminho dos arquivos .parquet.\n    threshold_null : float\n        Máx. % de valores nulos permitidos para incluir coluna no merge.\n    min_variancia : float\n        Variância mínima para manter coluna numérica no dataset final.\n    relatorio : bool\n        Se True, imprime relatórios de integração e filtragem.\n\n    Retorna:\n    --------\n    pd.DataFrame consolidado e enxuto para modelagem.\n    \"\"\"\n\n    # Carrega base principal\n    base = pd.read_parquet(os.path.join(diretorio_base, \"train_base.parquet\"))\n    base.set_index(\"case_id\", inplace=True)\n\n    arquivos = sorted([\n        f for f in os.listdir(diretorio_base) if \"train\" in f and f.endswith(\".parquet\")\n    ]) # Retorna os nomes dos arquivos na pasta de treino\n\n    resumo = {}\n    \n    for arq in tqdm(arquivos, desc=\"🔗 Integrando arquivos via merge filtrado\"):\n        try:\n            path = os.path.join(diretorio_base, arq)\n            df_aux = pd.read_parquet(path)\n\n            # Identifica colunas numéricas e categóricas (excluindo 'case_id')\n            col_num = df_aux.select_dtypes(include=\"number\").columns.difference([\"case_id\"]).tolist()\n            col_cat = df_aux.select_dtypes(include=['object', 'category']).columns.difference([\"case_id\"]).tolist()\n\n            # Calcula % de nulos para todas as colunas relevantes\n            # Consideramos numéricas e categóricas para o filtro de nulos\n            cols_to_check = col_num + col_cat\n            if not cols_to_check: # Se não houver colunas para verificar (além de case_id), pula\n                resumo[arq] = 0\n                continue\n\n            pct_null = df_aux[cols_to_check].isnull().mean() #Média de Nulos por coluna\n            col_validas = pct_null[pct_null <= threshold_null].index.tolist()\n\n            # Separa as colunas válidas em numéricas e categóricas novamente\n            col_num_validas = [col for col in col_validas if col in col_num]\n            col_cat_validas = [col for col in col_validas if col in col_cat]\n\n            if not col_num_validas and not col_cat_validas:\n                resumo[arq] = 0\n                continue\n\n            prefixo = arq.replace(\".parquet\", \"\").replace(\"train_credit_bureau_\", \"\")\n            \n            # DataFrame para agregação\n            df_ag = None\n\n            # Agregação para colunas numéricas\n            if col_num_validas:\n                df_num_ag = df_aux.groupby(\"case_id\")[col_num_validas].agg(['mean', 'sum'])\n                df_num_ag.columns = [f\"{prefixo}_{col}_{agg}\" for col, agg in df_num_ag.columns]\n                df_ag = df_num_ag\n            \n            # Agregação para colunas categóricas (usando a moda)\n            # Se uma coluna categórica tiver várias modas, 'mode()' retorna um Series,\n            # então pegamos o primeiro valor [0].\n            if col_cat_validas:\n                df_cat_ag = df_aux.groupby(\"case_id\")[col_cat_validas].agg(lambda x: x.mode()[0] if not x.mode().empty else None)\n                df_cat_ag.columns = [f\"{prefixo}_{col}_mode\" for col in df_cat_ag.columns]\n                \n                if df_ag is not None:\n                    df_ag = df_ag.merge(df_cat_ag, on='case_id', how='left')\n                else:\n                    df_ag = df_cat_ag\n\n            if df_ag is not None:\n                df_ag.reset_index(inplace=True)\n                base = base.merge(df_ag, how='left', on='case_id')\n                resumo[arq] = df_ag.shape[1] - 1 # removendo case_id\n            else:\n                resumo[arq] = 0 # Nenhuma coluna válida para merge\n\n            gc.collect()\n\n        except Exception as e:\n            print(f\"⚠️ Erro em {arq}: {e}\")\n            continue\n\n    base.reset_index(inplace=True)\n\n    # Separa colunas numéricas e categóricas na base final para filtro de variância\n    col_numericas_finais = base.select_dtypes(include='number').columns.tolist()\n    col_categoricas_finais = base.select_dtypes(include=['object', 'category']).columns.tolist()\n\n    # Aplica filtro de variância SOMENTE às colunas numéricas\n    col_numericas_para_filtrar = [c for c in col_numericas_finais if c not in ['case_id', 'target']]\n    if col_numericas_para_filtrar: # Garante que há colunas para calcular variância\n        variancia = base[col_numericas_para_filtrar].var() # Calcula variância\n        col_num_pos_variancia = variancia[variancia > min_variancia].index.tolist() # Mantém as colunas com variância mínima\n    else:\n        col_num_pos_variancia = []\n\n    col_essenciais = ['case_id', 'target'] # Estas sempre serão mantidas\n    \n    # Combina todas as colunas que devem ser mantidas\n    # Colunas essenciais + colunas numéricas após filtro de variância + todas as categóricas\n    cols_a_manter = list(set(col_essenciais + col_num_pos_variancia + col_categoricas_finais))\n\n    base = base[cols_a_manter] # Filtra o DataFrame final\n\n    # Se Relatório = True mostra um resumo final\n    if relatorio:\n        print(f\"\\n✅ Dataset final: {base.shape}\")\n        print(\"\\n📋 Colunas agregadas por arquivo (já filtradas por nulos):\")\n        for nome, qtd in resumo.items():\n            print(f\"• {nome}: {qtd} colunas\")\n        \n        print(f\"\\n📉 Colunas numéricas mantidas após filtro de variância: {len(col_num_pos_variancia)}\")\n        print(f\"🗄️ Colunas categóricas finais mantidas (sem filtro de variância): {len(col_categoricas_finais)}\")\n        print(f\"📊 Total de colunas no dataset final: {base.shape[1]}\")\n\n    return base","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T13:47:56.839706Z","iopub.execute_input":"2025-08-06T13:47:56.840343Z","iopub.status.idle":"2025-08-06T13:47:56.856721Z","shell.execute_reply.started":"2025-08-06T13:47:56.840310Z","shell.execute_reply":"2025-08-06T13:47:56.855841Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"diretorio = \"/kaggle/input/home-credit-credit-risk-model-stability/parquet_files/train\" # Caminho do diretório\ndf_modelagem = carregar_dados_merge_filtrado(diretorio, threshold_null=0.05, min_variancia=0.5) # Chamada da função com exibição de relatório final","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T13:47:56.858999Z","iopub.execute_input":"2025-08-06T13:47:56.859338Z","iopub.status.idle":"2025-08-06T18:11:33.783329Z","shell.execute_reply.started":"2025-08-06T13:47:56.859315Z","shell.execute_reply":"2025-08-06T18:11:33.782294Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"if \"index\" in df_modelagem.columns:\n    df_modelagem.drop(\"index\", axis=1, inplace=True) #Se houver, remove coluna de índice sem valor para o modelo","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T18:11:33.784733Z","iopub.execute_input":"2025-08-06T18:11:33.785754Z","iopub.status.idle":"2025-08-06T18:11:41.352982Z","shell.execute_reply.started":"2025-08-06T18:11:33.785720Z","shell.execute_reply":"2025-08-06T18:11:41.352041Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 5 primeiros registros\ndf_modelagem.head(5)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T18:11:41.354174Z","iopub.execute_input":"2025-08-06T18:11:41.354528Z","iopub.status.idle":"2025-08-06T18:11:41.400993Z","shell.execute_reply.started":"2025-08-06T18:11:41.354500Z","shell.execute_reply":"2025-08-06T18:11:41.400066Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Verificação de duplicatas\ndf_modelagem.drop_duplicates(subset=\"case_id\", inplace=True)\ndf_modelagem.head()\ngc.collect()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T18:11:41.402095Z","iopub.execute_input":"2025-08-06T18:11:41.402456Z","iopub.status.idle":"2025-08-06T18:11:57.939773Z","shell.execute_reply.started":"2025-08-06T18:11:41.402429Z","shell.execute_reply":"2025-08-06T18:11:57.938837Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Estrutura dos dados\ndf_modelagem.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T18:11:57.940954Z","iopub.execute_input":"2025-08-06T18:11:57.941290Z","iopub.status.idle":"2025-08-06T18:11:57.947695Z","shell.execute_reply.started":"2025-08-06T18:11:57.941258Z","shell.execute_reply":"2025-08-06T18:11:57.946900Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Verificação de nulos das 20 primeiras colunas\nprint(df_modelagem.isnull().sum()[:20])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T18:11:57.948623Z","iopub.execute_input":"2025-08-06T18:11:57.948950Z","iopub.status.idle":"2025-08-06T18:12:10.107861Z","shell.execute_reply.started":"2025-08-06T18:11:57.948892Z","shell.execute_reply":"2025-08-06T18:12:10.106985Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"gc.collect()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T18:12:10.112793Z","iopub.execute_input":"2025-08-06T18:12:10.113209Z","iopub.status.idle":"2025-08-06T18:12:10.256580Z","shell.execute_reply.started":"2025-08-06T18:12:10.113179Z","shell.execute_reply":"2025-08-06T18:12:10.255657Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Persistência do arquivo parcialmente tratado\npath_saida = \"df_modelagem_parcial.parquet\"\ndf_modelagem.to_parquet(path_saida, index=False)\nprint(f\"💾 Dataset salvo em: {path_saida}\")\ngc.collect()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T18:12:10.257722Z","iopub.execute_input":"2025-08-06T18:12:10.258074Z","iopub.status.idle":"2025-08-06T18:12:45.789758Z","shell.execute_reply.started":"2025-08-06T18:12:10.258046Z","shell.execute_reply":"2025-08-06T18:12:45.788892Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_base = df_modelagem.copy()\ntrain_base.tail()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T18:12:45.790784Z","iopub.execute_input":"2025-08-06T18:12:45.791268Z","iopub.status.idle":"2025-08-06T18:12:50.273074Z","shell.execute_reply.started":"2025-08-06T18:12:45.791234Z","shell.execute_reply":"2025-08-06T18:12:50.272193Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Informações úteis sobre o conjunto de dados final\ngc.collect()\ntrain_base.info()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T18:12:50.273987Z","iopub.execute_input":"2025-08-06T18:12:50.274262Z","iopub.status.idle":"2025-08-06T18:12:50.432414Z","shell.execute_reply.started":"2025-08-06T18:12:50.274242Z","shell.execute_reply":"2025-08-06T18:12:50.431494Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Balanceamento da classe\ninadimp = train_base[\"target\"].value_counts()\ninadimp","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T18:12:50.433471Z","iopub.execute_input":"2025-08-06T18:12:50.433759Z","iopub.status.idle":"2025-08-06T18:12:50.451888Z","shell.execute_reply.started":"2025-08-06T18:12:50.433730Z","shell.execute_reply":"2025-08-06T18:12:50.451016Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"inadimp[0]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T18:12:50.452830Z","iopub.execute_input":"2025-08-06T18:12:50.453778Z","iopub.status.idle":"2025-08-06T18:12:50.470408Z","shell.execute_reply.started":"2025-08-06T18:12:50.453749Z","shell.execute_reply":"2025-08-06T18:12:50.469648Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"taxa_inad = inadimp[1] / (inadimp[1] + inadimp[0])\nprint(str(round(taxa_inad, 4) * 100) + \"% dos clientes da empresa se tornaram inadimplentes\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T18:12:50.471405Z","iopub.execute_input":"2025-08-06T18:12:50.471711Z","iopub.status.idle":"2025-08-06T18:12:50.488230Z","shell.execute_reply.started":"2025-08-06T18:12:50.471686Z","shell.execute_reply":"2025-08-06T18:12:50.487167Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Resumo Estatístico\ntrain_base.describe()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T18:12:50.489118Z","iopub.execute_input":"2025-08-06T18:12:50.489422Z","iopub.status.idle":"2025-08-06T18:13:02.013286Z","shell.execute_reply.started":"2025-08-06T18:12:50.489400Z","shell.execute_reply":"2025-08-06T18:13:02.012355Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Salvamento do arquivo final em parquet","metadata":{}},{"cell_type":"code","source":"# Colunas com maior quantidade de nulos\ntrain_base.isnull().sum().sort_values(ascending=False).head(20)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T18:13:02.014279Z","iopub.execute_input":"2025-08-06T18:13:02.014608Z","iopub.status.idle":"2025-08-06T18:13:14.069925Z","shell.execute_reply.started":"2025-08-06T18:13:02.014581Z","shell.execute_reply":"2025-08-06T18:13:14.069058Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def filtrar_por_nulos(df: pd.DataFrame, limite: float = 0.15) -> pd.DataFrame:\n    \"\"\"\n    Remove colunas com proporção de nulos maior que o limite especificado.\n\n    Parâmetros:\n    ------------\n    df : DataFrame\n        Conjunto de dados original.\n    limite : float\n        Proporção máxima de nulos (entre 0 e 1) permitida por coluna.\n\n    Retorna:\n    --------\n    DataFrame apenas com colunas com poucos nulos.\n    \"\"\"\n    filtro = df.isnull().mean() <= limite\n    return df.loc[:, filtro]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T18:13:14.070994Z","iopub.execute_input":"2025-08-06T18:13:14.071279Z","iopub.status.idle":"2025-08-06T18:13:14.077714Z","shell.execute_reply.started":"2025-08-06T18:13:14.071251Z","shell.execute_reply":"2025-08-06T18:13:14.076583Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_base = filtrar_por_nulos(train_base, 0.5) # Mantém colunas com até 50% de nulos\nprint(\"Total de colunas após filtro: %d \" % train_base.shape[1])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T18:13:14.079154Z","iopub.execute_input":"2025-08-06T18:13:14.079976Z","iopub.status.idle":"2025-08-06T18:13:27.170781Z","shell.execute_reply.started":"2025-08-06T18:13:14.079942Z","shell.execute_reply":"2025-08-06T18:13:27.169963Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_base.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T18:13:27.171710Z","iopub.execute_input":"2025-08-06T18:13:27.172013Z","iopub.status.idle":"2025-08-06T18:13:27.193490Z","shell.execute_reply.started":"2025-08-06T18:13:27.171993Z","shell.execute_reply":"2025-08-06T18:13:27.192656Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"path_saida = \"df_modelagem_pronto.parquet\"\ntrain_base.to_parquet(path_saida, index=False)\nprint(f\"💾 Dataset salvo em: {path_saida}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T18:13:27.194479Z","iopub.execute_input":"2025-08-06T18:13:27.194782Z","iopub.status.idle":"2025-08-06T18:13:40.141784Z","shell.execute_reply.started":"2025-08-06T18:13:27.194754Z","shell.execute_reply":"2025-08-06T18:13:40.140878Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Treinamento de Modelo base (LightGBM)","metadata":{}},{"cell_type":"code","source":"def codificar_categorias_labelencoder(df: pd.DataFrame, armazenar_codificadores: bool = False):\n    \"\"\"\n    Codifica colunas categóricas com LabelEncoder.\n\n    Parâmetros:\n    ------------\n    df : DataFrame\n        Base de dados original.\n    armazenar_codificadores : bool\n        Se True, retorna também um dicionário com os LabelEncoders usados.\n\n    Retorna:\n    --------\n    df_codificado : DataFrame\n        Dados com colunas categóricas codificadas como números inteiros.\n    encoders : dict (opcional)\n        Dicionário {coluna: LabelEncoder} para reutilização posterior.\n    \"\"\"\n    df_codificado = df.copy()\n    encoders = {}\n\n    col_categoricas = df_codificado.select_dtypes(include=[\"object\", \"category\"]).columns\n\n    for col in col_categoricas:\n        le = LabelEncoder()\n        df_codificado[col] = le.fit_transform(df_codificado[col].astype(str))\n        gc.collect()\n        if armazenar_codificadores:\n            encoders[col] = le\n            \n\n    return (df_codificado, encoders) if armazenar_codificadores else df_codificado","metadata":{"trusted":true,"_kg_hide-input":false,"execution":{"iopub.status.busy":"2025-08-06T18:13:40.142846Z","iopub.execute_input":"2025-08-06T18:13:40.143163Z","iopub.status.idle":"2025-08-06T18:13:40.150326Z","shell.execute_reply.started":"2025-08-06T18:13:40.143141Z","shell.execute_reply":"2025-08-06T18:13:40.149255Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def treinar_modelo_lightgbm(df: pd.DataFrame, n_folds: int = 5):\n\n    features = [col for col in df.columns if col not in ['case_id', 'target', 'MONTH', 'WEEK_NUM']]\n    X = df[features]                                    # Colunas a serem ignoradas no treinamento do modelo\n    y = df['target']\n\n    skf = StratifiedKFold(n_splits=n_folds, shuffle=True, random_state=42)\n    oof_preds = np.zeros(len(X))\n    importancias = []\n\n    print(\"🚀 Iniciando treino com LightGBM...\")\n    for fold, (train_idx, valid_idx) in enumerate(skf.split(X, y)):\n        X_train, y_train = X.iloc[train_idx], y.iloc[train_idx]\n        X_valid, y_valid = X.iloc[valid_idx], y.iloc[valid_idx]\n\n        model = LGBMClassifier(n_estimators=50, learning_rate=0.01, \n                               num_leaves=10, random_state=fold)\n        model.fit(X_train, y_train,\n                  eval_set=[(X_valid, y_valid)],\n                  eval_metric='auc')\n        \n                \n        oof_preds[valid_idx] = model.predict_proba(X_valid)[:, 1]\n        importancias.append(pd.DataFrame({\n            'feature': features,\n            'importance': model.feature_importances_,\n            'fold': fold\n        }))\n        \n        gc.collect()\n\n    score = roc_auc_score(y, oof_preds)\n    print(f\"\\n📈 AUC final (CV média): {score:.4f}\")\n\n    # Importância média\n    df_imp = pd.concat(importancias).groupby('feature')['importance'].mean().sort_values(ascending=False)\n    print(\"\\n🔍 Top 10 features mais importantes:\")\n    print(df_imp.head(10))\n\n    return df_imp","metadata":{"trusted":true,"_kg_hide-input":true,"execution":{"iopub.status.busy":"2025-08-06T18:13:40.151609Z","iopub.execute_input":"2025-08-06T18:13:40.151895Z","iopub.status.idle":"2025-08-06T18:13:40.170224Z","shell.execute_reply.started":"2025-08-06T18:13:40.151873Z","shell.execute_reply":"2025-08-06T18:13:40.169321Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Libera Memória RAM\ngc.collect()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T18:13:40.171191Z","iopub.execute_input":"2025-08-06T18:13:40.171447Z","iopub.status.idle":"2025-08-06T18:13:40.326232Z","shell.execute_reply.started":"2025-08-06T18:13:40.171427Z","shell.execute_reply":"2025-08-06T18:13:40.325294Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Codificação com LabelEncoder\ntrain_base = codificar_categorias_labelencoder(train_base)\ntrain_base.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T18:13:40.327276Z","iopub.execute_input":"2025-08-06T18:13:40.327552Z","iopub.status.idle":"2025-08-06T18:14:06.636814Z","shell.execute_reply.started":"2025-08-06T18:13:40.327525Z","shell.execute_reply":"2025-08-06T18:14:06.635956Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Libera Memória RAM\ngc.collect()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T18:14:06.637885Z","iopub.execute_input":"2025-08-06T18:14:06.638331Z","iopub.status.idle":"2025-08-06T18:14:06.775748Z","shell.execute_reply.started":"2025-08-06T18:14:06.638295Z","shell.execute_reply":"2025-08-06T18:14:06.774892Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_base.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T18:14:06.779535Z","iopub.execute_input":"2025-08-06T18:14:06.780327Z","iopub.status.idle":"2025-08-06T18:14:06.795811Z","shell.execute_reply.started":"2025-08-06T18:14:06.780301Z","shell.execute_reply":"2025-08-06T18:14:06.795074Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Amostragem aleatória dos dados para reduzir o uso de memória\ntrain_base_final = train_base.sample(frac=0.6, random_state=33)\n# Treinar modelo com validação cruzada\ntreinar_modelo_lightgbm(train_base, n_folds=10)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T18:14:06.796940Z","iopub.execute_input":"2025-08-06T18:14:06.797288Z","iopub.status.idle":"2025-08-06T18:18:12.202336Z","shell.execute_reply.started":"2025-08-06T18:14:06.797258Z","shell.execute_reply":"2025-08-06T18:18:12.201550Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}