diff --git a/PyTorch_Explore/1_Regression.ipynb b/PyTorch_Explore/1_Regression.ipynb deleted file mode 100644 index db9a922..0000000 --- a/PyTorch_Explore/1_Regression.ipynb +++ /dev/null @@ -1,370 +0,0 @@ -{ - "nbformat": 4, - "nbformat_minor": 0, - "metadata": { - "colab": { - "provenance": [], - "toc_visible": true, - "authorship_tag": "ABX9TyMuXeJk+Zh3Dm2wwP6dBkFI", - "include_colab_link": true - }, - "kernelspec": { - "name": "python3", - "display_name": "Python 3" - }, - "language_info": { - "name": "python" - } - }, - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "view-in-github", - "colab_type": "text" - }, - "source": [ - "\"Open" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Linear Regression" - ], - "metadata": { - "id": "Q6KYqteBVejh" - } - }, - { - "cell_type": "code", - "source": [ - "# 1) Design Model (input, output size, forward pass)\n", - "# 2) Construct Loss and optimizer\n", - "# 3) Training Loop\n", - "# - forward pass: compute prediction\n", - "# - backward pass: gradients\n", - "# - Update weights\n", - "# - Iterated copuple of times" - ], - "metadata": { - "id": "k7BNBK8jUnz5" - }, - "execution_count": 27, - "outputs": [] - }, - { - "cell_type": "code", - "execution_count": 28, - "metadata": { - "id": "oX4MQ4bH8iAQ" - }, - "outputs": [], - "source": [ - "import torch\n", - "import torch.nn as nn # Neural Network modules\n", - "import numpy as np\n", - "from sklearn import datasets\n", - "import matplotlib.pyplot as plt" - ] - }, - { - "cell_type": "code", - "source": [ - "# 0) Prepare Data\n", - "X_numpy, y_numpy = datasets.make_regression(n_samples=100, # Number of datapoints\n", - " n_features=1, # Number of features\n", - " noise=20, # random noise added to the target values\n", - " random_state=1)\n", - "X = torch.from_numpy(X_numpy.astype(np.float32)) # Converts NumPy array to a PyTorch tensor\n", - "y = torch.from_numpy(y_numpy.astype(np.float32)) # Converts NumPy array to a PyTorch tensor\n", - "y = y.view(y.shape[0], 1) # Reshape the target tensor to have a shape of (100, 1)\n", - "# the target tensor should have the same number of columns as the input tensor\n", - "\n", - "n_samples, n_features = X.shape # store the number of samples and features in the data" - ], - "metadata": { - "id": "OWVhelS0UreC" - }, - "execution_count": 29, - "outputs": [] - }, - { - "cell_type": "code", - "source": [ - "# 1) model\n", - "\n", - "# store the number of input and output features for the model\n", - "input_size = n_features\n", - "output_size = 1\n", - "\n", - "model = nn.Linear(input_size, output_size) # Linead Regression Model" - ], - "metadata": { - "id": "ODgAKQuPUc1b" - }, - "execution_count": 30, - "outputs": [] - }, - { - "cell_type": "code", - "source": [ - "# 2) loss and optimizer\n", - "learning_rate = 0.01 # specify the learning rate of the optimizer\n", - "criterion = nn.MSELoss() # loss function\n", - "optimizer = torch.optim.SGD(model.parameters(), lr = learning_rate)" - ], - "metadata": { - "id": "Y5pgS7hwUvPC" - }, - "execution_count": 31, - "outputs": [] - }, - { - "cell_type": "code", - "source": [ - "# 3) Training Loop\n", - "num_epochs = 100\n", - "\n", - "for epoch in range(num_epochs):\n", - " # forward pass and loss\n", - " y_predicted = model(X)\n", - " loss = criterion(y_predicted, y) # calculate the loss between the predictions and the ground truth labels\n", - "\n", - " # backward pass\n", - " loss.backward() # backpropagates the loss through the model\n", - "\n", - " # update weights\n", - " optimizer.step()\n", - "\n", - " optimizer.zero_grad() # sets the gradients of the model to zero\n", - "\n", - " if (epoch+1) % 10 == 0:\n", - " print(f'epoch: {epoch+1}, loss = {loss.item():.4f}')" - ], - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "fZsxw1umUgPb", - "outputId": "577e4e97-52a6-4617-8cc1-c8dddf0f7ea4" - }, - "execution_count": 32, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "epoch: 10, loss = 4416.8926\n", - "epoch: 20, loss = 3295.9634\n", - "epoch: 30, loss = 2484.5186\n", - "epoch: 40, loss = 1896.5035\n", - "epoch: 50, loss = 1469.9907\n", - "epoch: 60, loss = 1160.3503\n", - "epoch: 70, loss = 935.3738\n", - "epoch: 80, loss = 771.7891\n", - "epoch: 90, loss = 652.7618\n", - "epoch: 100, loss = 566.1005\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "# Plot\n", - "predicted = model(X).detach().numpy() # converts prediction to numpy arrays\n", - "plt.plot(X_numpy, y_numpy, 'ro')\n", - "plt.plot(X_numpy, predicted, 'b')\n", - "plt.show()" - ], - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 430 - }, - "id": "OVVcoGigUi79", - "outputId": "35456a6a-53ae-4545-9eb7-1bf006e55d7d" - }, - "execution_count": 33, - "outputs": [ - { - "output_type": "display_data", - "data": { - "text/plain": [ - "
" - ], - "image/png": "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nf4+SRzNBoDAyXijycWLF2vWrFnatWtXzPU//elP+v73v6+tW7eqrKxMkrRo0SJde+212r59u7p3765rr71Wf/zjH/Xee+9FXnfeeedp165deumll1yPgUaT2ed0srm93fm5GKGQNQPjtORjGNYR6vr69J4sCn9uY6N94srU5wIA4vi+0eTq1av1xS9+MRJkJGn8+PFqbW3VunXrIveMGzcu5nXjx4/X6tWrE753W1ubWltbYx7IjvPOsw8r779/uFmkK17tXQkfzZbiBxv+naPZAOArnoWZpqammCAjKfJ7U1NTwntaW1v12WefOb73ggULVFJSEnlUJtyUgXR46y3ru/7JJ2OvX321lTtOOCHFN/Ry70p1tbWE1bHITUVFZpa2AABdklKYue6662QYRsLHhg0bMjVW1+bOnauWlpbIo6Ghwesh5ayDB60QM3p0/HOmKS1c2Mk39nrvSnW1tGmTVFsrLVli/ayvJ8gAgA+ltAH4qquu0tSpUxPeM2LECFfvVV5ernfeeSfmWnNzc+S58M/wteh7iouL1bNnT8f3LioqUlFRkatxoPOclowOHJC6dXVrebitQLK9K5lsK1BYKI0dm7n3BwCkRUpfOaWlpSotLU3LB48ePVo333yzPvnkEw0cOFCStGLFChUXF+vEE0+M3PPiiy/GvG7FihUabTcNgKyZNevwtpJo77wjfe1rafqQ8N6VSZOs4BIdaNi7AgCIkrE9M5s3b9batWu1efNmhUIhrV27VmvXrtWePXskSWeeeaZOPPFE/fjHP9bf//53vfzyy/rlL3+pGTNmRGZVLr/8cn388ce65pprtGHDBj3wwANatmyZZs+enalhI4F166wc0THI/PjHVtZIW5AJY+8KAMCFjB3Nnjp1qh577LG467W1tRp7aOr+n//8p6ZPn666ujodeeSRuuiii/Tb3/5W3aLWKOrq6jR79mytX79eFRUVuuGGG5IudXXE0eyuaW93ngDJSkfrUMg6tbRtm7VHZswYZmQAIA+4/f7OeJ0ZPyDMdJ7Tvph9+yS2JQEAMsn3dWbgbzfdZB9kXn3Vmo0hyAAA/CJj7QwQTJs2ScOHx18fN05asSLrwwEAICnCDCRZsy0FDvN0ub8QCQAIMpaZoF697INMaytBBgDgf4SZPLZokbUvpmNniOXLrRDTp48HgwqFpLo6aelS62co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ACAJwkxnZKs6b2GhNHZs+t4PAIAcxDJTqqjOCwCArxBmUkF1XgAAfIcwkwqq8wIA4DuEmVRQnRcAAN9hA3AqvKzOm+nTUwAABFTGZmY2bdqkadOmafjw4erZs6eOOeYYzZs3T/v374+5791339WYMWPUo0cPVVZW6tZbb417r6eeekonnHCCevTooS9+8Yt68cUXMzXsxLyqzltTIw0bJlVVSVOmWD+HDWOzMQAAymCY2bBhg9rb2/X73/9e69at05133qlFixbpF7/4ReSe1tZWnXnmmRo6dKjWrFmjhQsXav78+XrooYci97z55ps6//zzNW3aNP33f/+3zj33XJ177rl67733MjV0Z15U5+X0FAAACRmmaXc0JzMWLlyoBx98UB9//LEk6cEHH9T111+vpqYmde/eXZJ03XXX6dlnn9WGDRskST/84Q+1d+9evfDCC5H3+frXv64vf/nLWrRokavPbW1tVUlJiVpaWlRcXNz1P4hdnZnKSivIpLPOTChkzcA4bTo2DGumqL6eJScAQM5x+/2d1Q3ALS0t6tevX+T31atX61vf+lYkyEjS+PHj9cEHH+hf//pX5J5x48bFvM/48eO1evXq7AzaTnW1tGmTVFsrLVli/ayvT3+bAU5PAQCQVNY2AG/cuFH33nuvbrvttsi1pqYmDR8+POa+srKyyHNHHXWUmpqaItei72lqanL8rLa2NrW1tUV+b21tTccfIVY2qvNyegoAgKRSnpm57rrrZBhGwkd4iSissbFRZ511liZPnqxLL700bYN3smDBApWUlEQelZWVGf/MjPDy9BQAAAGR8szMVVddpalTpya8Z8SIEZF/3rp1q6qqqnTaaafFbOyVpPLycjU3N8dcC/9eXl6e8J7w83bmzp2rOXPmRH5vbW0NZqAJn55qbLSvOhzeM5Pu01MAAARIymGmtLRUpaWlru5tbGxUVVWVRo4cqUcffVQFBbETQaNHj9b111+vAwcO6IgjjpAkrVixQscff7yOOuqoyD0rV67UrFmzIq9bsWKFRo8e7fi5RUVFKioqSvFP5kPh01OTJlnBJTrQZOr0FAAAAZOxDcCNjY0aO3ashgwZottuu03bt29XU1NTzF6XKVOmqHv37po2bZrWrVunJ598UnfffXfMrMqVV16pl156Sbfffrs2bNig+fPn669//atmzpyZqaH7S3W19PTT0tFHx16vqLCup3vTMQAAAZOxo9mLFy/WxRdfbPtc9Ee+++67mjFjhv7yl79owIABuuKKK3TttdfG3P/UU0/pl7/8pTZt2qTjjjtOt956q773ve+5Hkvaj2Z7gQrAAIA84/b7O6t1ZrySE2EGAIA848s6MwAAAOlGmAEAAIFGmAEAAIFGmAEAAIFGmAEAAIFGmAEAAIFGmAEAAIFGmAEAAIFGmAEAAIGWcqPJIAoXOW5tbfV4JAAAwK3w93ayZgV5EWZ2794tSaqsrPR4JAAAIFW7d+9WSUmJ4/N50Zupvb1dW7duVZ8+fWQYhtfDSYvW1lZVVlaqoaGBflM+wN+H//B34i/8ffhPEP5OTNPU7t27NXjwYBUUOO+MyYuZmYKCAlVUVHg9jIwoLi727X8J8xF/H/7D34m/8PfhP37/O0k0IxPGBmAAABBohBkAABBohJmAKioq0rx581RUVOT1UCD+PvyIvxN/4e/Df3Lp7yQvNgADAIDcxcwMAAAINMIMAAAINMIMAAAINMIMAAAINMJMwG3atEnTpk3T8OHD1bNnTx1zzDGaN2+e9u/f7/XQ8tbNN9+s0047Tb169VLfvn29Hk5euv/++zVs2DD16NFDo0aN0jvvvOP1kPLWG2+8oXPOOUeDBw+WYRh69tlnvR5SXluwYIG+9rWvqU+fPho4cKDOPfdcffDBB14Pq8sIMwG3YcMGtbe36/e//73WrVunO++8U4sWLdIvfvELr4eWt/bv36/Jkydr+vTpXg8lLz355JOaM2eO5s2bp7/97W86+eSTNX78eH3yySdeDy0v7d27VyeffLLuv/9+r4cCSa+//rpmzJiht956SytWrNCBAwd05plnau/evV4PrUs4mp2DFi5cqAcffFAff/yx10PJa4sXL9asWbO0a9cur4eSV0aNGqWvfe1ruu+++yRZvdkqKyt1xRVX6LrrrvN4dPnNMAw988wzOvfcc70eCg7Zvn27Bg4cqNdff13f+ta3vB5OpzEzk4NaWlrUr18/r4cBZN3+/fu1Zs0ajRs3LnKtoKBA48aN0+rVqz0cGeBPLS0tkhT47wzCTI7ZuHGj7r33Xv3kJz/xeihA1n366acKhUIqKyuLuV5WVqampiaPRgX4U3t7u2bNmqVvfOMb+sIXvuD1cLqEMONT1113nQzDSPjYsGFDzGsaGxt11llnafLkybr00ks9Gnlu6szfBwD42YwZM/Tee+/piSee8HooXdbN6wHA3lVXXaWpU6cmvGfEiBGRf966dauqqqp02mmn6aGHHsrw6PJPqn8f8MaAAQNUWFio5ubmmOvNzc0qLy/3aFSA/8ycOVMvvPCC3njjDVVUVHg9nC4jzPhUaWmpSktLXd3b2NioqqoqjRw5Uo8++qgKCphwS7dU/j7gne7du2vkyJFauXJlZJNpe3u7Vq5cqZkzZ3o7OMAHTNPUFVdcoWeeeUZ1dXUaPny410NKC8JMwDU2Nmrs2LEaOnSobrvtNm3fvj3yHP9P1BubN2/Wzp07tXnzZoVCIa1du1aSdOyxx6p3797eDi4PzJkzRxdddJFOOeUUnXrqqbrrrru0d+9eXXzxxV4PLS/t2bNHGzdujPxeX1+vtWvXql+/fhoyZIiHI8tPM2bM0JIlS/Tcc8+pT58+kb1kJSUl6tmzp8ej6wITgfboo4+akmwf8MZFF11k+/dRW1vr9dDyxr333msOGTLE7N69u3nqqaeab731ltdDylu1tbW2/3u46KKLvB5aXnL6vnj00Ue9HlqXUGcGAAAEGpsrAABAoBFmAABAoBFmAABAoBFmAABAoBFmAABAoBFmAABAoBFmAABAoBFmAABAoBFmAABAoBFmAABAoBFmAABAoBFmAABAoP0/EEQYlOgtpUwAAAAASUVORK5CYII=\n" - }, - "metadata": {} - } - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Logistic Regression" - ], - "metadata": { - "id": "mEsyp0yRViVR" - } - }, - { - "cell_type": "code", - "source": [ - "# 1) Design Model (input, output size, forward pass)\n", - "# 2) Construct Loss and optimizer\n", - "# 3) Training Loop\n", - "# - forward pass: compute prediction\n", - "# - backward pass: gradients\n", - "# - Update weights\n", - "# - Iterated copuple of times" - ], - "metadata": { - "id": "Lnbz6PItVqbG" - }, - "execution_count": 14, - "outputs": [] - }, - { - "cell_type": "code", - "source": [ - "import torch\n", - "import torch.nn as nn # Neural Network modules\n", - "import numpy as np\n", - "from sklearn import datasets\n", - "from sklearn.preprocessing import StandardScaler\n", - "from sklearn.model_selection import train_test_split" - ], - "metadata": { - "id": "JL1dsY3MVuJs" - }, - "execution_count": 15, - "outputs": [] - }, - { - "cell_type": "code", - "source": [ - "# 0) Prepare Data\n", - "bc = datasets.load_breast_cancer()\n", - "X, y = bc.data, bc.target\n", - "\n", - "n_samples, n_features = X.shape\n", - "\n", - "X_train, X_test, y_train, y_test = train_test_split(X, y,\n", - " test_size=0.2,\n", - " random_state=1234)\n", - "\n", - "# scale\n", - "sc = StandardScaler()\n", - "X_train = sc.fit_transform(X_train)\n", - "X_test = sc.transform(X_test)\n", - "\n", - "X_train = torch.from_numpy(X_train.astype(np.float32))\n", - "X_test = torch.from_numpy(X_test.astype(np.float32))\n", - "y_train = torch.from_numpy(y_train.astype(np.float32))\n", - "y_test = torch.from_numpy(y_test.astype(np.float32))\n", - "\n", - "y_train = y_train.view(y_train.shape[0], 1)\n", - "y_test = y_test.view(y_test.shape[0], 1)" - ], - "metadata": { - "id": "GpgtUu7MV6Z7" - }, - "execution_count": 17, - "outputs": [] - }, - { - "cell_type": "code", - "source": [ - "# 1) model\n", - "# f = wx + b, sigmoid at the end\n", - "class LogisticsRegression(nn.Module):\n", - " def __init__(self, n_input_features):\n", - " super(LogisticsRegression, self).__init__()\n", - " self.linear = nn.Linear(n_input_features, 1)\n", - " def forward(self, x):\n", - " y_predicted = torch.sigmoid(self.linear(x))\n", - " return y_predicted\n", - "\n", - "model = LogisticsRegression(n_features)" - ], - "metadata": { - "id": "GFV0Hd9pV9q4" - }, - "execution_count": 24, - "outputs": [] - }, - { - "cell_type": "code", - "source": [ - "# 2) loss and optimizer\n", - "learning_rate = 0.01\n", - "criterion = nn.BCELoss()\n", - "optimizer = torch.optim.SGD(model.parameters(), lr = learning_rate)" - ], - "metadata": { - "id": "_vRuHR8vbqYg" - }, - "execution_count": 25, - "outputs": [] - }, - { - "cell_type": "code", - "source": [ - "# 3) training loop\n", - "num_epochs = 100\n", - "\n", - "for epoch in range(num_epochs):\n", - " # forward pass\n", - " y_predicted = model(X_train)\n", - " loss = criterion(y_predicted, y_train)\n", - "\n", - " # backward pass\n", - " loss.backward()\n", - "\n", - " # updates\n", - " optimizer.step()\n", - "\n", - " # zero gradients\n", - " optimizer.zero_grad()\n", - "\n", - " if (epoch+1) % 10 == 0:\n", - " print(f'epoch: {epoch+1}, loss = {loss.item():.4f}')\n", - "\n", - "with torch.no_grad():\n", - " y_predicted = model(X_test)\n", - " y_predicted_cls = y_predicted.round()\n", - " acc = y_predicted_cls.eq(y_test).sum() / float(y_test.shape[0])\n", - " print(f'accuracy = {acc:.4f}')" - ], - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "5YEEppc4btTO", - "outputId": "20ab187b-f52d-4722-f6cb-14edde10c396" - }, - "execution_count": 26, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "epoch: 10, loss = 0.5717\n", - "epoch: 20, loss = 0.4766\n", - "epoch: 30, loss = 0.4155\n", - "epoch: 40, loss = 0.3726\n", - "epoch: 50, loss = 0.3406\n", - "epoch: 60, loss = 0.3155\n", - "epoch: 70, loss = 0.2952\n", - "epoch: 80, loss = 0.2784\n", - "epoch: 90, loss = 0.2641\n", - "epoch: 100, loss = 0.2518\n", - "accuracy = 0.9123\n" - ] - } - ] - } - ] -} \ No newline at end of file