Skip to content

Instantly share code, notes, and snippets.

@rafaelvareto
Last active February 22, 2024 15:02
Show Gist options
  • Save rafaelvareto/21aa689b739f498872962cd92936cdb9 to your computer and use it in GitHub Desktop.
Save rafaelvareto/21aa689b739f498872962cd92936cdb9 to your computer and use it in GitHub Desktop.
21_02-logistic-regression.ipynb
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"<a href=\"https://colab.research.google.com/gist/rafaelvareto/21aa689b739f498872962cd92936cdb9/21_02-logistic-regression.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "l2ZdhIazr6sO"
},
"source": [
"# CIAG 2024 - Regressão Logística\n",
"\n",
"## Preâmbulo\n",
"\n",
"O código abaixo consiste dos imports comuns. Além do mais, configuramos as imagens para ficar de um tamanho aceitável e criamos algumas funções auxiliares.\n",
"No geral, você pode ignorar a próxima célula."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "Gk2LpsyrqVYk"
},
"outputs": [],
"source": [
"import numpy as np\n",
"import torch\n",
"import torch.optim as optim\n",
"import matplotlib.pyplot as plt\n",
"\n",
"from sklearn.datasets import make_blobs"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "cxaonZmlr-Mc"
},
"outputs": [],
"source": [
"plt.rcParams['figure.figsize'] = (8, 5)\n",
"\n",
"plt.rcParams['axes.axisbelow'] = True\n",
"plt.rcParams['axes.labelsize'] = 16\n",
"plt.rcParams['axes.linewidth'] = 1\n",
"plt.rcParams['axes.spines.bottom'] = True\n",
"plt.rcParams['axes.spines.left'] = True\n",
"plt.rcParams['axes.titlesize'] = 16\n",
"plt.rcParams['axes.ymargin'] = 0.1\n",
"\n",
"plt.rcParams['font.family'] = 'serif'\n",
"\n",
"plt.rcParams['axes.grid'] = True\n",
"plt.rcParams['grid.color'] = 'lightgrey'\n",
"plt.rcParams['grid.linewidth'] = .1\n",
"\n",
"plt.rcParams['xtick.labelsize'] = 16\n",
"plt.rcParams['xtick.bottom'] = True\n",
"plt.rcParams['xtick.direction'] = 'out'\n",
"plt.rcParams['xtick.major.size'] = 10\n",
"plt.rcParams['xtick.major.width'] = 1\n",
"plt.rcParams['xtick.minor.size'] = 3\n",
"plt.rcParams['xtick.minor.width'] = .5\n",
"plt.rcParams['xtick.minor.visible'] = True\n",
"\n",
"plt.rcParams['ytick.labelsize'] = 16\n",
"plt.rcParams['ytick.left'] = True\n",
"plt.rcParams['ytick.direction'] = 'out'\n",
"plt.rcParams['ytick.major.size'] = 10\n",
"plt.rcParams['ytick.major.width'] = 1\n",
"plt.rcParams['ytick.minor.size'] = 3\n",
"plt.rcParams['ytick.minor.width'] = .5\n",
"plt.rcParams['ytick.minor.visible'] = True\n",
"\n",
"plt.rcParams['legend.fontsize'] = 16\n",
"\n",
"plt.rcParams['lines.linewidth'] = 4\n",
"plt.rcParams['lines.markersize'] = 10\n",
"\n",
"plt.style.use('tableau-colorblind10')\n",
"plt.ion()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "rZIarhsdsA7D"
},
"source": [
"## Criando 2 classes linearmente separáveis\n",
"\n",
"Dando continuidade aos experimentos com classificação e regressão, vamos trabalhar hoje com um dos métodos mais tradicionais em aprendizado de máquina: Regressão Linear (Linear Regression).\n",
"\n",
"Primeiramente, vamos gerar duas classes de forma aleatória de forma que sabemos de antemão que podem ser separados linearmente."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "0rcP_88zr_UK"
},
"outputs": [],
"source": [
"random_seed = 2024\n",
"\n",
"features, labels = make_blobs(n_samples=5000, random_state=random_seed, centers=2)\n",
"\n",
"print('Feature samples:', type(features), features.shape)\n",
"print('Label samples:', type(labels), labels.shape)\n",
"\n",
"for (x_,y_) in zip(features[:5],labels[:5]):\n",
" print(x_, y_)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "FNc2NuQJsCrC"
},
"outputs": [],
"source": [
"plt.Figure(figsize=(8, 9))\n",
"plt.scatter(features[:,0], features[:,1], c=labels.ravel(), edgecolor='w', alpha=0.75)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"source": [
"## Mapeando eixo X ao eixo Y com SKLEARN e Regressão Lienar\n",
"\n",
"Será que encontramos uma maneira de ajudar uma reta de forma que conseguimos minimizar a soma do quadrado das diferenças?"
],
"metadata": {
"id": "3i7iJEFthfYF"
}
},
{
"cell_type": "code",
"source": [
"from sklearn.linear_model import LinearRegression\n",
"from sklearn.model_selection import train_test_split"
],
"metadata": {
"id": "mD3AD-cRhngV"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "bCJuIoOrU1rF"
},
"source": [
"Assim como na aula anterior, **divida sua base de dados em partições treino/teste** de forma que 70% das amostras estejam no conjunto de treino e o restante no conjunto de teste."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "fu0ADijzV3LW"
},
"outputs": [],
"source": [
"# Implemente aqui a sua solução\n",
"feat_train, feat_test, lbl_train, lbl_test = # executar train_test_split aqui\n",
"\n",
"print(feat_train.shape, feat_test.shape)"
]
},
{
"cell_type": "markdown",
"source": [
"Se desejamos mapear os valores do eixo X para um valor correspondente no eixo Y, precisaremos, por enquanto, descartar os labels gerados pela função `make_blobs`."
],
"metadata": {
"id": "M_jUE_fpiYUC"
}
},
{
"cell_type": "code",
"source": [
"x_axis, y_axis = feat_train[:,0].reshape(-1,1), feat_train[:,1].reshape(-1,1)\n",
"x_axis_, y_axis_ = feat_test[:,0].reshape(-1,1), feat_test[:,1].reshape(-1,1)"
],
"metadata": {
"id": "K1HgL4QvizJA"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"Agora utilizando a classe LinearRegression(), crie um objeto que será responsável em se ajustar as amostras linearmente. Você pode chamar esse objeto de linearR e visualizar os coeficientes e o valor do intercepto imprimindo os seguintes atributos: `coef_` e `intercept_`."
],
"metadata": {
"id": "ouN9Y16li9Tq"
}
},
{
"cell_type": "code",
"source": [
"# API: https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LinearRegression.html\n",
"\n",
"# Implemente aqui a sua solução\n",
"linearR = None\n",
"\n",
"print(linearR.coef_, linearR.intercept_)"
],
"metadata": {
"id": "yMWhKyQAi68O"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"# Visualize a reta que separa ambas as classes\n",
"def get_line(x, a, b=0):\n",
" # Equacao reduzida da reta\n",
" return (a[0] * x) + b\n",
"\n",
"x_line = np.linspace(-10, 7, 100)\n",
"y_line = get_line(x_line, linearR.coef_, linearR.intercept_)\n",
"\n",
"plt.Figure(figsize=(8, 9))\n",
"plt.scatter(feat_train[:,0], feat_train[:,1], c=lbl_train.ravel(), edgecolor='w', alpha=0.75)\n",
"plt.plot(x_line, y_line)\n",
"plt.xlabel('X-axis')\n",
"plt.ylabel('Y-axis')\n",
"plt.show()"
],
"metadata": {
"id": "UfuILjoaktbg"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"Abaixo você pode visualizar a predição para as 10 primeiras amostras do teste utilizando a função `predict`. Implemente a mesma funcão realizando o produto interno (`linearR.coef_`) seguido pela soma do intercepto (`linearR.intercept_`) e verifique se os resultados alcançados são os mesmos."
],
"metadata": {
"id": "9AyTbQ1-lXXg"
}
},
{
"cell_type": "code",
"source": [
"y_pred = linearR.predict(x_axis_)\n",
"print(y_pred[:10].ravel())\n",
"\n",
"# Implemente aqui a sua solução\n",
"y_pred = None\n",
"print(y_pred[:10].ravel())"
],
"metadata": {
"id": "AGfzbBZfl7NV"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"Agora que você já treinou seu modelo, valide seu resultado utilizando o método `score` com as amostras reservadas para teste e gere um novo gráfico com os resultados."
],
"metadata": {
"id": "j5Ud0kQmnG4q"
}
},
{
"cell_type": "code",
"source": [
"# Implemente aqui a sua solução\n",
"score = None\n",
"print(score)"
],
"metadata": {
"id": "SJzWlfxbnGbx"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"Vamos computar o *overall_score* $S$ manualmente. Para isso, precisamos calcular a soma dos quadrados residuais $u = \\sum(y_{true} - y_{pred})^2$ e dividi-la pela soma total das diferenças $v = \\sum(y_{true} - \\bar{y}_{true})^2$ de tal forma que $S = 1 - \\frac{u}{v}$."
],
"metadata": {
"id": "L37UH0KCoJLP"
}
},
{
"cell_type": "code",
"source": [
"# Implemente aqui a sua solução\n",
"y_pred = linearR.predict(x_axis_)\n",
"score = None\n",
"print(score)"
],
"metadata": {
"id": "lPlIv8UkqW5U"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "_neyKTiJVnhE"
},
"source": [
"## Trabalhando com SKLEARN e Regressão Linear"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "zW-VamNUWY76"
},
"source": [
"Agora utilizando a classe **LinearRegression()**, crie um objeto que será responsável em separar as amostras linearmente. Você pode chamar esse objeto de *linearR* e visualizar os coeficientes e o valor do intercepto imprimindo os seguintes atributos: *coef_* e *intercept_*."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "CNxmScFyU0oI"
},
"outputs": [],
"source": [
"# API: https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LinearRegression.html\n",
"\n",
"# Implemente aqui a sua solução\n",
"linearR = None\n",
"\n",
"print(linearR.coef_, linearR.intercept_)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "LrJAGSzHYD2d"
},
"outputs": [],
"source": [
"# Visualize o plano que separa ambas as classes\n",
"def get_plane(x1, x2, a, b=0):\n",
" return (a[0] * x1) + (a[1] * x2) + b\n",
"\n",
"x_line, y_line = np.meshgrid(np.linspace(-10, 7, 100), np.linspace(-15, 10, 100))\n",
"plane_eq = get_plane(x_line, y_line, linearR.coef_, linearR.intercept_)\n",
"\n",
"fig = plt.figure(figsize=(16, 9))\n",
"\n",
"ax = fig.add_subplot(121, projection='3d')\n",
"ax.view_init(elev=15, azim=130, roll=0)\n",
"ax.scatter(feat_train[:,0], feat_train[:,1], c=lbl_train.ravel(), edgecolor='w', alpha=0.75)\n",
"ax.plot_surface(x_line, y_line, plane_eq, color='r', alpha=0.15)\n",
"\n",
"ax = fig.add_subplot(122, projection='3d')\n",
"ax.view_init(elev=5, azim=180, roll=0)\n",
"ax.scatter(feat_train[:,0], feat_train[:,1], c=lbl_train.ravel(), edgecolor='w', alpha=0.75)\n",
"ax.plot_surface(x_line, y_line, plane_eq, color='r', alpha=0.15)\n",
"\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "S2wa8a_Qe3IH"
},
"source": [
"Agora que você já treinou seu modelo, valide seu resultado com as amostras reservadas para teste e gere um novo gráfico com os resultados."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "7aN-dfeJe3aE"
},
"outputs": [],
"source": [
"# Implemente aqui a sua solução\n",
"score = None\n",
"print(score)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "p3n6_c0sf2MS"
},
"outputs": [],
"source": [
"x_line, y_line = np.meshgrid(np.linspace(-10, 7, 100), np.linspace(-15, 10, 100))\n",
"plane_eq = get_plane(x_line, y_line, linearR.coef_, linearR.intercept_)\n",
"\n",
"fig = plt.figure(figsize=(16, 9))\n",
"\n",
"ax = fig.add_subplot(121, projection='3d')\n",
"ax.view_init(elev=15, azim=130, roll=0)\n",
"ax.scatter(feat_test[:,0], feat_test[:,1], c=lbl_test.ravel(), edgecolor='w', alpha=0.75)\n",
"ax.plot_surface(x_line, y_line, plane_eq, color='r', alpha=0.15)\n",
"\n",
"ax = fig.add_subplot(122, projection='3d')\n",
"ax.view_init(elev=5, azim=180, roll=0)\n",
"ax.scatter(feat_test[:,0], feat_test[:,1], c=lbl_test.ravel(), edgecolor='w', alpha=0.75)\n",
"ax.plot_surface(x_line, y_line, plane_eq, color='r', alpha=0.15)\n",
"\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "H3DxU0gfhgSW"
},
"source": [
"## Trabalhando com SKLEARN e Regressão Logística\n",
"\n",
"Utilizando os mesmos conjuntos de dados (mesma repartição), repita todo o processo acima, mas desta vez trabalhando com a Regressão Logística. Voce pode chamar seu modelo de *logR*, inicialmente recebendo o valor None."
]
},
{
"cell_type": "code",
"source": [
"from sklearn.linear_model import LogisticRegression\n",
"\n",
"def sigmoid(x):\n",
" return 1 / (1 + np.exp(-x))"
],
"metadata": {
"id": "jQjslf1ih8eU"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "9o4ayPEIhfeG"
},
"outputs": [],
"source": [
"# API: https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegression.html\n",
"\n",
"# Implemente aqui a sua solução\n",
"logR = None\n",
"\n",
"print(logR.coef_, logR.intercept_)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "CzRE_-8YhveE"
},
"outputs": [],
"source": [
"# Visualize o plano que separa ambas as classes\n",
"def get_plane(x1, x2, a, b=0):\n",
" return (a[0,0] * x1) + (a[0,1] * x2) + b\n",
"\n",
"x_line, y_line = np.meshgrid(np.linspace(-5, 7, 100), np.linspace(-15, 10, 100))\n",
"plane_eq = get_plane(x_line, y_line, logR.coef_, logR.intercept_)\n",
"\n",
"fig = plt.figure(figsize=(16, 9))\n",
"\n",
"ax = fig.add_subplot(121, projection='3d')\n",
"ax.view_init(elev=15, azim=130, roll=0)\n",
"ax.scatter(feat_train[:,0], feat_train[:,1], c=lbl_train.ravel(), edgecolor='w', alpha=0.75)\n",
"ax.plot_surface(x_line, y_line, plane_eq, color='r', alpha=0.15)\n",
"\n",
"ax = fig.add_subplot(122, projection='3d')\n",
"ax.view_init(elev=5, azim=180, roll=0)\n",
"ax.scatter(feat_train[:,0], feat_train[:,1], c=lbl_train.ravel(), edgecolor='w', alpha=0.75)\n",
"ax.plot_surface(x_line, y_line, plane_eq, color='r', alpha=0.15)\n",
"\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "oTlCRCVGkuUL"
},
"source": [
"Agora que você já treinou seu modelo, valide seu resultado com as amostras reservadas para teste e gere um novo gráfico com os resultados."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "YVVxLp5gkkP6"
},
"outputs": [],
"source": [
"# Implemente aqui a sua solução\n",
"score = None\n",
"print(score)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "6l4rl2HLk07T"
},
"outputs": [],
"source": [
"x_line, y_line = np.meshgrid(np.linspace(-10, 7, 100), np.linspace(-15, 10, 100))\n",
"plane_eq = get_plane(x_line, y_line, logR.coef_, logR.intercept_)\n",
"\n",
"fig = plt.figure(figsize=(16, 9))\n",
"\n",
"ax = fig.add_subplot(121, projection='3d')\n",
"ax.view_init(elev=15, azim=130, roll=0)\n",
"ax.scatter(feat_train[:,0], feat_train[:,1], c=lbl_train.ravel(), edgecolor='w', alpha=0.75)\n",
"ax.plot_surface(x_line, y_line, plane_eq, color='r', alpha=0.15)\n",
"\n",
"ax = fig.add_subplot(122, projection='3d')\n",
"ax.view_init(elev=5, azim=180, roll=0)\n",
"ax.scatter(feat_train[:,0], feat_train[:,1], c=lbl_train.ravel(), edgecolor='w', alpha=0.75)\n",
"ax.plot_surface(x_line, y_line, plane_eq, color='r', alpha=0.15)\n",
"\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "sCThIxd2sOfi"
},
"source": [
"## Trabalhando com PYTORCH e Regressão Logística\n",
"\n",
"A partir daqui será um pouco diferente, pois ao invés de utilizarmos a biblioteca **SCIKIT-LEARN (SKLEARN)** para resolver nosso problema de regressão, iremos implementar nossa solução utilizando uma pequena rede neural através do framework **PyTORCH**\n",
"\n",
"### Criando parâmetros para implementação da regressão logística\n",
"No bloco abaixo vamos inicializar os pesos de nossa rede, contendo três parâmetros somente, um para cada dimensão dos dados de entrada e mais um para armazenar o intercepto. Perceba que os pesos foram inicializados de forma aleatória."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "OPOYVelLsD_S"
},
"outputs": [],
"source": [
"torch.manual_seed(random_seed)\n",
"\n",
"# Note que colocaremos o intercepto dentro da matriz de pesos w\n",
"W = torch.randn(size=(3, 1), dtype=torch.float64, requires_grad=True)\n",
"print('Weight matrix:', W)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "M6dfnRqLoYsV"
},
"source": [
"No bloco abaixo, precisamos adicionar uma nova dimensão aos dados de entrada para que possa multiplicar o intercepto da matriz de pesos W (weights) definida acima."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "h7DLXPLctcP8"
},
"outputs": [],
"source": [
"# Com isso, teremos que adicionar o intercepto também nos dados\n",
"def add_intercept(X) -> np.ndarray:\n",
" X_new = np.zeros(shape=(X.shape[0], X.shape[1] + 1))\n",
" X_new[:, 0] = 1\n",
" X_new[:, 1:] = X\n",
"\n",
" return X_new\n",
"\n",
"if features.shape[1] == 2:\n",
" features = add_intercept(features)\n",
"print('Features shape:', features.shape)\n",
"print('Features example:', features[0])"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "t_34e_BixCv1"
},
"source": [
"Para que tudo funcione apropriadamente, temos que converter todos os vetores do tipo array em tensores torch"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "6HutcEqbuSYE"
},
"outputs": [],
"source": [
"print(f'ANTES | Features type: {type(features)} | Labels type: {type(labels)}')\n",
"features = torch.from_numpy(features)\n",
"labels = torch.from_numpy(labels)\n",
"print(f'DEPOIS | Features type: {type(features)} | Labels type: {type(labels)}')"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "jUqNXY8p0jzc"
},
"source": [
"### Definindo nosso modelo de regressão logística\n",
"\n",
"- Definição da saída do modelo, seguindo a seguinte fórmula: $\\hat{y} = \\sigma(\\textbf{w}^\\text{T}\\textbf{x}) $.\n",
"- A função $\\sigma$, também chamada de função de ativação, será uma função logística, assumindo o seguinte formato: $\\sigma(z) = \\dfrac{1}{1 + \\exp(-z)}$.\n",
"- A função logística, nesse caso uma _sigmoid_, faz com que a saída seja um valor entre $[0, 1]$, em outras palavras a probabilidade $\\mathbb{P}(y = 1)$."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "B8V3Wilr0jKk"
},
"outputs": [],
"source": [
"def model(\n",
" X: torch.tensor,\n",
" W: torch.tensor\n",
"):\n",
" def sigmoid(z: torch.tensor):\n",
" return 1 / (1 + torch.exp(-z))\n",
"\n",
" # O produto escalar resulta em um vetor (n, 1), faremos squeeze para tirar a segunda dimensão que é desnecessária\n",
" return sigmoid(X @ W).squeeze(dim=1)\n",
"\n",
"print('First 5 labels:', labels[:5])\n",
"print('First 5 predictions:', model(features, W)[:5])"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "twafN-Q2y-31"
},
"source": [
"### Definindo nossa função de risco\n",
"Definindo nossa função de custo (risco) para informar o quanto o modelo está errando:\n",
"\n",
"- Definição da função de risco, seguindo a seguinte fórmula:\n",
"$ \\mathcal{L} = - \\frac{1}{n} \\sum\\limits_{i=1}^n y \\ln(\\hat{y}) + (1 - y)\\ln(1 - \\hat{y}) $.\n",
"- Essa função de risco recebe o nome de ___negative log-likelihood___ ou também de ___binary cross entropy___."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "1iph19DSy8jE"
},
"outputs": [],
"source": [
"def cross_entropy(\n",
" y_pred: torch.tensor,\n",
" y: torch.tensor\n",
"):\n",
" return - torch.mean(y * torch.log(y_pred) + (1 - y) * torch.log(1 - y_pred))\n",
"\n",
"lbl_pred = model(features, W)\n",
"loss = cross_entropy(lbl_pred, labels)\n",
"print('Loss value:', loss) # Perceba que retorna o valor da função de risco e também a derivada associada no parâmetro grad_fn"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "1ArRFtcJ4EUJ"
},
"source": [
"Otimizando os parâmetros do modelo através de um _loop_ de treinamento padrão do PyTorch."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "TYWtTpkD3LAM"
},
"outputs": [],
"source": [
"# Definindo hiperarâmetros\n",
"n_iters = 100\n",
"learning_rate = 0.01\n",
"\n",
"# Definindo o otimizador a ser utilizado (SGD - Stochastic Gradient Descent)\n",
"optimizer = optim.SGD((W, ), lr=learning_rate)\n",
"\n",
"# Realizando o loop de treinamento\n",
"for i in range(n_iters):\n",
" optimizer.zero_grad() # Passo necessário no PyTorch, sem ele o treinamento não dará certo\n",
"\n",
" # Computando as derivadas e dando um passo na otimização\n",
" lbl_preds = model(features, W)\n",
" loss = cross_entropy(lbl_preds, labels)\n",
" loss.backward()\n",
" optimizer.step()\n",
"\n",
" # Printando a performance do modelo\n",
" if (i+1) % 10 == 0:\n",
" print(f'iter {i+1}/{n_iters} => {loss.item():.5f}')"
]
},
{
"cell_type": "markdown",
"source": [
"Para visualize os parametros (coeficientes) finais de sua rede neural, basta exibi-los após realizar o trainamento."
],
"metadata": {
"id": "i88g1W1p9eKg"
}
},
{
"cell_type": "code",
"source": [
"print(W)"
],
"metadata": {
"id": "-uOD_IiJ9zgq"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "7wbhW19a4xZb"
},
"source": [
"Verificando o separador linear encontrado pelo nosso modelo."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "uW3mnMiE5qpe"
},
"outputs": [],
"source": [
"# Visualize o plano que separa ambas as classes\n",
"def get_plane(x1, x2, w):\n",
" return (w[1,0] * x1) + (w[2,0] * x2) + w[0,0]\n",
"\n",
"x_line, y_line = np.meshgrid(np.linspace(-5, 7, 100), np.linspace(-15, 10, 100))\n",
"plane_eq = get_plane(x_line, y_line, W.detach().numpy())\n",
"\n",
"fig = plt.figure(figsize=(16, 9))\n",
"\n",
"ax = fig.add_subplot(121, projection='3d')\n",
"ax.view_init(elev=15, azim=130, roll=0)\n",
"ax.scatter(features[:,1], features[:,2], c=labels.ravel(), edgecolor='w', alpha=0.75)\n",
"ax.plot_surface(x_line, y_line, plane_eq, color='r', alpha=0.15)\n",
"\n",
"ax = fig.add_subplot(122, projection='3d')\n",
"ax.view_init(elev=5, azim=180, roll=0)\n",
"ax.scatter(features[:,1], features[:,2], c=labels.ravel(), edgecolor='w', alpha=0.75)\n",
"ax.plot_surface(x_line, y_line, plane_eq, color='r', alpha=0.15)\n",
"\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "2-BiOVxz4Tqd"
},
"outputs": [],
"source": [
"def logits_to_class(logits: torch.tensor):\n",
" classes = list(map(lambda logit: 1 if logit > 0.5 else 0, logits))\n",
" return torch.tensor(classes, dtype=torch.int64)\n",
"\n",
"logits = model(features, W)\n",
"n_corrects = (labels == logits_to_class(logits)).sum()\n",
"acc = n_corrects / len(labels)\n",
"\n",
"print(f'Model accuracy: {acc:.3f}')"
]
},
{
"cell_type": "markdown",
"source": [
"## Desafio\n",
"\n",
"Agora é com você! Repita os mesmos passos definidos para a tarefa de regressão. Só que desta vez, ao invés de utilizar todo as amostras para treino, separe os dados em duas partições: treino e teste.\n",
"Sinta-se livre para explorar uma outra base de dados, como aquela disponível no SKLEARN de diabetes!\n",
"A ideia deste exercício é fazer com que você coloque a mão na massa por conta própria, enfrentando os problemas que encontrar ao longo do caminho."
],
"metadata": {
"id": "ncmnoyLMstFu"
}
},
{
"cell_type": "code",
"source": [],
"metadata": {
"id": "e89i4BietFZN"
},
"execution_count": null,
"outputs": []
}
],
"metadata": {
"colab": {
"provenance": [],
"include_colab_link": true
},
"kernelspec": {
"display_name": "Python 3",
"name": "python3"
},
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment