{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Predição de sobreviventes do Titanic com Regressão Logística","metadata":{}},{"cell_type":"markdown","source":"<h1>Sumário<span class=\"tocSkip\"></span></h1>\n<div class=\"toc\"><ul class=\"toc-item\"><li><span><a href=\"#Introdução\" data-toc-modified-id=\"Introdução-1\">Introdução</a></span></li><li><span><a href=\"#Descrição-das-variáveis\" data-toc-modified-id=\"Descrição-das-variáveis-2\">Descrição das variáveis</a></span></li><li><span><a href=\"#Bibliotecas-utilizadas\" data-toc-modified-id=\"Bibliotecas-utilizadas-3\">Bibliotecas utilizadas</a></span></li><li><span><a href=\"#Lendo-Dados\" data-toc-modified-id=\"Lendo-Dados-4\">Lendo Dados</a></span></li><li><span><a href=\"#Separando-entre-Dataset-de-Treino-e-Teste\" data-toc-modified-id=\"Separando-entre-Dataset-de-Treino-e-Teste-5\">Separando entre Dataset de Treino e Teste</a></span></li><li><span><a href=\"#Análise-Exploratória-dos-Dados\" data-toc-modified-id=\"Análise-Exploratória-dos-Dados-6\">Análise Exploratória dos Dados</a></span><ul class=\"toc-item\"><li><span><a href=\"#Colunas-Numéricas\" data-toc-modified-id=\"Colunas-Numéricas-6.1\">Colunas Numéricas</a></span><ul class=\"toc-item\"><li><span><a href=\"#Idade\" data-toc-modified-id=\"Idade-6.1.1\">Idade</a></span></li><li><span><a href=\"#Tarifa-paga\" data-toc-modified-id=\"Tarifa-paga-6.1.2\">Tarifa paga</a></span></li><li><span><a href=\"#Classe-do-passageiro\" data-toc-modified-id=\"Classe-do-passageiro-6.1.3\">Classe do passageiro</a></span></li><li><span><a href=\"#nº-de-familiares\" data-toc-modified-id=\"nº-de-familiares-6.1.4\">nº de familiares</a></span></li></ul></li><li><span><a href=\"#Colunas-categóricas\" data-toc-modified-id=\"Colunas-categóricas-6.2\">Colunas categóricas</a></span><ul class=\"toc-item\"><li><span><a href=\"#Gênero\" data-toc-modified-id=\"Gênero-6.2.1\">Gênero</a></span></li><li><span><a href=\"#Onde-embarcou\" data-toc-modified-id=\"Onde-embarcou-6.2.2\">Onde embarcou</a></span></li></ul></li></ul></li><li><span><a href=\"#Preparando-dados-para-o-modelo\" data-toc-modified-id=\"Preparando-dados-para-o-modelo-7\">Preparando dados para o modelo</a></span></li><li><span><a href=\"#Construção-e-otimização-do-modelo\" data-toc-modified-id=\"Construção-e-otimização-do-modelo-8\">Construção e otimização do modelo</a></span><ul class=\"toc-item\"><li><span><a href=\"#Analisando-resultados\" data-toc-modified-id=\"Analisando-resultados-8.1\">Analisando resultados</a></span></li><li><span><a href=\"#Treinando-o-modelo-com-todos-os-dados\" data-toc-modified-id=\"Treinando-o-modelo-com-todos-os-dados-8.2\">Treinando o modelo com todos os dados</a></span></li></ul></li><li><span><a href=\"#Predição-do-dataset-de-teste\" data-toc-modified-id=\"Predição-do-dataset-de-teste-9\">Predição do dataset de teste</a></span></li><li><span><a href=\"#Resultados-da-predição-do-teste\" data-toc-modified-id=\"Resultados-da-predição-do-teste-10\">Resultados da predição do teste</a></span></li><li><span><a href=\"#Salvando-predições-em-um-arquivo-csv\" data-toc-modified-id=\"Salvando-predições-em-um-arquivo-csv-11\">Salvando predições em um arquivo csv</a></span></li></ul></div>","metadata":{"toc":true}},{"cell_type":"markdown","source":"\n## Introdução\n\nNesse notebook, vou utilizar um algoritmo de regressão logística para prever sobreviventes do acidente do Titanic. Para isso, vou:\n1. Ler e separar os dados em dataset de treino e teste;\n2. Tratar e limpar os dados;\n3. Realizar uma análise exploratória para obter insights e compreender quais features devo utilizar no meu algoritmo;\n4. Treinar o modelo e otimizá-lo;\n5. Prever sobreviventes a partir do dataset de teste e comparar com as respostas reais.\n<br>\n\nVamos lá!\n\n## Descrição das variáveis \n\nSurvival : 0 se não sobreviveu e 1 se sobreviveu\n\nPclass : Classe do quarto do passageiro: 1st = Alta, 2nd = Média, 3rd = Baixa\n\nSibSp : Número de irmãos e cônjuges\n\nParch : Número de pais ou filhos\n\nTicket : Número do ticket\n\nFare : Tarifa do passageiro\n\nCabin : Número da cabine do passageiro\n\nEmbarked: Aonde o passageiro embarcou. C = Cherbourg, Q = Queenstown, S = Southampton\n\nName: nome de passageiro\n\nSex: gênero do passageiro\n\nAge: idade do passageiro","metadata":{}},{"cell_type":"markdown","source":"## Bibliotecas utilizadas","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport plotly.graph_objects as go\nimport plotly.express as px\nfrom plotly.subplots import make_subplots\nimport scipy\nimport sklearn\nimport matplotlib.pyplot as plt","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:44.831511Z","iopub.execute_input":"2022-07-25T14:20:44.831797Z","iopub.status.idle":"2022-07-25T14:20:44.836479Z","shell.execute_reply.started":"2022-07-25T14:20:44.831764Z","shell.execute_reply":"2022-07-25T14:20:44.835663Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Lendo Dados","metadata":{}},{"cell_type":"code","source":"train = pd.read_csv('../input/titanic/train.csv', index_col='PassengerId')\ntest = pd.read_csv('../input/titanic/test.csv')\ntrain.head()","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:44.848334Z","iopub.execute_input":"2022-07-25T14:20:44.849352Z","iopub.status.idle":"2022-07-25T14:20:44.877760Z","shell.execute_reply.started":"2022-07-25T14:20:44.849294Z","shell.execute_reply":"2022-07-25T14:20:44.876882Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.info()","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:44.879128Z","iopub.execute_input":"2022-07-25T14:20:44.879890Z","iopub.status.idle":"2022-07-25T14:20:44.893147Z","shell.execute_reply.started":"2022-07-25T14:20:44.879837Z","shell.execute_reply":"2022-07-25T14:20:44.892079Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"Tamanho do train de treino: \", train.shape)\nprint(\"Tamanho do train de teste: \", test.shape)","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:44.894971Z","iopub.execute_input":"2022-07-25T14:20:44.895807Z","iopub.status.idle":"2022-07-25T14:20:44.906996Z","shell.execute_reply.started":"2022-07-25T14:20:44.895769Z","shell.execute_reply":"2022-07-25T14:20:44.906115Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Análise Exploratória dos Dados","metadata":{}},{"cell_type":"code","source":"cols = list(train.columns)\ncols","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:44.908336Z","iopub.execute_input":"2022-07-25T14:20:44.909055Z","iopub.status.idle":"2022-07-25T14:20:44.920395Z","shell.execute_reply.started":"2022-07-25T14:20:44.909006Z","shell.execute_reply":"2022-07-25T14:20:44.919471Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.info()","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:44.921872Z","iopub.execute_input":"2022-07-25T14:20:44.922094Z","iopub.status.idle":"2022-07-25T14:20:44.938385Z","shell.execute_reply.started":"2022-07-25T14:20:44.922067Z","shell.execute_reply":"2022-07-25T14:20:44.937484Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"É possível verificar que as colunas \"Age\", \"Cabin\" e \"Embarked\" possuem valores nulos. Vou verificar qual percentual de valores nulos para concluir se é interessante substituí-los ou simplesmente remover a coluna em questão.","metadata":{}},{"cell_type":"code","source":"def null_count(train):\n    null_count = train.isnull().sum()\n    null_count = null_count[null_count > 0] / len(train) * 100\n    null_count.sort_values(inplace=True)\n    return null_count\n\nnull_count(train)","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:44.939957Z","iopub.execute_input":"2022-07-25T14:20:44.940331Z","iopub.status.idle":"2022-07-25T14:20:44.951613Z","shell.execute_reply.started":"2022-07-25T14:20:44.940287Z","shell.execute_reply":"2022-07-25T14:20:44.950998Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"\"Cabin\" possue 77.6% de valores nulos, então vou descartá-la. Após analisar individualmente as outras duas colunas vou conseguir concluir qual melhor opção para substituir os valores nulos.","metadata":{}},{"cell_type":"code","source":"cols.remove(\"Cabin\")","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:44.953509Z","iopub.execute_input":"2022-07-25T14:20:44.953989Z","iopub.status.idle":"2022-07-25T14:20:44.962371Z","shell.execute_reply.started":"2022-07-25T14:20:44.953957Z","shell.execute_reply":"2022-07-25T14:20:44.961476Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"num_cols = list(train.select_dtypes(exclude=[\"object\"]).columns) # colunas numéricas\nobj_cols = list(train.select_dtypes(include=[\"object\"]).columns) # colunas não-numéricas\nobj_cols.remove(\"Cabin\")\nnum_cols.remove(\"Survived\")","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:44.963578Z","iopub.execute_input":"2022-07-25T14:20:44.963927Z","iopub.status.idle":"2022-07-25T14:20:44.977107Z","shell.execute_reply.started":"2022-07-25T14:20:44.963899Z","shell.execute_reply":"2022-07-25T14:20:44.976494Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Colunas Numéricas","metadata":{}},{"cell_type":"code","source":"train[num_cols].info()","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:44.978572Z","iopub.execute_input":"2022-07-25T14:20:44.978961Z","iopub.status.idle":"2022-07-25T14:20:44.998254Z","shell.execute_reply.started":"2022-07-25T14:20:44.978930Z","shell.execute_reply":"2022-07-25T14:20:44.996387Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def multiple_plots(df, graph_type, cols=list(train.columns), n_cols=5):\n    \"\"\"Retorna um objeto Figure (plotly) com um gráfico para cada coluna especificada\n    \"\"\"\n    n_rows = int(np.ceil(len(cols) / n_cols))\n    fig = make_subplots(n_rows, n_cols, subplot_titles=cols)\n    \n    i = 1\n    j = 1\n    for i in range(1, n_rows + 1):\n        for j in range(1, n_cols + 1):\n            col = cols[(i - 1) * n_cols + j - 1]\n            if graph_type == 'hist':\n                fig.add_trace(go.Histogram(x=df[col], name=col), row=i, col=j)\n            elif graph_type == 'box':\n                fig.add_trace(go.Box(y=df[col], name=\"\"), row=i, col=j)\n            elif graph_type == 'violin':\n                fig.add_trace(go.Violin(y=df[col], name=\"\"), row=i, col=j)\n                    \n    fig.update_layout(height=400, width=800)\n    return fig\n    \n\nfig = multiple_plots(train, \"box\", num_cols, 5)\nfig.update_layout(title_text=\"Box Plots das colunas numéricas\")\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:45.001369Z","iopub.execute_input":"2022-07-25T14:20:45.002407Z","iopub.status.idle":"2022-07-25T14:20:45.068836Z","shell.execute_reply.started":"2022-07-25T14:20:45.002323Z","shell.execute_reply":"2022-07-25T14:20:45.067963Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"É possível verificar que todas colunas numéricas (menos \"Pclass\") possuem outliers. Vou exibir um histograma para cada coluna para visualizar melhor esses outliers quando comparados com o resto da distribuição.","metadata":{}},{"cell_type":"code","source":"fig = multiple_plots(train, \"hist\", num_cols)\nfig.update_layout(title_text=\"Histogramas das colunas numéricas\")\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:45.070818Z","iopub.execute_input":"2022-07-25T14:20:45.071318Z","iopub.status.idle":"2022-07-25T14:20:45.150407Z","shell.execute_reply.started":"2022-07-25T14:20:45.071274Z","shell.execute_reply":"2022-07-25T14:20:45.149696Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"É possível verificar que em especial \"Fare\" possue muitos outliers. <br>\nAgora, qual a relação entre essas variáveis e a taxa de sobrevivência dos passageiros? Para isso, vou comparar a taxa média de sobrevivência para cada grupo das variáveis em análise.","metadata":{}},{"cell_type":"code","source":"fig = make_subplots(rows=1, cols=5, subplot_titles=num_cols)\n\nfor idx, col in enumerate(num_cols):\n    if col in [\"Age\", \"Fare\"]:\n        grouped_df = train[[col, \"Survived\"]].groupby(col).mean()\n        fig.add_trace(go.Scatter(x=grouped_df.index, y=grouped_df.Survived, name=col, mode=\"markers\"), row=1, col=idx + 1)\n    else:\n        grouped_df = train[[col, \"Survived\"]].groupby(col).mean()\n        fig.add_trace(go.Bar(x=grouped_df.index, y=grouped_df.Survived, name=col), row=1, col=idx + 1)\n    \nfig.update_layout(height=400, width=800, title_text=\"Média da taxa de sobrevivência em relação com cada coluna numérica\")\n\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:45.152500Z","iopub.execute_input":"2022-07-25T14:20:45.153595Z","iopub.status.idle":"2022-07-25T14:20:45.232686Z","shell.execute_reply.started":"2022-07-25T14:20:45.153544Z","shell.execute_reply":"2022-07-25T14:20:45.231864Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Aparentemente, verifica-se uma relação decrescente quanto a taxa de sobrevivência em relação a \"Pclass\", e crescente em relação a \"Parch\". Vou analisar individualmente as colunas para realizar uma análise mais profunda.","metadata":{}},{"cell_type":"markdown","source":"#### Idade","metadata":{}},{"cell_type":"code","source":"fig = px.histogram(train, x=\"Age\", \n                   color=\"Survived\", color_discrete_sequence=[\"#363945\", \"#B6E880\"])\nfig.update_layout(height=400, width=800, title_text=\"Sobrevivência em relação à idade\")\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:45.234750Z","iopub.execute_input":"2022-07-25T14:20:45.235306Z","iopub.status.idle":"2022-07-25T14:20:45.300692Z","shell.execute_reply.started":"2022-07-25T14:20:45.235256Z","shell.execute_reply":"2022-07-25T14:20:45.299866Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Tarifa paga","metadata":{}},{"cell_type":"code","source":"fig = px.histogram(train, x=\"Fare\", color=\"Survived\", nbins=20,\n                   color_discrete_sequence=[\"#363945\", \"#B6E880\"])\nfig.update_layout(height=400, width=800, title_text=\"Sobrevivência em relação à tarifa paga\")\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:45.301863Z","iopub.execute_input":"2022-07-25T14:20:45.302106Z","iopub.status.idle":"2022-07-25T14:20:45.370910Z","shell.execute_reply.started":"2022-07-25T14:20:45.302068Z","shell.execute_reply":"2022-07-25T14:20:45.370016Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = px.box(train, y=\"Fare\", color=\"Survived\", color_discrete_sequence=[\"#363945\", \"#B6E880\"])\nfig.update_layout(height=400, width=800, title_text=\"Sobrevivência em relação à tarifa paga\")\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:45.372390Z","iopub.execute_input":"2022-07-25T14:20:45.372731Z","iopub.status.idle":"2022-07-25T14:20:45.435495Z","shell.execute_reply.started":"2022-07-25T14:20:45.372697Z","shell.execute_reply":"2022-07-25T14:20:45.434380Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Aparentemente, pessoas que pagaram mais caro pela passagem sobreviveram mais. Apesar de haver muitos outliers, estão presentes tanto com \"Survived\" == 1 quanto com \"Survived\" == 0. Mas há um outlier muito extremo (\"Fare\" ~= 512). Vou removê-lo.","metadata":{}},{"cell_type":"code","source":"train = train[train.Fare < 512]","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:45.436998Z","iopub.execute_input":"2022-07-25T14:20:45.437296Z","iopub.status.idle":"2022-07-25T14:20:45.443386Z","shell.execute_reply.started":"2022-07-25T14:20:45.437255Z","shell.execute_reply":"2022-07-25T14:20:45.442472Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = px.box(train, y=\"Fare\", color=\"Survived\", color_discrete_sequence=[\"#363945\", \"#B6E880\"])\nfig.update_layout(height=400, width=800, title_text=\"Sobrevivência em relação à tarifa paga\")\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:45.444771Z","iopub.execute_input":"2022-07-25T14:20:45.445168Z","iopub.status.idle":"2022-07-25T14:20:45.507745Z","shell.execute_reply.started":"2022-07-25T14:20:45.445081Z","shell.execute_reply":"2022-07-25T14:20:45.507151Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Agora ficou mais evidente como aqueles que pagaram mais tiveram uma taxa de sobrevivência maior.","metadata":{}},{"cell_type":"markdown","source":"#### Classe do passageiro","metadata":{}},{"cell_type":"code","source":"fig = px.histogram(train, x=\"Pclass\", color=\"Survived\", color_discrete_sequence=[\"#363945\", \"#B6E880\"])\nfig.update_layout(height=400, width=800, title_text=\"Sobrevivência em relação à classe do passageiro\")\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:45.508656Z","iopub.execute_input":"2022-07-25T14:20:45.509532Z","iopub.status.idle":"2022-07-25T14:20:45.569039Z","shell.execute_reply.started":"2022-07-25T14:20:45.509498Z","shell.execute_reply":"2022-07-25T14:20:45.568142Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"As classes mais altas (1 e 2) apresentaram uma taxa de sobrevivência muito superior comparada a mais baixa (3). Será que há uma relação entre o preço da passagem e a classe do passageiro?","metadata":{}},{"cell_type":"code","source":"fig = px.box(train, x=\"Pclass\", y=\"Fare\")\nfig.update_layout(height=400, width=800, title_text=\"Preço da passagem em relação a classe do passageiro\")\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:45.571318Z","iopub.execute_input":"2022-07-25T14:20:45.571577Z","iopub.status.idle":"2022-07-25T14:20:45.630388Z","shell.execute_reply.started":"2022-07-25T14:20:45.571546Z","shell.execute_reply":"2022-07-25T14:20:45.629450Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Há uma relação muito forte! Não há necessidade então de utilizar ambas colunas. Como \"Pclass\" na realidade é uma variável categórica, vou mantê-la e remover \"Fare\". Mas para isso, preciso alterar o tipo da coluna \"Pclass\" para ser tratada como objeto, e não numérica.","metadata":{}},{"cell_type":"code","source":"train[\"Pclass\"] = train[\"Pclass\"].astype(\"category\")\ncols.remove(\"Fare\")","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:45.631618Z","iopub.execute_input":"2022-07-25T14:20:45.631832Z","iopub.status.idle":"2022-07-25T14:20:45.637593Z","shell.execute_reply.started":"2022-07-25T14:20:45.631807Z","shell.execute_reply":"2022-07-25T14:20:45.636648Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### nº de familiares","metadata":{}},{"cell_type":"code","source":"fig = px.histogram(train, x=\"SibSp\", color=\"Survived\", color_discrete_sequence=[\"#363945\", \"#B6E880\"])\nfig.update_layout(height=400, width=800, title_text=\"Sobrevivência em relação à quantidade de irmãos/cônjuges\")\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:45.639022Z","iopub.execute_input":"2022-07-25T14:20:45.639316Z","iopub.status.idle":"2022-07-25T14:20:45.705241Z","shell.execute_reply.started":"2022-07-25T14:20:45.639286Z","shell.execute_reply":"2022-07-25T14:20:45.704681Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = px.histogram(train, x=\"Parch\", color=\"Survived\", color_discrete_sequence=[\"#363945\", \"#B6E880\"])\nfig.update_layout(height=400, width=800, title_text=\"Sobrevivência em relação à quantidade de pais/filhos\")\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:45.706225Z","iopub.execute_input":"2022-07-25T14:20:45.706884Z","iopub.status.idle":"2022-07-25T14:20:45.772875Z","shell.execute_reply.started":"2022-07-25T14:20:45.706839Z","shell.execute_reply":"2022-07-25T14:20:45.771974Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"As duas variáveis em análise acima possuem um comportamento muito semelhante. Vou adicioná-las em apenas uma coluna que representa o número de familiares.","metadata":{}},{"cell_type":"code","source":"train[\"n_family\"] = train[\"SibSp\"] + train[\"Parch\"]\ncols.remove(\"SibSp\")\ncols.remove(\"Parch\")\ncols.append(\"n_family\")","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:45.774509Z","iopub.execute_input":"2022-07-25T14:20:45.774790Z","iopub.status.idle":"2022-07-25T14:20:45.782073Z","shell.execute_reply.started":"2022-07-25T14:20:45.774744Z","shell.execute_reply":"2022-07-25T14:20:45.781030Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Agora vamos analisar as colunas categóricas.","metadata":{}},{"cell_type":"markdown","source":"### Colunas categóricas","metadata":{}},{"cell_type":"code","source":"train[obj_cols].head()","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:45.783038Z","iopub.execute_input":"2022-07-25T14:20:45.783239Z","iopub.status.idle":"2022-07-25T14:20:45.799839Z","shell.execute_reply.started":"2022-07-25T14:20:45.783214Z","shell.execute_reply":"2022-07-25T14:20:45.799220Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"\"Name\" não é uma coluna categórica, então vou removê-la. Mas observando seu conteúdo, cada passageiro possue um título pelo qual é chamado (\"Mr\", \"Miss\", etc.). Será que esse título tem alguma relação com a taxa de sobrevivência?","metadata":{}},{"cell_type":"code","source":"cols.remove(\"Name\")\nobj_cols.remove(\"Name\")","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:45.800809Z","iopub.execute_input":"2022-07-25T14:20:45.801192Z","iopub.status.idle":"2022-07-25T14:20:45.804683Z","shell.execute_reply.started":"2022-07-25T14:20:45.801165Z","shell.execute_reply":"2022-07-25T14:20:45.803766Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_title(name):\n    name = name.split(\" \")\n    title = name[1]\n    if title in [\"Mr.\", \"Mrs.\", \"Miss.\", \"Master.\"]:\n        return title\n    else:\n        return \"Other\"","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:45.805725Z","iopub.execute_input":"2022-07-25T14:20:45.806152Z","iopub.status.idle":"2022-07-25T14:20:45.816068Z","shell.execute_reply.started":"2022-07-25T14:20:45.806124Z","shell.execute_reply":"2022-07-25T14:20:45.814999Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train[\"title\"] = train.Name.map(get_title)\ntrain.title.value_counts()","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:45.817727Z","iopub.execute_input":"2022-07-25T14:20:45.818349Z","iopub.status.idle":"2022-07-25T14:20:45.831461Z","shell.execute_reply.started":"2022-07-25T14:20:45.818301Z","shell.execute_reply":"2022-07-25T14:20:45.830644Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = px.histogram(train, x=\"title\", color=\"Survived\", color_discrete_sequence=[\"#363945\", \"#B6E880\"])\nfig.update_layout(height=400, width=800, title_text=\"Sobrevivência em relação a como o passageiro é chamado (título)\")\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:45.832551Z","iopub.execute_input":"2022-07-25T14:20:45.833110Z","iopub.status.idle":"2022-07-25T14:20:45.899529Z","shell.execute_reply.started":"2022-07-25T14:20:45.833080Z","shell.execute_reply":"2022-07-25T14:20:45.898824Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Passageiros chamados de \"Mr.\" viveram muito menos do que outros.","metadata":{}},{"cell_type":"code","source":"cols.append(\"title\")","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:45.900607Z","iopub.execute_input":"2022-07-25T14:20:45.900925Z","iopub.status.idle":"2022-07-25T14:20:45.904001Z","shell.execute_reply.started":"2022-07-25T14:20:45.900890Z","shell.execute_reply":"2022-07-25T14:20:45.903494Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train[obj_cols].describe()","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:45.904859Z","iopub.execute_input":"2022-07-25T14:20:45.905450Z","iopub.status.idle":"2022-07-25T14:20:45.928014Z","shell.execute_reply.started":"2022-07-25T14:20:45.905380Z","shell.execute_reply":"2022-07-25T14:20:45.927401Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Analisando a tabela acima, \"Ticket\" possue muitos valores únicos (assim como \"Name\"). Vou removê-la também.","metadata":{}},{"cell_type":"code","source":"cols.remove(\"Ticket\") # too many unique values","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:45.928899Z","iopub.execute_input":"2022-07-25T14:20:45.929632Z","iopub.status.idle":"2022-07-25T14:20:45.934044Z","shell.execute_reply.started":"2022-07-25T14:20:45.929593Z","shell.execute_reply":"2022-07-25T14:20:45.932984Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Gênero","metadata":{}},{"cell_type":"code","source":"fig = px.histogram(train, x=\"Sex\", color=\"Survived\", color_discrete_sequence=[\"#363945\", \"#B6E880\"])\nfig.update_layout(height=400, width=800, title_text=\"Sobrevivência por gênero\")\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:45.935274Z","iopub.execute_input":"2022-07-25T14:20:45.936198Z","iopub.status.idle":"2022-07-25T14:20:46.003620Z","shell.execute_reply.started":"2022-07-25T14:20:45.936163Z","shell.execute_reply":"2022-07-25T14:20:46.003037Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"É evidente que mulheres sobreviveram muito mais que homens. Aparentemente gênero é uma feature muito importante para a predição de sobrevivência de um passageiro.","metadata":{}},{"cell_type":"markdown","source":"#### Onde embarcou","metadata":{}},{"cell_type":"code","source":"fig = px.histogram(train, x=\"Embarked\", color=\"Survived\", color_discrete_sequence=[\"#363945\", \"#B6E880\"])\nfig.update_layout(height=400, width=800, title_text=\"Sobrevivência por porto de embarque\")\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:46.004558Z","iopub.execute_input":"2022-07-25T14:20:46.005370Z","iopub.status.idle":"2022-07-25T14:20:46.071269Z","shell.execute_reply.started":"2022-07-25T14:20:46.005322Z","shell.execute_reply":"2022-07-25T14:20:46.070465Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Pessoas que embarcaram em Southampton sobreviveram com menos frequência.","metadata":{}},{"cell_type":"markdown","source":"## Preparando dados para o modelo","metadata":{}},{"cell_type":"code","source":"cols.remove(\"Survived\")","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:46.072530Z","iopub.execute_input":"2022-07-25T14:20:46.072755Z","iopub.status.idle":"2022-07-25T14:20:46.076610Z","shell.execute_reply.started":"2022-07-25T14:20:46.072729Z","shell.execute_reply":"2022-07-25T14:20:46.075765Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train[cols].head()","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:46.077746Z","iopub.execute_input":"2022-07-25T14:20:46.078004Z","iopub.status.idle":"2022-07-25T14:20:46.097391Z","shell.execute_reply.started":"2022-07-25T14:20:46.077969Z","shell.execute_reply":"2022-07-25T14:20:46.096793Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cat_cols = [\"Sex\", \"Embarked\", \"title\"]\nnum_cols = [\"n_family\", \"Pclass\", \"Age\"]\n\nX = train[cols]\ny = train[\"Survived\"]","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:46.098478Z","iopub.execute_input":"2022-07-25T14:20:46.098993Z","iopub.status.idle":"2022-07-25T14:20:46.104820Z","shell.execute_reply.started":"2022-07-25T14:20:46.098959Z","shell.execute_reply":"2022-07-25T14:20:46.103813Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.pipeline import Pipeline\nfrom sklearn.preprocessing import OrdinalEncoder, OneHotEncoder, StandardScaler\nfrom sklearn.compose import ColumnTransformer\nfrom sklearn.impute import SimpleImputer\n\ncat_pipe = Pipeline([\n    ('imputer', SimpleImputer(strategy=\"most_frequent\")), # substituir valores nulos de \"Embarked\" pelo mais frequente\n    ('encoder', OneHotEncoder(handle_unknown=\"ignore\")),\n])\n\nnum_pipe = Pipeline([\n    ('imputer', SimpleImputer(strategy=\"median\")), # substituir valores nulos de \"Age\" pela mediana por ter uma\n    ('scaler', StandardScaler())                   # distribuição assimétrica\n])\n\ndata_prep_pipe = ColumnTransformer([\n    (\"cat_cols\", cat_pipe, cat_cols),\n    (\"num_cols\", num_pipe, num_cols)\n])\n\nX_prep = data_prep_pipe.fit_transform(X)\nX_prep.shape","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:46.109767Z","iopub.execute_input":"2022-07-25T14:20:46.110226Z","iopub.status.idle":"2022-07-25T14:20:46.137076Z","shell.execute_reply.started":"2022-07-25T14:20:46.110189Z","shell.execute_reply":"2022-07-25T14:20:46.136404Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Construção e otimização do modelo\nPara otimizar o algoritmo de regressão logística, utilizarei o método GridSearchCV para procurar os parâmetros optimos para o modelo. Mas antes, como a performance deve ser mensurada? Por se tratar de um problema de classificação, a primeira métrica que vem em mente é calcular simplesmente a precisão. Entretanto, por se tratar de um dataset não-balanceado (há muito mais não-sobreviventes do que sobreviventes do acidente), otimizar o modelo a partir dessa métrica pode fazer com que ele se torne muito bom em prever a classe mais frequente (0), mas não a classe menos frequente, e mesmo assim apresentar uma precisão alta. Para isso, utilizarei como métrica de otimização o \"F1 score\", que leva em consideração a quantidade de falsos positivos e negativos.","metadata":{}},{"cell_type":"code","source":"print(\"Percentual de sobreviventes e mortos:\")\ny.value_counts(normalize=True)","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:46.137997Z","iopub.execute_input":"2022-07-25T14:20:46.138679Z","iopub.status.idle":"2022-07-25T14:20:46.147009Z","shell.execute_reply.started":"2022-07-25T14:20:46.138644Z","shell.execute_reply":"2022-07-25T14:20:46.146389Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.linear_model import LogisticRegression\nfrom sklearn.model_selection import cross_val_score, cross_val_predict, GridSearchCV\nfrom sklearn.metrics import confusion_matrix, roc_auc_score, roc_curve, f1_score, mean_absolute_error, accuracy_score","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:46.148213Z","iopub.execute_input":"2022-07-25T14:20:46.148465Z","iopub.status.idle":"2022-07-25T14:20:46.158718Z","shell.execute_reply.started":"2022-07-25T14:20:46.148435Z","shell.execute_reply":"2022-07-25T14:20:46.157791Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"params_dist = {\"random_state\": [42], \n                \"solver\": [\"lbfgs\", \"liblinear\"],\n                \"C\" : [100, 10, 1.0, 0.1, 0.01],\n                }","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:46.159858Z","iopub.execute_input":"2022-07-25T14:20:46.160071Z","iopub.status.idle":"2022-07-25T14:20:46.175349Z","shell.execute_reply.started":"2022-07-25T14:20:46.160044Z","shell.execute_reply":"2022-07-25T14:20:46.174571Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = LogisticRegression(random_state=42)\ngrid = GridSearchCV(model, params_dist, cv=10, scoring=\"f1\")\ngrid.fit(X_prep, y)\npreds = grid.predict(X_prep)\nprint(f\"Melhores parâmetros: {grid.best_params_}\\nMelhor resultado: {grid.best_score_}\\n\")","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:46.176544Z","iopub.execute_input":"2022-07-25T14:20:46.177183Z","iopub.status.idle":"2022-07-25T14:20:47.529856Z","shell.execute_reply.started":"2022-07-25T14:20:46.177147Z","shell.execute_reply":"2022-07-25T14:20:47.528966Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"best_model = LogisticRegression(**grid.best_params_)\ntrain_preds = cross_val_predict(best_model, X_prep, y, cv=50)","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:47.531096Z","iopub.execute_input":"2022-07-25T14:20:47.531644Z","iopub.status.idle":"2022-07-25T14:20:48.650403Z","shell.execute_reply.started":"2022-07-25T14:20:47.531599Z","shell.execute_reply":"2022-07-25T14:20:48.649498Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Analisando resultados","metadata":{}},{"cell_type":"code","source":"roc_auc = roc_auc_score(y, train_preds)\nmae = mean_absolute_error(y, train_preds)\nf1 = f1_score(y, train_preds)\n\nprint(f\"ROC AUC: {roc_auc:.3f}\")\nprint(f\"MAE: {mae:.3f}\")\nprint(f\"F1: {f1:.3f}\")","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:48.656038Z","iopub.execute_input":"2022-07-25T14:20:48.659592Z","iopub.status.idle":"2022-07-25T14:20:48.679632Z","shell.execute_reply.started":"2022-07-25T14:20:48.659499Z","shell.execute_reply":"2022-07-25T14:20:48.678651Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay\n\ncm = confusion_matrix(y, preds, normalize='true', labels=[0,1])\ndisp = ConfusionMatrixDisplay(confusion_matrix=cm,\n                              display_labels=[0, 1])\ndisp.plot() \nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:48.681319Z","iopub.execute_input":"2022-07-25T14:20:48.681847Z","iopub.status.idle":"2022-07-25T14:20:48.917646Z","shell.execute_reply.started":"2022-07-25T14:20:48.681799Z","shell.execute_reply":"2022-07-25T14:20:48.917027Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fpr, tpr, thresholds = roc_curve(y, train_preds)","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:48.918743Z","iopub.execute_input":"2022-07-25T14:20:48.919100Z","iopub.status.idle":"2022-07-25T14:20:48.923646Z","shell.execute_reply.started":"2022-07-25T14:20:48.919057Z","shell.execute_reply":"2022-07-25T14:20:48.922801Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_roc_curve(fpr, tpr, label=None):\n    plt.plot(fpr, tpr, linewidth=2, label=label)\n    plt.plot([0, 1], [0, 1], 'k--')\n    plt.axis([0, 1, 0, 1])\n    plt.xlabel('False Positive Rate')\n    plt.ylabel('True Positive Rate')\n    \nplot_roc_curve(fpr, tpr)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:48.924761Z","iopub.execute_input":"2022-07-25T14:20:48.924970Z","iopub.status.idle":"2022-07-25T14:20:49.106665Z","shell.execute_reply.started":"2022-07-25T14:20:48.924944Z","shell.execute_reply":"2022-07-25T14:20:49.105959Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"A partir das métricas e gráficos acima, é possível observar que apesar de o modelo apresentar uma precisão maior quanto a predição da classe 0 (90% de precisão), também apresentou uma alta eficiência ao prever a classe 1 (74% de precisão).","metadata":{}},{"cell_type":"markdown","source":"### Treinando o modelo com todos os dados","metadata":{}},{"cell_type":"code","source":"full_model = LogisticRegression(**grid.best_params_)\nfull_model.fit(X_prep, y)","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:49.107718Z","iopub.execute_input":"2022-07-25T14:20:49.108043Z","iopub.status.idle":"2022-07-25T14:20:49.137601Z","shell.execute_reply.started":"2022-07-25T14:20:49.108016Z","shell.execute_reply":"2022-07-25T14:20:49.136633Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Predição do dataset de teste","metadata":{}},{"cell_type":"code","source":"X_test = test.copy()\nX_test[\"n_family\"] = X_test[\"SibSp\"] + X_test[\"Parch\"]\nX_test[\"title\"] = X_test.Name.map(get_title)\nX_test[\"Pclass\"] = X_test[\"Pclass\"].astype(\"category\")\nX_test = X_test[cols]","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:49.139372Z","iopub.execute_input":"2022-07-25T14:20:49.139959Z","iopub.status.idle":"2022-07-25T14:20:49.156665Z","shell.execute_reply.started":"2022-07-25T14:20:49.139908Z","shell.execute_reply":"2022-07-25T14:20:49.155671Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X_test_prep = data_prep_pipe.transform(X_test)\ntest_preds = full_model.predict(X_test_prep)","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:20:49.158369Z","iopub.execute_input":"2022-07-25T14:20:49.158923Z","iopub.status.idle":"2022-07-25T14:20:49.177482Z","shell.execute_reply.started":"2022-07-25T14:20:49.158866Z","shell.execute_reply":"2022-07-25T14:20:49.176522Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Salvando predições em um arquivo csv","metadata":{}},{"cell_type":"code","source":"# Saving the output for submission\noutput = pd.DataFrame({'PassengerId': test.index, 'Survived':test_preds})\noutput.to_csv('my_submission.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2022-07-25T14:22:00.277778Z","iopub.execute_input":"2022-07-25T14:22:00.278454Z","iopub.status.idle":"2022-07-25T14:22:00.287086Z","shell.execute_reply.started":"2022-07-25T14:22:00.278392Z","shell.execute_reply":"2022-07-25T14:22:00.286472Z"},"trusted":true},"execution_count":null,"outputs":[]}]}