{ "nbformat": 4, "nbformat_minor": 0, "metadata": { "colab": { "name": "2021-01-26-numpy-array-ranks-reshapes.ipynb", "provenance": [], "collapsed_sections": [] }, "kernelspec": { "name": "python3", "display_name": "Python 3" } }, "cells": [ { "cell_type": "markdown", "metadata": { "id": "1EHw4jrMJ5mN" }, "source": [ "# Numpy Array Ranks and Reshaping\n", "- toc:false\n", "- badges: true\n", "- comments: true\n", "\n" ] }, { "cell_type": "markdown", "metadata": { "id": "80TOrn2dhN5f" }, "source": [ "A lot of numpy functions generate rank 1 arrays. A simple example:" ] }, { "cell_type": "code", "metadata": { "id": "ZvJBnV5EOjEl", "colab": { "base_uri": "https://localhost:8080/" }, "outputId": "bff50571-2fe8-4afa-fdea-96b5daade1e1" }, "source": [ "import numpy as np\n", "x = np.linspace(0,1)\n", "x.shape" ], "execution_count": null, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ "(50,)" ] }, "metadata": { "tags": [] }, "execution_count": 5 } ] }, { "cell_type": "markdown", "metadata": { "id": "AIlTpkuMNvXo" }, "source": [ "The shape attribute of a numpy array is a tuple listing the size of each of its dimensions (axes). In this case there is just one dimension. The number of dimensions/axes is simply the length of its shape attribute:" ] }, { "cell_type": "code", "metadata": { "id": "dG_5pvT-O7NJ", "colab": { "base_uri": "https://localhost:8080/" }, "outputId": "dc47e9e6-4ec1-4d91-9dec-5834b17acd0c" }, "source": [ "len(x.shape)" ], "execution_count": null, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ "1" ] }, "metadata": { "tags": [] }, "execution_count": 2 } ] }, { "cell_type": "markdown", "metadata": { "id": "-HN1O52YQg6f" }, "source": [ "An array of rank 1 is called a *vector*. Which is not the same as *matrix* with one column.\n", "\n", "The problem is that a lot of scikit functions require matrices (e.g. submitting the training data has to be in the form of a matrix even if it contains just one feature). So if you try submitting a vector you get the common \"*ValueError: Expected 2D Arrays, got 1D array instead*\".\n", "\n", "This is where reshaping becomes necessary." ] }, { "cell_type": "code", "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "00CS-ikVSjgc", "outputId": "cea37cbc-a062-4982-aeaa-6d3805b96134" }, "source": [ "x2 = x.reshape(-1,1)\n", "x2.shape" ], "execution_count": null, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ "(50, 1)" ] }, "metadata": { "tags": [] }, "execution_count": 6 } ] }, { "cell_type": "markdown", "metadata": { "id": "XnCwueWrSuNe" }, "source": [ "Now the new array x2 is of rank 2 (has two dimensions) - the first is of size 50, and the second is of size 1.\n", "\n", "What is the meaning of -1 here?\n", "\n", "It simply acts as a placeholder - the size of that axis is determined depending on the size of the other axes. In this particular case we asked that the second axis is of size 1 so in order to be able to accommodate all the elements the first axis of the new array has to be of size 50.\n", "\n", "This is how usually the reshaping is performed. At least, this is how I have been doing it. But [a lecture of Jeremy Howard](https://youtu.be/BFIYUvBRTpE?t=5400) made me aware of other ways to achieve the same result." ] }, { "cell_type": "code", "metadata": { "id": "YPaVkeOmSqAA", "colab": { "base_uri": "https://localhost:8080/" }, "outputId": "3b4d4f07-8544-4949-86e2-1a41cbcae23e" }, "source": [ "x2 = x[:, None]\n", "x2.shape" ], "execution_count": null, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ "(50, 1)" ] }, "metadata": { "tags": [] }, "execution_count": 7 } ] }, { "cell_type": "markdown", "metadata": { "id": "b8Pp0C9FWcTR" }, "source": [ "In the above example we used slicing to achieve the same result. The colon (:), essentially, means 'get everything from that axis'. 'None' simply adds an axis of length 1. And it can be added anywhere:" ] }, { "cell_type": "code", "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "22VwEq9iS6lm", "outputId": "b3458898-4bb6-4103-df83-518ac9375c86" }, "source": [ "x2 = x[None, :]\n", "x2.shape" ], "execution_count": null, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ "(1, 50)" ] }, "metadata": { "tags": [] }, "execution_count": 8 } ] }, { "cell_type": "markdown", "metadata": { "id": "VdFE6TteaRrv" }, "source": [ "In this particular case we added axis of length 1 as a first axis.\n", "\n", "We can, actually, achieve the same by omitting the colon:" ] }, { "cell_type": "code", "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "BLB5sKaCYYtJ", "outputId": "71586d61-4cfb-47dd-af6c-bf4079323c19" }, "source": [ "x2 = x[None]\n", "x2.shape" ], "execution_count": null, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ "(1, 50)" ] }, "metadata": { "tags": [] }, "execution_count": 9 } ] }, { "cell_type": "markdown", "metadata": { "id": "FoYRVrkIf_Hp" }, "source": [ "But so far our example was related to adding one dimension to a 1D array. What if the array has originally more dimensions?\n", "\n", "We can explicitly specify them. Or, if the new dimension is supposed to be appended than we can do it this way:" ] }, { "cell_type": "code", "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "KdS2842pYbgC", "outputId": "41f6479a-aee7-46b0-b848-ccf21386fc06" }, "source": [ "x2 = x[...,None]\n", "x2.shape" ], "execution_count": null, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ "(50, 1)" ] }, "metadata": { "tags": [] }, "execution_count": 10 } ] }, { "cell_type": "markdown", "metadata": { "id": "qkkH84tMgW7_" }, "source": [ "There is yet another way to reshape (not mentioned by Jeremy):" ] }, { "cell_type": "code", "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "kN1CXiCxgho-", "outputId": "13654f2b-85c2-43cc-ccac-70cdb16a7af0" }, "source": [ "x2 = x[:] #the slicing is just another way to create a copy of x\n", "x2.shape = (50,1)\n", "x2.shape" ], "execution_count": null, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ "(50, 1)" ] }, "metadata": { "tags": [] }, "execution_count": 11 } ] }, { "cell_type": "markdown", "metadata": { "id": "ZSywO2V9hCW3" }, "source": [ "## Summary\n", "\n", "The vectors and matrixes are just n-dimensional arrays. In the case of vectors n = 1.\n", "\n", "Even though the content of a vector may be the same as a matrix with 1 column they are still considered arrays of different dimensions. Thus it is often necessary to convert a vector to a corresponding matrix. This can be performed in 3 different ways:\n", "\n", "\n", "1. By using reshape(-1,1). This generates a new 2D array with the last one being of size 1.\n", "2. By slicing and using 'None' to add a dimension of size 1.\n", "3. By changing the shape attribute of the vector." ] } ] }