{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<p style=\"text-align:center\">\n",
    "    <a href=\"https://nbviewer.jupyter.org/github/twMr7/Python-Machine-Learning/blob/master/11-Numpy_Vectorized_Computation.ipynb\">\n",
    "        Open In Jupyter nbviewer\n",
    "        <img style=\"float: center;\" src=\"https://nbviewer.jupyter.org/static/img/nav_logo.svg\" width=\"120\" />\n",
    "    </a>\n",
    "</p>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/twMr7/Python-Machine-Learning/blob/master/11-Numpy_Vectorized_Computation.ipynb)\n",
    "\n",
    "# 11. Numpy 向量運算\n",
    "\n",
    "機器學習的資料處理經常使用大量數據作運算,使用 Python 內建的資料類型,沒有辦法利用硬體在向量運算優化的好處。 [Numpy](http://www.numpy.org/) 是 Python 社群中公認的針對科學運算的標準套件,包含了強大的 **`ndarray`** 多維陣列類型,支援硬體優化的向量運算、簡單直覺的向量式操作、線性代數及傅立葉轉換等工具函式。\n",
    "+ [**11.1 建立向量、矩陣、與陣列**](#create-ndarray)\n",
    "+ [**11.2 索引及片段 Indexing and Slicing**](#indexing-slicing)\n",
    "+ [**11.3 陣列形狀的操作**](#shape-manipulation)\n",
    "+ [**11.4 數值陣列運算**](#numerical-operations)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### § 使用 `numpy` 套件"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 載入 numpy 的慣例方式\n",
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 部份範例會將資料視覺化,預先開啟 matplotlib 互動呈現\n",
    "%matplotlib inline\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### § 取得說明\n",
    "除了官方文件 ([https://numpy.org/doc/stable/](https://numpy.org/doc/stable/) ) 以外,互動式介面下也可以取得說明。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 取得 np.array 的說明\n",
    "np.array?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 忘記函式的全名怎麼拼,可以打前幾個字,然後按 Tab 鍵。\n",
    "np.con"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id=\"create-ndarray\"></a>\n",
    "\n",
    "## 11.1 建立向量、矩陣、與陣列\n",
    "\n",
    "Numpy 的 `ndarray` 是可以存放**同類型**資料的多維度陣列,在大多數的應用中,陣列元素的資料類型通常是數值。`ndarray` 類型的物件可以透過 [`array()`、`zeros()`、`ones()`、或 `identity()` 等函式建立](https://docs.scipy.org/doc/numpy/reference/routines.array-creation.html)。 描述 `ndarray` 的基本的屬性有:\n",
    "\n",
    "+ `ndarray.ndim` - 維度\n",
    "+ [`ndarray.shape`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.shape.html) - Tuple 表示每個維度的大小,也可以指定新的 Tuple 值改變陣列的形狀,類似 `reshape()` 函式,差別是 `shape` 屬性是就地改變。\n",
    "+ `ndarray.size` - 元素總數量\n",
    "+ [`ndarray.dtype`](https://docs.scipy.org/doc/numpy/user/basics.types.html) - 元素資料形態,數值通常使用 numpy 提供的 `np.float64`、`np.int32`、`np.int16`、 ...等,可以只寫 `float`、`int` 使用系統預設的浮點數或整數型態。\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "v: ndim=1, shape=(4,), size=4, dtype=int32\n"
     ]
    }
   ],
   "source": [
    "# a one-dimension vector\n",
    "v = np.array([0, 1, 2, 3])\n",
    "\n",
    "print('v: ndim={}, shape={}, size={}, dtype={}'.format(v.ndim, v.shape, v.size, v.dtype))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "rowv: ndim=2, shape=(1, 4), size=4, dtype=int32\n"
     ]
    }
   ],
   "source": [
    "# a 1 x 4 row vector/matrix,明確指定使用整數型態的資料\n",
    "rowv = np.array([[0, 1, 2, 3]], dtype=int)\n",
    "\n",
    "print('rowv: ndim={}, shape={}, size={}, dtype={}'.format(rowv.ndim, rowv.shape, rowv.size, rowv.dtype))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "colv: ndim=2, shape=(4, 1), size=4, dtype=float64\n"
     ]
    }
   ],
   "source": [
    "# a 4 x 1 column vector/matrix,明確指定使用浮點數型態的資料\n",
    "colv = np.array([[0],\n",
    "                 [1],\n",
    "                 [2],\n",
    "                 [3]], dtype=float)\n",
    "\n",
    "print('colv: ndim={}, shape={}, size={}, dtype={}'.format(colv.ndim, colv.shape, colv.size, colv.dtype))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Amat: ndim=2, shape=(3, 4), size=12, dtype=float64\n"
     ]
    }
   ],
   "source": [
    "# a 3 x 4 matrix,明確指定使用 np.float64 浮點數型態的資料\n",
    "Amat = np.array([[0, 1,  2,  3],\n",
    "                 [4, 5,  6,  7],\n",
    "                 [8, 9, 10, 11]], dtype=np.float64)\n",
    "\n",
    "print('Amat: ndim={}, shape={}, size={}, dtype={}'.format(Amat.ndim, Amat.shape, Amat.size, Amat.dtype))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "A3d: ndim=3, shape=(2, 3, 4), size=24, dtype=int32\n"
     ]
    }
   ],
   "source": [
    "# a 2 x 3 x 4 array\n",
    "A3d = np.array([[[ 0,  1,  2,  3],\n",
    "                 [ 4,  5,  6,  7],\n",
    "                 [ 8,  9, 10, 11]],\n",
    "\n",
    "                [[12, 13, 14, 15],\n",
    "                 [16, 17, 18, 19],\n",
    "                 [20, 21, 22, 23]]])\n",
    "\n",
    "print('A3d: ndim={}, shape={}, size={}, dtype={}'.format(A3d.ndim, A3d.shape, A3d.size, A3d.dtype))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0., 0., 0.],\n",
       "       [0., 0., 0.],\n",
       "       [0., 0., 0.]])"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 元素都為 0 的 3 x 3 matrix\n",
    "np.zeros((3, 3))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1., 1., 1., 1.],\n",
       "       [1., 1., 1., 1.],\n",
       "       [1., 1., 1., 1.],\n",
       "       [1., 1., 1., 1.]])"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 元素都為 1 的 4 x 4 matrix\n",
    "np.ones((4, 4))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1., 0., 0., 0., 0.],\n",
       "       [0., 1., 0., 0., 0.],\n",
       "       [0., 0., 1., 0., 0.],\n",
       "       [0., 0., 0., 1., 0.],\n",
       "       [0., 0., 0., 0., 1.]])"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 5 x 5 identity matrix\n",
    "np.identity(5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "其他常用函式,可用來建立具備某種規律排列數列的 ndarray:\n",
    "+ [`np.arange`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.arange.html) - 產生一維的固定間距的整數數列陣列。 類似 Python 內建函式 `range()` 的 numpy 陣列版。\n",
    "+ [`np.linspace`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.linspace.html) - 在指定區間內產生線性(固定)間隔的指定數量的數列。\n",
    "+ [`np.logspace`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.logspace.html) - 在指定區間內產生對數間隔的指定數量的數列。\n",
    "+ [`np.random.rand`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.random.rand.html) - 產生指定大小的均勻分佈隨機亂數。\n",
    "+ [`np.random.randn`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.random.randn.html) - 產生指定大小的高斯分佈隨機亂數。\n",
    "+ [`np.random.randint`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.random.randint.html) - \n",
    "產生指定大小的隨機整數。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# [0, 10) 整數數列\n",
    "np.arange(10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 3, 5, 7, 9])"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 指定範圍及間距,arange([start, ]stop, [step, ]),注意參數 [start, stop) 為半開放區間\n",
    "np.arange(1, 10, 2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[ 1,  2,  3,  4],\n",
       "        [ 5,  6,  7,  8],\n",
       "        [ 9, 10, 11, 12]],\n",
       "\n",
       "       [[13, 14, 15, 16],\n",
       "        [17, 18, 19, 20],\n",
       "        [21, 22, 23, 24]]])"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 時常用來產生數列後就轉成需要的維度形狀\n",
    "np.arange(1, 25).reshape((2, 3, 4))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 1.     2.125  3.25   4.375  5.5    6.625  7.75   8.875 10.   ]\n"
     ]
    }
   ],
   "source": [
    "# 指定範圍及點數,linspace(start, stop, num=50),注意參數 [start, stop] 為封閉區間 \n",
    "linda = np.linspace(1, 10, num=9)\n",
    "print(linda)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 1.          1.33352143  1.77827941  2.37137371  3.16227766  4.21696503\n",
      "  5.62341325  7.49894209 10.        ]\n"
     ]
    }
   ],
   "source": [
    "# 指定範圍及點數,logspace(start, stop, num=50),注意參數 [start, stop] 為封閉區間 \n",
    "logda = np.logspace(0, 1, num=9)\n",
    "print(logda)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x2c408b91cc0>]"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXQAAAD8CAYAAABn919SAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAIABJREFUeJzt3Xd8VFX6x/HPSS+kAEkICb2FDoFQFCvgBqVIERUbwirurgVdl2ZZde1gY/VnQVdFsScBFFEQFGSVIhBIQgklkIQkkEBISC8z5/fHDc0FCSlzpzzv14vXJHcmcx+G5MvNmXOeo7TWCCGEcHxuZhcghBCiYUigCyGEk5BAF0IIJyGBLoQQTkICXQghnIQEuhBCOAkJdCGEcBIS6EII4SQk0IUQwkl42PJkISEhul27drY8pRBCOLwtW7Yc1VqHXuhxNg30du3asXnzZlueUgghHJ5SKr02j5MhFyGEcBIS6EII4SQk0IUQwklIoAshhJOQQBdCCCdxwUBXSr2vlMpVSqWccayZUuoHpdTemtumjVumEEI4niWJWYx5Po6N/xzE6OfjWZKY1ajnq80V+ofAiN8dmw2s1lp3BlbXfC6EEKLGksQs5iQkM7HkMwaoVG4s+ZQ5CcmNGuqqNlvQKaXaAcu01j1rPk8FrtJa5yilWgJrtNZRF3qemJgYLfPQhRCuoOLJELyp+t/jeOL95NGLei6l1BatdcyFHlfXMfQWWuscgJrbsD8oZJpSarNSanNeXl4dTyeEEA7k0GY2WLpRrU9HbJn2YnH1EC4rn99op230N0W11gu01jFa65jQ0AuuXBVCCMdiqYaMDbDqKThkjEBkHyugo1s2+3VLrBrKtSfeVFGML17BLRutlLou/T+ilGp5xpBLbkMWJYQQdq26EnYugT0rYN8qKC8A5Y7FvwUL9jXl1VWVuPFv5ru9ykZLNz6zDGOS+2rC3QqZEXvB0ek6q2ugfw1MBl6ouV3aYBUJIYS90RqOpEDJUeh4NSg3WD4D3Dwg6jrofA27/GOYsSydlKzdjOgRzr/G9uDXfX15Z0Uq2QVlvNPkXmbERjE2OrLRyrzgm6JKqc+Aq4AQ4AjwBLAE+BJoA2QAE7XW+Rc6mbwpKoRwGBXFkLYG9q6EvT9AUTY07wT3bzHuzz8AwW0pt2he/3Evb69No6mfF09f34NrezXssEpt3xS94BW61nrSee4adtFVCSGEPcs/AE3bgVLw7cOQ9Dl4BRhX5V1iodM1px/brD1b0vOZGZfE/rwSJvRrxeOjuhHs52Va+TZtnyuEEHaluhLSfzGuwvesgPz9cN9mCOkMg/8KfW+BNpeAx9khXVJRzbwVqSxcf5CIIF8WTh3IlV3Mn/QhgS6EcC1aG1fgGRtg0QSoLAZ3b2h/OQz6C/g2Mx4X0fecX/7znjzmJCSTXVjG5EvaMSM2Cn9v+4hS+6hCCCEai9UCWVtOX4X3mghDHoDQrsbHXWKh/RXg5f+HT1NQWskz3+4ibsshOoT689U9lxDTrpmN/hK1I4EuhHBOWsPS+2DPd1B6zJiZ0noQBEYY9/sGw+jXavVU3yXn8PjSHRwvreTeqzty/9DO+Hi6N2LxdSOBLoRwfFpD7k7jKvxEDlw31xhWqSyGTsOh85+g41Dwu7gr6tyicp5YuoPvUg7TIyKQhVMH0CMiqJH+EvUngS6EcFyZm2D7Z8a0wsJM41hEP2P1prsH3LiwTk+rtSZuyyGe+XYXZVUWZo3oyl2Xt8fT3b47jkugCyEcR/4B4yq810TjavvQb7D9C2Na4RUzjCvxwPrNAc/ML+WRxcms23uUAe2a8sKE3nQMbdJAf4HGJYEuhLBflirIWG+8mbl3JRzdYxwPaAndx0D/O2HAXeDhXe9TWa2aj9YfZO6KVBTw9PU9uHVQW9zcVL2f21Yk0IUQ9qXoCFSVQLMOUJABC0eDuxe0HQIxU42r8OYdjcdeYGZKbe3LLWJWfDJb0o9zZZdQnh3Xk1ZN/RrkuW1JAl0IYS6rFXISYc9K2LsCshOhx3iY+IER3LfGQ5vB4N3wwx5VFisLfk5j/qq9+Hm788qNfRgXHYlSjnNVfiYJdCGE7VVXnB4mWTjKWK2JglYDYOhjRsOrkzoPb5QSUrIKmRmXxM6cE4zs3ZInR/cgNKD+QzdmkkAXQjQ+rSEv1bgC37MS8nbBw6ng7gn9pxhj4R2HgX/zRi+lvMrC/NV7WfBzGs38vXjn9v7E9ghv9PPaggS6EKJx7VoGK+YY4+EALXpCv8lQVWYEeu+JNitl04F8ZscnkXa0hJtiWvPIdd0I8vO02fkbmwS6EKLhFGSevgofMh3aDQH/UAjrAZc9ZLyhGdTK5mUVV1Tz4ne7+XhDOq2a+rLoz4O4rHOIzetobBLoQoj6qSiCn+edHkoBowVtWc0WCW0GwS2fm1beT6m5PJqQTM6JcqYOac8/Yrvg5+Wc0eecfyshROMpOWqszAToOwk8fGHbZxDWFaJvM5pdNe9kLL030fGSSp5etpOExCw6hTUh7i+X0r9tU1NramwS6EKIsxUdhrgpcMOHENDCOHY4BVKXGwt8srYAGloPNgLd3QMe2vE/PcNtaUliFvNqtnqLCPZheLcWfJucQ0FpFQ8M7cS9Qzvh7WF/zbQamgS6EOJsa+dC+npYei/c+pVxpf3LfEj+CiL7w1VzoMufILzP6a8xOcznJCRTVmUBIKugnIXr02kV7Ms39w+iW8tA02qzNQl0IYThmTBjfvhJ+36Ap4KN+eL3boLY56CJ+bvy/N68FamnwvxMVrRLhTlIoAshAA5tNsbCqysABWhjF59uo40gPzn0YoeyC8rOeTynoNzGlZjPvntBCiEaR0URbFkIO5YYn4d2NaYUdo41hlg8fMBaBT5BdhvmFqvmP/89cN77I4J9bViNfZArdCFchdZGu9mtCyFlsdEAq9sY6DHW6JMy4V34/FZj5WbMFNj8ARQfMbvqc9p7pIiZ8UkkZhTQvWUA+/NKqKi2nrrf19OdGbFRJlZoDgl0IVzF0vtg2yLw9Iee46HfHUbvlDPd/Mnpj0e9Ytv6aqGy2srba/fz+o97aeLtwfyb+zKmTwRLt2WfMcvFlxmxUYyNjjS7XJuTQBfCGVmtkPYTJH4M186FJmFGiLceaNx6B5hd4UXbnlnArPgkdh8uYnSfCJ4c3Z3mTYxmWmOjI10ywH9PAl0IZ1J4CBI/gcRFUJgBvk0hd5cR6J2GmV1dnZRVWnht1R7eXZdGaIA3794RwzXd7XNc32wS6EI4i5KjML8PWC3Q4Sq45inoOrJBdvMxy4a0Y8yOT+LgsVImDWzDnOu6EujjPM20GpoEuhCOKi8Vtn4Epfkw7i3wD4Exrxs7+zRta3Z19XKivIoXvtvNpxszaNvcj0/vHsSlHZ2vmVZDk0AXwpFUFMOOxcbYeOZGcPMw5opbLeDmDn1vMbvCevtx9xEeSUght6icuy9vz9+vicLXy/mX7TcECXQh7J3Wxh83N9i0AFY/BSFd4Jqnoc8ku1y9WRfHiiv417KdLN2WTVSLAN6+vT99WwebXZZDkUAXwl6V5kPSF7D1Y7j879DrBoi+HdpeCq0Hmd7NsKForfkmKYcnv95BUXkVDw7vzN+u6oSXh6x7vFgS6ELYE63hwFpjbHzXN2CphIh+4F3Tk6RJqNNckQPkFJbx+JIUVu3KpU/rYOZO6E1UuONNqbQXEuhC2IOK4tO72i+faazQjJlqXJGH9zS3tkZgtWo+/y2T55fvospq5bGR3ZgypD3ubs7xW4dZJNCFMIulCvZ8bwypZG6Ev+8CLz9jtWZQa/D0MbvCRnHwaAmzE5LYkJbPJR2a88KEXrRt7m92WU5BAl0IWyvMgk3vGLv8lORCQEsY8GdjeAU/COlsdoWNwmLVvP/fA7z8Qyqebm68ML4XNw1ojXKS9wLsgQS6ELZQWQqVxcaKzZJc+PUN6DLC6KfSabix648TSz1cxMy47Ww/VMjwbi14ZmxPwoOc8zcQM9Xru0gp9RBwF6CBZGCK1tr1mhALcT7Z24w3OJO/Mjobjv0/aNkXHk51qjc3z6ei2sKbP+3nzTX7CPTx5PVJ0Yzq3VKuyhtJnQNdKRUJPAB011qXKaW+BG4GPmyg2oRwXNs+hQ1vwuFko7d49+uNDZTBmG7oAmGemHGcWfFJ7DlSzLjoSB4f1Z1m/uZtVecK6vt7ngfgq5SqAvyA7PqXJIQD0hoyNhjzw93cICcJlBtc9xL0mgi+rrNAprSympdX7uH9Xw4QHujD+3fGMLSrNNOyhToHutY6Syn1EpABlAErtdYrf/84pdQ0YBpAmzZt6no6IexT0WHYVtPdMD8NJn8D7a+Aa/5l6sbJZvl131FmJySTkV/KbYPbMGtEVwKkmZbN1GfIpSlwPdAeKAC+UkrdprVedObjtNYLgAUAMTExuh61CmE/io7AsgdhzwrQFmh7GVw5CyJjjPtdLMwLy6p4fvkuPv8tk/Yh/nw+bTCDOzQ3uyyXU58hl+HAAa11HoBSKgG4FFj0h18lhKM6th8KM43WtH7NoCAThjxgLP5p3tHs6kyzcsdhHluSwtHiCu65sgMPDe+Cj6c00zJDfQI9AxislPLDGHIZBmxukKqEMFPRYYibAjd8CD6BxhL8rR/BwXUQ3Bambwd3T/jLOqfpp1JbSxKzTm311iLIh/BAb7ZlFtI1PID3JsfQu5XrvFdgj+ozhr5RKRUHbAWqgURqhlaEcGhr5xpvcMZPNWaplBdC03Yw9HGjPe3JEHfBMJ+TkExZlQWAw4XlHC4s57qe4cyfFI2nuzTTMlu9ZrlorZ8AnmigWoQw1zNhUF1x+vOD/zVu3T3h/kRj9ooLm7ci9VSYn2n7oUIJczsh/wpCABzZCe0uNz52q7nO8fA1phw+uMPlw9xq1WQVlJ3zvuzzHBe259zrjYW4kGP7Yc3zkBwHXk2gZTTkbDMWA1kqjLa1Aa49hzotr5jZCcnnvT8i2NeG1Yg/4tqXHUKsfRF2LTNmqzyYBEGRRtvau1ZB/ylGG1sXVW2x8vba/Vw7fx27c05w88DW+HqeHRm+nu7MiI0yqULxe0pr200Nj4mJ0Zs3y0QYYaLiXFj3CkTfCuG94ES2saIzINzsyuzKzuwTzIzfTkrWCWJ7tODp63sSFuhz1iyXiGBfZsRGMTY60uxynZ5SaovWOuZCj5MhF+EaSvPh13/DxneMNz6bdzQCPTDC7MrsSkW1hTd+3Mdba/YT7OfJm7f249qe4aeaaY2NjpQAt2MS6ML5/fq6MRWxogh6ToCr5kBIJ7Orsjtb0o1mWvtyixnfL5LHR3anqTTTcigS6MI5VZWDh7cxV7zsuDGDZeij0KKH2ZXZnZKKal5amcqHvx4kIsiXD6cM4KqoMLPLEnUggS6cS3UlJH4EP78Eo16DqBFw9WMuP+3wfNbtzWNOQjKHjpcx+ZK2zBjRlSbeEguOSv7lhHOwWiDpC1jzAhSkQ+vB4F/Tc1zC/H8Ullbx7PKdfLn5EB1C/fnqL5cwoF0zs8sS9SSBLpzDovGQtgZa9oGRLxvburnY0vza+j7lMI8vTSG/pJK/XdWRB4Z1lmZaTkICXTgmrWHfaqP3uIeXMWc8ZqqxzZsE+TnlFVXw5Nc7+DY5h+4tA/ngzgH0jAwyuyzRgCTQheM58DOsfhoObYIxb0C/26HHWLOrsltaaxK2ZvGvZTspq7IwIzaKaVd0kP4rTkgCXTiOzN/gx6fhwFoIiIBRr0Kfm82uyq4dOl7KI4tT+HlPHv3bNuXFCb3pFNbE7LJEI5FAF45Ba1j+Dyg8BLHPQcyfwdPH7KrsltWqWbQxnRe/240GnhrTg9sHt8XNTYajnJkEurBfR/cay/RjnzV2CLrhfWjSArzlCvOP7M8rZnZ8Er8dPM7lnUN4blwvWjfzM7ssYQMS6ML+FGTAmhdh+6c1LWwnGLNWXHibt9qoslh5d10ar63ai6+nOy9N7MOEfpGnlu0L5yeBLuyH1QLfz4HN7xsNswb9FS57CJqEml2Z3UvJKmRWfBI7sk9wXa9wnhzTg7AAGZJyNRLownxVZeDpC27uRrva6NvgihlGK1vxh8qrLLz+417eXptGUz8v3r6tHyN6tjS7LGESCXRhnvITsP7/YOPbcNdqo2HWDR/Iys5a2nwwn5nxSaTllTCxfyseG9mdID9Ps8sSJpJAF7ZXWQqbFsAvrxmNs7qNNq7OQcK8Foorqpn3/W4+2pBORJAvH00dyBVdZFhKSKALW6uuhDcHGW98dhoOQx+DiGizq3IYa/fk8UhCMtmFZUy+pB0zYqPwl2ZaooZ8J4jGUXQY4qbADR+CX3PYvxq6xBrL9IdMh7Du0PZSs6u0W7/fGejeqzuyJb2A+K2H6Bjqz1f3XEKMNNMSvyNb0InGsezvsOUDaHcFnDgEx/bBn3+A1gPNrszuLUnMYk5CMmVVlrOOK+Deqztx39BO0kzLxcgWdMIcz4QZW7yddGCNcevmCa0GmFKSo5m3IvV/whwgJMCbf8iGzOIPyDtQomFNT4LuZzTKcveCXhPhoR3SBbGWsgvKznn8aFHFOY8LcZIEumg4WVuNTSV8mwHK2ALOWg3egRDQwuzqHEJmfileHuf+sYwI9rVxNcLRSKCL+quugJWPwbtDjVWeJblGb/K7Vht9youPmF2h3bNYNR/8coDY135Ga42n+9m/zfh6ujNDhlvEBcgYuqifw8mQcA/k7jDCu88kGHj36ftHvWJebQ5iX24Rs+KT2ZJ+nCu7hPLc+F78diD/rFkuM2KjGBstK2fFH5NAF3W39SNjNotvU7jlS2Naoqi1KouVd9bu59+r9+Hn7c4rN/ZhXLTRTCsyOlICXFw0CXRRdyFdoOtIGPkK+Dc3uxqHkpJVyIy4JHblnGBk75Y8OboHoQHeZpclHJwEuqg9rSFxERSkGys82ww2/ohaK6+y8Nqqvby7Lo1m/l68c3t/YnuEm12WcBIS6KJ2ivPgmwcgdbmxMbOlCtylEdTF2Jh2jNkJyRw4WsJNMa155Lpu0kxLNCgJdHFhu7+Frx+AiiJj+7dBf5UmWhehqLyKud+n8vGGdFo38+WTuwYxpFOI2WUJJySBLv5Y0RGImwohnWHcN9Ciu9kVOZSfUnN5NCGZnBPlTB3Snn/EdsHPS37sROOo13eWUioYeA/oCWhgqtZ6fUMUJkyWlwqhUcaCoDu+NjoieniZXZXDyC+p5OllO1mcmEXnsCbE//VS+rVpanZZwsnV91JhPvC91voGpZQXIDvROrrqCvjpWfjl33DjQuh+PbQZZHZVDkNrzbfJOTyxdAeFZVU8MLQT9w7thLeHNNMSja/Oga6UCgSuAO4E0FpXApUNU5YwxeEUWHwPHEmB/ndCx2FmV+RQjpwo57ElKfyw8wi9IoNYdNcgurUMNLss4ULqc4XeAcgDPlBK9QG2ANO11iUNUpmwrd/eMzZo9gmGSV9A1AizK3IYWmu+3JzJM9/uorLayiPXdWXqkPZ4uMsbx8K26hPoHkA/4H6t9Ual1HxgNvD4mQ9SSk0DpgG0adOmHqcTjcovBDr/CUbPB3+ZgVFbGcdKmZ2QxK/7jzGofTNenNCbdiH+ZpclXFSdN7hQSoUDG7TW7Wo+vxyYrbUeeb6vkQ0u7IjWsO0TqCo73XtFa2lxW0snm2m9vHIP7m6KOdd1ZdKANri5yesnGl6jb3ChtT6slMpUSkVprVOBYcDOuj6fsKHiPPhmOqR+a4yTD7jLCHIJ81rZc6SImXFJbMssYGjXMJ4d15OWQdLaVpivvrNc7gc+qZnhkgZMqX9JolHtXm6s+CwvhD89C4P/JkFeS5XVVt5as583ftpLE28P5t/clzF9IlDy+gk7Ua9A11pvAy74a4CwE8f2wxe3QlgPY265LBKqte2ZBcyKT2L34SJG94ngydHdad5EmmkJ+yJL1lxBQQYEt4HmHeGWr6D95cZuQuKCyiotvLpqD++tSyM0wJt374jhmu6y+5KwTxLozqy6An56Dn59HSZ/A+2GQOfhZlflMNbvP8bshCTSj5UyaWAb5lzXlUAfaaYl7JcEurM6shMSpsGRZOg3GVr2Nrsih3GivIrnl+/ms00ZtG3ux6d3D+LSjjKVU9g/CXRnUXQY4qbADR/CziXGHp8+QbJI6AKWJGadtdXbtb3CWbY9h9yicu6+vD1/vyYKXy9Zti8cgwS6s1g7FzI2wNoXjc6IskjogpYkZjEnIZmyKgsAWQVlvLfuAOGB3iT8bQh9WwebXKEQF0cC3dE9E2aMlZ+0+T/GrYe3hPkFzFuReirMz+SmlIS5cEjSbMLRTU8yWtue5OELvSbC9GTzanIQ2QVl5zyeU1hu40qEaBhyhe7ItIatH0N2ovG5hzdYKsA70OhjLs7JatV89lvGee+PCJZVn8IxSaA7KqsVVj4KG96EwEjoHAsDpsLmD6D4iNnV2a2DR0uYnZDEhrR8OoX6k3m8jIpq66n7fT3dmREbZWKFQtSdBLqjUsoYOx/0V2Ofz5N7fI56xdy67FS1xcr7Nc20vNzdeGF8L24a0Jql27LPmuUyIzaKsdGRZpcrRJ3UudtiXUi3xQZQVWZcgTdtZ1ylS1OtC9p9+ASz4pLYfqiQ4d3CeGZsL8KDfMwuS4haa/Rui8IE5YXw2SQoyIT7NoGnjPX+kYpqC//3037e/GkfQb6evD4pmlG9W0ozLeG0JNAdRXEeLBoPuTth3DsS5hewNeM4s+KS2JtbzNi+EfxzdA+a+csm18K5SaA7guPp8PE4OJFtrPyUfiznVVpZzcsr9/D+LwcID/Th/TtjGNpVZvwI1yCB7ghWPQmlR+GOpdBmkNnV2K1f9h1ldkISmfll3Da4DbNGdCVAmmkJFyKBbs9Obgk3+jXj6jysm9kV2aXCsiqeX76Lz3/LpF1zPz6fNpjBHZqbXZYQNieBbq/2/wjr34SbPjaabPkEmV2RXVq54zCPLUnhaHEF91zZgYeGd8HHU5ppCdckgW6PdiyG+LshNAoqiuUN0HM4WlzBk1/vYFlSDl3DA3hvcgy9W0n/FeHaJNDtzeYPYNlD0HoQ3PIF+EpInUlrzZJtWTz1zU5KKyw8fE0X7rmyI14e0pZICAl0e7LpXVj+D6P17cSF4OVndkV2JaugjEcXJ7MmNY/oNsHMndCbzi0CzC5LCLshgW5P2l8JA+6CES+Au8zOOMlq1XyyKYMXlu/CquGfo7oz+dJ2uLvJAiEhziSBbjZLNaTEQ+8bIbQLjHzZ7IrsSlpeMbPjk9l0MJ/LOoXw/PhetG4mv7kIcS4S6GaqKoe4qZD6LQS2hPZXmF2R3ai2WHnvvwd49Yc9eHm4MXdCbybGtJJl+0L8AQl0s5SfgM9vgYPr4Np5EuZn2Jl9gpnx20nJOsGfurfg6bE9aREozbSEuBAJdDOUHIVFE+BICox/D3pPNLsiu1BRbeGNH/fx1pr9BPt58uat/bi2Z7hclQtRSxLoZjicBMf2w82fQpdYs6uxC1vS85kZl8T+vBLG94vk8ZHdaSrNtIS4KBLotlRRDN5NoONQeDAJ/JqZXZHpSiqqmbcilYXrDxIR5MuHUwZwVVSY2WUJ4ZAk0G3l0Bb47CYYPR+6jpQwB9btzWNOQjKHjpdxxyVtmTmiK0285VtSiLqSn57GVHQY4qbAwGmw5F5oEuqyDbaWJGad2uotPMiH1k192XTwOB1C/PnynksY2F7+gxOiviTQG9PauZC+HtI3QFhXuH0xBISbXZXNLUnMYk5CMmVVFgByCsvJKSxneLcw3rilnzTTEqKBSKA3hmfCjA2cT9HGTkPze8NjuaaVZZZ5K1JPhfmZduUUSZgL0YCko1FjmJ4EPSeCR02XRA9f6DURpiebW5cJtNZkFZSd877s8xwXQtSNBHpjcPcCrGCpAA8f49Y7EAJcayu0Q8dLmfzBb+e9PyJY2gIL0ZBkyKWhWarhqzshYz1E3w4D7zZa4hYfMbsym7FaNR9vSOfF73cDML5fJN8l51BWZT31GF9Pd2bERplVohBOSQK9of3wOBxYC2Pfgr63GMdGvWJuTTa0P6+YWXFJbE4/zuWdQ3hunNFM64rOoadmuUQE+zIjNoqx0ZFmlyuEU6l3oCul3IHNQJbWelT9S3JgiZ/Ahjdh8N9Oh7mLqLJYWfBzGvNX78XX052XJvZhQr/IU8v2x0ZHSoAL0cga4gp9OrALCGyA53JcOdth2YNGT/Nrnja7GptKySpkVnwSO7JPcF2vcJ4c04OwAGmmJYSt1SvQlVKtgJHAs8DfG6QiRxUSBYP+Apc9BO6uMZJVXmXh36v38s7PaTT18+Lt2/oxomdLs8sSwmXVN3leA2YCrrsPWFW5MYvFJwj+5DpX5psP5jMzPom0vBIm9m/FYyO7E+QnuywJYaY6B7pSahSQq7XeopS66g8eNw2YBtCmTZu6ns4+aW1s6Jy1GaatdYk9QIsrqpn3/W4+2pBORJAvH00dyBVdQs0uSwhB/a7QhwBjlFLXAT5AoFJqkdb6tjMfpLVeACwAiImJ0fU4n/3Z+DZs/xSunO0SYb52Tx6PJCSTXVjG5EvaMSM2Cn9ppiWE3ajzT6PWeg4wB6DmCv0fvw9zp5a2BlY8Cl1HwZWzzK6mURWUVvKvZTtJ2JpFx1B/4v5yCf3bSjMtIeyNXF7VRf4BY/FQSBcY9za4Oe+C2+XJOfxzaQoFpVXcd3Un7hvaSfqvCGGnGiTQtdZrgDUN8VwOwcMHIvvDtXPB2znfD849Uc4/l+7g+x2H6RkZyMKpA+kREWR2WUKIPyBX6BfDagU0BLaE2+LNrqZRaK35asshnlm2k/JqK7NGdOXuy9vj4e68v4UI4Swk0C/Gz/Pg0G9w0yLwdL6FM5n5pTyyOJl1e48ysF0zXpjQiw6hTcwuSwhRSxLotbX7W1jzHPSZBB7eZlfToCxWzUfrDzJvRSoKeHpsT24d2AY3N2V2aUKIiyCBXhu5uyBhGkT0g1GvgXKeoNuXW8Ss+GS2pB/nqqhQnh3Xi0hpayuEQ5JAv5DSfPhsEnj5w82fOM1QS5XFyjtr9/Pv1fvw83bn1Zv6MLbv6WZaQgjAn9TRAAANqUlEQVTHI4F+IUU5oC1w48cQGGF2NQ0i+VAhM+K2s/twESN7t+SpMT0IaeJcw0hCuCIJ9Atp0QPu2wIeXmZXUm/lVRZeW7WXd9el0dzfi3du709sD9fbtFoIZyWBfj7bv4AjKTD8SacI841px5idkMyBoyXcPKA1c67rRpCvNNMSwplIoJ+p6DDETYHLHoav74fWA0FbAcdZGbkkMeusnYHuH9qRHdlFfLwhndbNfPnkrkEM6RRidplCiEYggX6mtXMhfT1k3w5NWsDEheDuOFexSxKzmJOQTFmVBYCsgjLmJKSggT9f1p6H/9QFPy/5JxfCWclPN8AzYVBdcfrzqlIozIBXu8FjuebVdZHmrUg9FeYnaSC0iTePj+puTlFCCJuR9dwA05Og50Rwr5np4e4FvSbC9GRz67pI2QVl5zx+tLjinMeFEM5FAh0gINxosmWtMkLdWg3egRDQwuzKau3IiXK8Pc79zxkhC4WEcAky5ALGzkN5u6D/FIiZAps/gOIjZldVK1prvtycyTPf7qLKYsXDTVFtPb2PiK+nOzNio0ysUAhhKxLoACnxkLEeLn0AwnvBqFfMrqhWMo6VMjshiV/3H2NQ+2a8OKE32zILzprlMiM2irHRkWaXKoSwAQn08kJY8QhEREOXWLOrqRWLVfPBLwd4aWUqHm5uPDeuFzcPaI2bm6JdiL8EuBAuSgL9p+ehOBcmfQZu9j/ffM+RImbGJbEts4ChXcN4dlxPWgbJGLkQwtUDPScJNr0DMVONHYjsWGW1lbfW7OeNn/YS4OPJ/Jv7MqZPhDTTEkKc4tqBXpwLod1g2ONmV/KHtmcWMCs+id2HixjTJ4InRnenuTTTEkL8jmsHeufh0GmY3fY3L6u08OqqPby3Lo2wAB/euyOG4d0dZyqlEMK2XDPQS/Mh6UsYcBe42+dLsH7/MWYnJJF+rJRbBrVh9rVdCfRxnDYEQgjbs880a2yrnoDET6Dj1RBqX3O0T5RX8fzy3Xy2KYO2zf349O5BXNpRmmkJIS7M9QI9cxNs/Qguvd/uwnz1riM8ujiF3KJypl3RgYeGd8HXy/5n3ggh7INrBbqlGr79OwREwJWzza7mlGPFFTz1zU6+3p5NVIsA3r69P31bB5tdlhDCwbhWoP/2HhxOhhs/Au8mZleD1pqvt2fz1Dc7KSqv4qHhXfjrVR3xOk9PFiGE+COuFegt+8Cgv0C3MWZXQk5hGY8tTmH17lz6tg5m7g296dIiwOyyhBAOzLUCve0lxh8TWa2az37L4Pnlu6m2WnlsZDemDGmPu5t9Tp0UQjgO1wj0tDWwezkM+6epQy0Hj5YwOyGJDWn5XNqxOS+M702b5n6m1SOEcC7OH+jVFfDtP4we59c8ZU4JFivv/3KAl1fuwcvdjRfG9+KmAa1l2b4QokE5f6D/+joc2wu3xoGn7ZtY7T58gllxSWw/VMjwbi14ZmxPwoN8bF6HEML5OXegH0+Hn1+CbqOh8zU2PXVFtYX/+2k/b/60jyBfT964JZqRvVrKVbkQotE4d6D/8DgoNxjxgk1PuzXjOLPiktibW8y46Ej+Oao7Tf29bFqDEML1OHegD38Set4AQa1scrrSympeXrmH9385QHigDx/cOYCru4bZ5NxCCOF8gV50GL6aAhM/hGYdjD+NYEli1llbvV3fN4JvkrLJzC/jtsFtmDWiKwHSTEsIYUPOF+hr50LGr/DeMHggEdwbPlSXJGYxJyGZsioLAFkFZby5Zj8hTbz4YtpgBnVo3uDnFEKIC6lzoCulWgMfAeGAFVigtZ7fUIVdtGfCjCmKJxVmwtMh4OENj+U26KnmrUg9FeZn8nJ3kzAXQpimPk1DqoGHtdbdgMHAvUqp7g1TVh1MT4KeE0HVdCf08IFeE2F6coOfKrug7JzHcwrLG/xcQghRW3UOdK11jtZ6a83HRcAuwLzt5gPCjZ2HtMUIdUsleAdCQMPt8KO1ZnHiITjPzMOIYNmsWQhhngYZQ1dKtQOigY0N8Xx1lrXFuL3lC0j9DoqPNNxTF5Tx6OJk1qTm0baZL4dPVFBRbT11v6+nOzNi7au/uhDCtdQ70JVSTYB44EGt9Ylz3D8NmAbQpk2b+p7uj929GtJ/NRYRNdBCIqtV88mmDF5YvgurhidGd+eOS9rxzfbss2a5zIiNYmy0eb+gCCGE0lrX/YuV8gSWASu01q9c6PExMTF68+bNdT6fraXlFTM7PplNB/O5vHMIz43rRetm0kxLCGFbSqktWuuYCz2uPrNcFPAfYFdtwrxRVVfA57ca28p1uLL+T2ex8u66A7y6ag8+Hm7Mu6E3N/RvJcv2hRB2rT5DLkOA24FkpdS2mmOPaK2X17+si5T8Fez7AQb/td5PtTP7BDPjt5OSdYLYHi14+vqehAVKMy0hhP2rc6Brrf/Leed72JDWRkfFFr2g49A6P015lYU3ftzH22v3E+znxVu39uPaXi0bsFAhhGhcjr9SdO8PkLcbxi0wpi3WwZb0fGbGJbE/r4QJ/Vrx+KhuBPtJMy0hhGNx/ED/9d8QGAk9x1/0l5ZUVDNvRSoL1x8kIsiXhVMHcmWX0IavUQghbMCxA11r6H0TuHtddM+Wn/fkMSchmezCMu4Y3JYZI7rSxNuxXw4hhGtz7ARTCvrdflFfUlhaxdPf7iRuyyE6hPrz5T2XMKBds0YqUAghbMdxA/34QWPj5/6Twcu/Vl/yfUoOjy/dQX5JJX+7qiMPDOuMj6d749YphBA24riBvv5N2Pw+9Bh3wUDPLSrniaU7+C7lMN1bBvLBnQPoGRlko0KFEMI2HDPQS/Mh8WPofSMEnn9qodaa+K1ZPL1sJ2VVFmbERjHtig54utenyaQQQtgnxwz03/4DVaXGytDzyMwv5ZHFyazbe5SYtk15YUJvOoU1sWGRQghhW44X6FXlsOkd6HQNhHX7n7utVs1H6w8yd0UqCvjX9T24bVBb3NzMXwMlhBCNyfECvSQXQrrAkAf+5659ucXMjk9ic/pxrugSynPjetKqqTTTEkK4BscL9OA2MOXsdjFVFisLfk5j/qq9+Hq58/LEPozvFynNtIQQLsWxAv3ITvBrftYuRClZhcyMS2Jnzgmu6xXOU2N6EhrgbWKRQghhDscK9GUPGjNc7vuN8mor81fvZcHPaTTz9+Lt2/oxoqc00xJCuC7HCfSMjZC5EUa8yG/px5kVl0Ta0RIm9m/FYyO7E+R3cUv/hRDC2dh9oC9JzOL979fzYfl0PJUfDyZFsXrJelo19eXjPw/k8s7STEsIIcDOA31JYhZzEpJ5Xv+Hpu7FJFvbsTqtlCs6h/DWbf3xl2ZaQghxil0n4rVL+zDWverU573VQQ763EJFpife3kdNrEwIIeyPXa+Bv7z8NZZUX0qZNjabKNNeLK4ewmXl802uTAgh7I9dB7pncATF+OJNFeXaE2+qKMYXr2CZzSKEEL9n14E+IzaKMLcTLLIMY1zlv1hkGUYLt0JmxEaZXZoQQtgduw70sdGRlI5byDtN7mW3bss7Te6ldNxCxkZHml2aEELYHbt+UxSMUJcAF0KIC7PrK3QhhBC1J4EuhBBOQgJdCCGchAS6EEI4CQl0IYRwEkprbbuTKZUHpNvshI0jBJC+AwZ5Lc4mr8fZ5PU4rb6vRVut9QU7Edo00J2BUmqz1jrG7DrsgbwWZ5PX42zyepxmq9dChlyEEMJJSKALIYSTkEC/eAvMLsCOyGtxNnk9ziavx2k2eS1kDF0IIZyEXKELIYSTkECvBaVUa6XUT0qpXUqpHUqp6WbXZA+UUu5KqUSl1DKzazGbUipYKRWnlNpd831yidk1mUUp9VDNz0mKUuozpZSP2TXZklLqfaVUrlIq5YxjzZRSPyil9tbcNm2Mc0ug10418LDWuhswGLhXKdXd5JrswXRgl9lF2In5wPda665AH1z0dVFKRQIPADFa656AO3CzuVXZ3IfAiN8dmw2s1lp3BlbXfN7gJNBrQWudo7XeWvNxEcYPq0v39FVKtQJGAu+ZXYvZlFKBwBXAfwC01pVa6wJzqzKVB+CrlPIA/IBsk+uxKa31z0D+7w5fDyys+XghMLYxzi2BfpGUUu2AaGCjuZWY7jVgJmA1uxA70AHIAz6oGYJ6Tynlb3ZRZtBaZwEvARlADlCotV5pblV2oYXWOgeMC0QgrDFOIoF+EZRSTYB44EGt9Qmz6zGLUmoUkKu13mJ2LXbCA+gHvKW1jgZKaKRfqe1dzdjw9UB7IALwV0rdZm5VrkMCvZaUUp4YYf6J1jrB7HpMNgQYo5Q6CHwODFVKLTK3JFMdAg5prU/+1haHEfCuaDhwQGudp7WuAhKAS02uyR4cUUq1BKi5zW2Mk0ig14JSSmGMj+7SWr9idj1m01rP0Vq30lq3w3jD60ettctehWmtDwOZSqmTu5cPA3aaWJKZMoDBSim/mp+bYbjoG8S/8zUwuebjycDSxjiJ3e8paieGALcDyUqpbTXHHtFaLzexJmFf7gc+UUp5AWnAFJPrMYXWeqNSKg7YijE7LBEXWzGqlPoMuAoIUUodAp4AXgC+VEr9GeM/vYmNcm5ZKSqEEM5BhlyEEMJJSKALIYSTkEAXQggnIYEuhBBOQgJdCCGchAS6EEI4CQl0IYRwEhLoQgjhJP4fscGbFa+br5UAAAAASUVORK5CYII=\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# visualize\n",
    "y = linda\n",
    "fig, ax = plt.subplots()\n",
    "ax.plot(linda, y, 'o-')\n",
    "ax.plot(logda, y, '*--')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x2c408bf9a58>]"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# linspace 適合用來生成數列代入函數求得一系列的函數值\n",
    "from numpy import pi\n",
    "x = np.linspace(0, 2*pi, 100)\n",
    "y = np.sin(x)\n",
    "\n",
    "fig, ax = plt.subplots()\n",
    "ax.plot(x, y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.colorbar.Colorbar at 0x2c408cc45c0>"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Uniform 分佈的隨機亂數\n",
    "image = np.random.rand(30, 30)\n",
    "\n",
    "# 二維的陣列資料都可以當成影像顯示\n",
    "plt.imshow(image)\n",
    "plt.colorbar()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id=\"indexing-slicing\"></a>\n",
    "\n",
    "## 11.2 索引及片段 Indexing and Slicing\n",
    "\n",
    "### § 基本索引與片段\n",
    "\n",
    "`ndarray` 基本的索引和片段語法,與使用 Python 序列容器(如:List)的語法雷同,都是使用中括號內置索引序號或冒號間隔的片段範圍:\n",
    "+ 一維 `vector[index]`,二維 `matrix[index1, index2]`,高維 `array[index1, index2, index3, ...]`。\n",
    "+ 一維片段 `vector[start:end:step]`,二維片段 `matrix[start:end:step, start:end:step]`,高維片段 array 類推。\n",
    "\n",
    "片段的索引方式可以放在等號左邊,用來直接對原陣列的片段指派新的值。存取陣列的片段,返回的是原陣列裡的參考 view,不是複製一個新的陣列,如果明確需要另外複製一份相同內容的陣列,可以使用 **copy** 函式,`np.copy()` 或 `ndarray.copy()` 都可以用。\n",
    "\n",
    "以下索引及片段示意圖來自 *scipy-lectures.org*\n",
    "\n",
    "![numpy indexing](http://scipy-lectures.org/_images/numpy_indexing.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Amat =\n",
      " [[ 0  1  2  3]\n",
      " [ 4  5  6  7]\n",
      " [ 8  9 10 11]] \n",
      "\n"
     ]
    }
   ],
   "source": [
    "Amat = np.arange(12).reshape((3,4))\n",
    "print('Amat =\\n', Amat, '\\n')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 1, 2, 3])"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 索引維度若小於實際維度時,返回的是子陣列的參考\n",
    "Amat[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Amat[0][2] = 2,Amat[0, 2] = 2,兩種索引方式存取同一個位置的元素,\n",
      "但 Amat[0][2] 效率較差,因為 Amat[0] 會先產生一個暫時的陣列物件才存取索引2元素。\n"
     ]
    }
   ],
   "source": [
    "# 所以個別元素的存取,也可以使用另外一種效率較差的索引方式\n",
    "print('Amat[0][2] = {},Amat[0, 2] = {},兩種索引方式存取同一個位置的元素,\\n'\n",
    "      '但 Amat[0][2] 效率較差,因為 Amat[0] 會先產生一個暫時的陣列物件才存取索引2元素。'\n",
    "      .format(Amat[0][2], Amat[0, 2]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  7,  2,  7],\n",
       "       [ 4,  7,  6,  7],\n",
       "       [ 8,  7, 10,  7]])"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 片段可以放在等號左邊,用來直接對原陣列的片段指派新的值\n",
    "Amat[:, 1::2] = 7\n",
    "Amat"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Amat =\n",
      " [[ 0  7  2  7]\n",
      " [ 4  7  6  7]\n",
      " [ 8  7 10  7]] \n",
      "\n",
      "AsliceCopy =\n",
      " [[9 9]\n",
      " [9 9]\n",
      " [9 9]]\n"
     ]
    }
   ],
   "source": [
    "# 明確複製新的物件\n",
    "AsliceCopy = Amat[:, 1::2].copy()\n",
    "# 更改元素值\n",
    "AsliceCopy[:] = 9\n",
    "\n",
    "# 不會更改到原陣列\n",
    "print('Amat =\\n', Amat, '\\n')\n",
    "print('AsliceCopy =\\n', AsliceCopy)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### § 索引技巧 - 使用布林陣列\n",
    "\n",
    "陣列索引的中括號裡可以使用另外一個相同形狀及大小的 boolean 陣列(元素都是 `True` 或 `False` 的 `bool` 型態陣列),這種用法的 boolean 陣列又稱為遮罩(**mask**),索引的結果,會返回“複製”索引結果的元素值的一維陣列。 \n",
    "\n",
    "如果遮罩陣列的維度比被索引的陣列還要少的時候,不足的維度視爲片段全選。 例如: 若 `A` 爲二維陣列,`mask` 是一維的遮罩,則 `A[mask]` 等同於 `A[mask, :]`。 若索引結果無法形成有效的陣列形狀,則視爲錯誤的陳述。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0.5, 1.0, 'Original Image')"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 產生 [0, 255] 區間的亂數\n",
    "I = np.random.randint(0, 256, size=(16,16))\n",
    "\n",
    "# 準備將二維矩陣顯示成影像\n",
    "fig1, ax1 = plt.subplots()\n",
    "# 顯示原本的亂數影像\n",
    "ax1.imshow(I, cmap='gray')\n",
    "ax1.set_title('Original Image')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0.5, 1.0, 'Mask image')"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 取門檻值後作為遮罩,\"<\" 的比較運算下在一節中詳細介紹\n",
    "mask = I < 128\n",
    "# 顯示遮罩成影像\n",
    "fig2, ax2 = plt.subplots()\n",
    "ax2.imshow(mask, cmap='gray')\n",
    "ax2.set_title('Mask image')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0.5, 1.0, 'I[mask] set to 0')"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAP8AAAEICAYAAACQ6CLfAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAFXdJREFUeJzt3XnQHHWdx/H3h5CABMgBIgkg97JGgZgKghci4cY1WqsCIrIgUhYr4gKFofBg2S1WUViOxSOIEBQkXlwWQRJRUEsiIZuEIxwPAZKQyBlCgGAS+e4f03Enw0wy/ZueSR5/n1fVU89M9+/bv+/T83yne3q6+6eIwMzys9H6TsDM1g8Xv1mmXPxmmXLxm2XKxW+WKRe/WaZc/GaZcvH3mKRzJa2U9LKkwT3uOyTt1mLeY5JWSPpRL3Oy9cfF3wOSnpB0UN2kyRGxeUS8st6SahARuwLnV71cSVdL+s91tGn5ptRmH6Ml3Svp1eL36NRl5cTFb/2apEHATcCPgGHAJOCmYrqthYt/A1BsHb8taUrxceAPkraVdLGkJZIekvTOuvYTit30ZZIelPTRunm7SbpT0lJJz0ma3KLP90laIOmDbebYcrmS/lHSVEkvSHpY0ieK6ScDxwJnFX/XLU2We1fxcHbR5qhi+mcl9RXLvFnSyBapHQBsDFwcEX+JiEsBAQe283flzMW/4fgE8GVga+AvwB+BmcXznwEX1bV9DHg/MAT4d+BHkkYU8/4DuJ3aVnB74LLGjiQdCvwY+OeI+E2b+TVdbnHcYipwHbANcAzwbUlvj4iJwLXABcXHnH9qXGhE7F883LtoM1nSgcB/FetkBPAkcH2LvN4OzIk1L1KZU0y3tXDxbzhuiIh7I+I14AbgtYi4JiL+CkwG/rblj4ifRsSiiHg9IiYDjwLvKmavBHYERkbEaxHx+4Z+Pg5MBI6IiD+VyK/Vcj8EPBERV0XEqoiYCfwc+Fipv35NxwI/iIiZEfEX4Gzg3ZJ2atJ2c2Bpw7SlwBYd9J8FF/+G4+m6x8ubPN989RNJn5Y0S9KLkl4E3kFtDwHgLGq7vX+S9ICkExv6+SLwk4i4r2R+rZa7I7Dv6lyKfI4Fti25/HojqW3tAYiIl4Hnge2atH0Z2LJh2pbAsg76z8LG6zsBK0fSjsAVwDjgjxHxV0mzqBUmEfFn4LNF2/cB0yTdFRF9xSI+Dlwp6amIuLjdflstF1gA3BkRB7cKLf1HwiJqbyoU/Q0GtgKeatL2AeAMSarb9d8LuDyh36x4y9//DKZWUM8CSDqB2paf4vnHJW1fPF1StP1rXfwiam8cX5B0SrudrmW5vwT+QdJxkgYWP/tIelvR9mlgl3UsvrHNdcAJxVd4m1D7CnJ6RDzRJPa3RR5fkLSJpM8X0+9o92/LlYu/n4mIB4ELqR0QfBrYE/hDXZN9gOmSXgZuBk6LiMcbljGf2hvAlySd1GbXTZcbEcuAQ4Cjqb2x/Bn4BrBJEXclMKr4SHBji2WfC0wq2nwiIn4NfIXasYPFwK7F8putjxXAR4BPAy8CJwIfKabbWsh38uktSV+mdgBrJbDdhnKij6SHqX2m/klENB4nsL9DLn6zTHm33yxTLn6zTPX0q74hQ4bEttuW//p35cqVpWMef/zxdTdqYvTo8teErFiRdmxp6dLGc1Pa89RTzb7x6o4xY8Ykxb3ySvlDGYMHp13kKKl0TOrH3VWrViXFDRgwoHTMs88+WzpmyZIlvPzyy22tkJ5+5t9jjz3ie9/7Xum4RYsWlY459thjS8cAvPDCC6Vj5s+fn9TXlClTkuLOPvvspLgUy5cvT4qbOXNm6Zh99tknqa+NNiq/A5uyQYH0N+wtt2w8D2ndUmrlwgsvZMGCBW0Vv3f7zTLl4jfLVEfFL+mw4hLOPkkTqkrKzLovufglDaB2/vThwCjgGEmjqkrMzLqrky3/u4C+iJhXnEp5PTC+mrTMrNs6Kf7tqF3RtdpCmlxyKelkSTMkzUg9Umpm1euk+Jt9nfCG7w0jYmJEjI2IsUOGDOmgOzOrUifFvxDYoe759tSu6jKzfqCT4r8H2F3SzsWdUo+mdqmnmfUDyaf3RsSq4sYJvwIGULvn2gOVZWZmXdXRuf0RcStwa0W5mFkP+Qw/s0z19Kq+Rx55hA9+sK0xItab4cOHl46ZMWNGUl+pF+jMnj27dMwNN9yQ1Neb3vSmpLgUqRc6HX744aVjpk2bltTXTjvtlBSXcjXrddddVzpm4MCBbbf1lt8sUy5+s0y5+M0y5eI3y5SL3yxTLn6zTLn4zTLl4jfLlIvfLFMufrNMufjNMuXiN8tUTy/s2WuvvZIu3thuuzfcGnCdLrrootIxAKeffnrpmIULFyb1lWrvvfcuHbNs2bKkvr7yla8kxaUMT3XPPfck9ZXioIMOSop7+OGHK86ktU9+8pNdXb63/GaZcvGbZcrFb5apTkbs2UHSbyTNlfSApNOqTMzMuquTA36rgDMiYqakLYB7JU2NiAcrys3Muih5yx8RiyNiZvF4GTCXJiP2mNmGqZLP/JJ2At4JTG8y72/DdT3//PNVdGdmFei4+CVtDvwc+GJEvNQ4v364rq222qrT7sysIh0Vv6SB1Ar/2oj4RTUpmVkvdHK0X8CVwNyISDudzszWm062/O8FjgMOlDSr+DmiorzMrMs6Gavv9zQfptvM+gGf4WeWKUVE7zqTkjr7+te/XjpmwoQJKV0lWb58eVJcL4fCsjX19fUlxe22224VZ1K9iGhrj9xbfrNMufjNMuXiN8uUi98sUy5+s0y5+M0y5eI3y5SL3yxTLn6zTLn4zTLl4jfLlIvfLFM9Ha5r1KhRTJ48uXTc0KFDS8ecdlrancTnzp1bOsYX6LzRFVdcUTrmuOOOS+pr0003LR0zbdq0pL5eeukNd6pry6RJk0rHnHrqqUl9tctbfrNMufjNMuXiN8tUFbfuHiDpfyX9soqEzKw3qtjyn0ZttB4z60c6vW//9sCRwPerScfMeqXTLf/FwFnA6xXkYmY91MmgHR8CnomIe9fR7m9j9S1ZsiS1OzOrWKeDdnxY0hPA9dQG7/hRY6P6sfqGDRvWQXdmVqVOhug+OyK2j4idgKOBOyLiU5VlZmZd5e/5zTJVybn9EfFb4LdVLMvMesNbfrNM9YvhulasWFE6ZtCgQSldJUkd+unFF19Mihs7dmzpmOuvvz6pry222CIp7sgjj0yK65VFixYlxY0cOTIp7rnnnisds/XWWyf15eG6zGytXPxmmXLxm2XKxW+WKRe/WaZc/GaZcvGbZcrFb5YpF79Zplz8Zply8ZtlysVvlikXv1mm+sVVfX+vrrnmmqS4N7/5zaVjDjjggKS+li9fnhT3u9/9rnTM+PHjk/pKcd999yXFTZ8+PSlu3LhxpWMWLlxYOuakk07ioYce8lV9Ztaai98sUy5+s0x1OmLPUEk/k/SQpLmS3l1VYmbWXZ3ewPMS4LaI+JikQcBmFeRkZj2QXPyStgT2B/4FICJWAOVvtmdm60Unu/27AM8CVxVDdH9f0uDGRvXDdXXQl5lVrJPi3xgYA3wnIt4JvAJMaGxUP1xXB32ZWcU6Kf6FwMKIWH3Ww8+ovRmYWT/QyVh9fwYWSNqjmDQOeLCSrMys6zo92n8qcG1xpH8ecELnKZlZL3RU/BExC/BnebN+qJKBOrttzpw5pWOmTZuW1Nfpp59eOiZlODGAZcuWJcVttdVWpWPuvvvupL6efPLJpLjXXnstKa5X9txzz572N3/+/NIx73//+7uQyf/z6b1mmXLxm2XKxW+WKRe/WaZc/GaZcvGbZcrFb5YpF79Zplz8Zply8ZtlysVvlikXv1mmXPxmmeoXV/XttddepWPOO++8pL5mzCh/q8FBgwYl9ZU6XNe8efNKx+yyyy5JfaW66aabetpfWZdddllS3KmnnpoU99a3vrV0zPnnn1865vLLL2+7rbf8Zply8ZtlysVvlqlOh+v6N0kPSLpf0o8lbVpVYmbWXcnFL2k74AvA2Ih4BzAAOLqqxMysuzrd7d8YeJOkjamN07eo85TMrBc6uW//U8C3gPnAYmBpRNze2M7DdZltmDrZ7R8GjAd2BkYCgyV9qrGdh+sy2zB1stt/EPB4RDwbESuBXwDvqSYtM+u2Top/PrCfpM0kidpwXXOrScvMuq2Tz/zTqQ3OORO4r1jWxIryMrMu63S4rq8BX6soFzPrIZ/hZ5apnl7VN3r0aO64447SccOHDy8d89WvfrV0DMApp5xSOiZ1HLxtttkmKe6HP/xhUlyKlNcL0q487KUBAwas7xTWadSoUaVjNt20/ZNsveU3y5SL3yxTLn6zTLn4zTLl4jfLlIvfLFMufrNMufjNMuXiN8uUi98sUy5+s0y5+M0ypYjoXWdSUmdXXXVV6ZgTTjghpaskV199dVLcoYcemhQ3YsSIpLheev3110vHbLTRhr8tevDBB5PiUi7SSRURaqfdhr+2zawrXPxmmXLxm2VqncUv6QeSnpF0f9204ZKmSnq0+D2su2maWdXa2fJfDRzWMG0C8OuI2B34dfHczPqRdRZ/RNwFvNAweTwwqXg8CfhIxXmZWZel3sPvLRGxGCAiFktqeTM6SScDJyf2Y2Zd0vUbeEbERIr7+ad+z29m1Us92v+0pBEAxe9nqkvJzHohtfhvBo4vHh8P3FRNOmbWK+181fdj4I/AHpIWSvoM8HXgYEmPAgcXz82sH1nnZ/6IOKbFrHEV52JmPeQz/Mwy1S+u6kvJsTZquK32rW99KynuyCOPTIp729veVjrm1ltvTerrwAMPLB1z2223JfV12GGN57u1Z9asWaVj9ttvv6S+fFWfma2Vi98sUy5+s0y5+M0y5eI3y5SL3yxTLn6zTLn4zTLl4jfLlIvfLFMufrNMufjNMtXTC3t23333uOSSS0rHpQz9tP/++5eOAZg/f37pmJSLNgA233zzpLh58+aVjjnjjDOS+rrnnnuS4vbZZ5+kuBQXXHBB6ZhXX301qa9zzz03Ke72228vHfPKK6+UjjnzzDPp6+vzhT1m1pqL3yxTLn6zTKUO1/VNSQ9JmiPpBklDu5ummVUtdbiuqcA7ImIv4BHg7IrzMrMuSxquKyJuj4hVxdO7ge27kJuZdVEVn/lPBKa0minpZEkzJM1YunRpBd2ZWRU6Kn5J5wCrgGtbtYmIiRExNiLGDhkypJPuzKxCyWP1SToe+BAwLnp5ppCZVSKp+CUdBnwJ+EBEpJ0qZWbrVepwXf8DbAFMlTRL0ne7nKeZVSx1uK4ru5CLmfWQz/Azy1TyAb8UfX19ScM/TZo0qXRMf/hmYcqUlt+QrlXKFXqzZ89O6mvvvfdOirvxxhtLx4wcOTKpr5SrI2+55ZakvlKNHTu2dMyll15aOqbM1Yre8ptlysVvlikXv1mmXPxmmXLxm2XKxW+WKRe/WaZc/GaZcvGbZcrFb5YpF79Zplz8Zply8Ztlqqdj9Uny7b76mdRxCFPGVxwzZkxSXynuvPPOpLgPfOADFWfS2sqVK0vH7Lvvvtx7770eq8/MWnPxm2UqabiuunlnSgpJW3cnPTPrltThupC0A3AwUH5AezNb75KG6yr8N3AW4IN4Zv1Q6n37Pww8FRGzpbUfWJR0MnBySj9m1j2li1/SZsA5wCHttI+IicDEItZ7CWYbiJSj/bsCOwOzJT1BbYTemZK2rTIxM+uu0lv+iLgP2Gb18+INYGxEPFdhXmbWZanDdZlZP5c6XFf9/J0qy8bMesZn+JllqqfDdaWaPn166Zh99923C5k0t2DBgqS4lItfAIYOHVo6JnX4stRhrY466qikuBTnnXde6Zjly5d3IZPWUoZmGzhwYBcy+X/e8ptlysVvlikXv1mmXPxmmXLxm2XKxW+WKRe/WaZc/GaZcvGbZcrFb5YpF79Zplz8Zply8ZtlqtfDdT0LPNli9tbAhnA3IOexJuexpg09jx0j4s3tLKCnxb82kmZExFjn4TycR2/y8G6/WaZc/GaZ2pCKf+L6TqDgPNbkPNb0d5PHBvOZ38x6a0Pa8ptZD7n4zTLV0+KXdJikhyX1SZrQZP4mkiYX86dL2qkLOewg6TeS5kp6QNJpTdocIGmppFnFz1erzqOuryck3Vf0M6PJfEm6tFgncySNqbj/Per+zlmSXpL0xYY2XVsfkn4g6RlJ99dNGy5pqqRHi9/DWsQeX7R5VNLxXcjjm5IeKtb7DZKa3jZ5Xa9hBXmcK+mpuvV/RIvYtdbXG0RET36AAcBjwC7AIGA2MKqhzSnAd4vHRwOTu5DHCGBM8XgL4JEmeRwA/LJH6+UJYOu1zD8CmAII2A+Y3uXX6M/UThTpyfoA9gfGAPfXTbsAmFA8ngB8o0nccGBe8XtY8XhYxXkcAmxcPP5GszzaeQ0ryONc4Mw2Xru11lfjTy+3/O8C+iJiXkSsAK4Hxje0GQ9MKh7/DBindY0BXlJELI6ImcXjZcBcYLsq+6jYeOCaqLkbGCppRJf6Ggc8FhGtzsKsXETcBbzQMLn+/2AS8JEmoYcCUyPihYhYAkwFDqsyj4i4PSJWFU/vpjYobVe1WB/taKe+1tDL4t8OqB/dYiFvLLq/tSlW+lJgq24lVHyseCfQbFSQd0uaLWmKpLd3KwcggNsl3Svp5Cbz21lvVTka+HGLeb1aHwBviYjFUHuzpm5g2Dq9XC8AJ1LbA2tmXa9hFT5ffPz4QYuPQaXXRy+Lv9kWvPF7xnbaVELS5sDPgS9GxEsNs2dS2/XdG7gMuLEbORTeGxFjgMOBf5W0f2OqTWIqXyeSBgEfBn7aZHYv10e7evm/cg6wCri2RZN1vYad+g6wKzAaWAxc2CzNJtPWuj56WfwLgR3qnm8PLGrVRtLGwBDSdoHWStJAaoV/bUT8onF+RLwUES8Xj28FBkrauuo8iuUvKn4/A9xAbfetXjvrrQqHAzMj4ukmOfZsfRSeXv3Rpvj9TJM2PVkvxYHEDwHHRvHhulEbr2FHIuLpiPhrRLwOXNFi+aXXRy+L/x5gd0k7F1uZo4GbG9rcDKw+avsx4I5WKzxVcQzhSmBuRFzUos22q481SHoXtfX0fJV5FMseLGmL1Y+pHWC6v6HZzcCni6P++wFLV+8SV+wYWuzy92p91Kn/PzgeuKlJm18Bh0gaVuwGH1JMq4ykw4AvAR+OiFdbtGnnNew0j/pjPB9tsfx26mtNVRyhLHEk8whqR9cfA84ppp1HbeUCbEptt7MP+BOwSxdyeB+13aE5wKzi5wjgc8DnijafBx6gdsT0buA9XVofuxR9zC76W71O6nMRcHmxzu4DxnYhj82oFfOQumk9WR/U3nAWAyupbb0+Q+04z6+BR4vfw4u2Y4Hv18WeWPyv9AEndCGPPmqfo1f/n6z+JmokcOvaXsOK8/hh8drPoVbQIxrzaFVfa/vx6b1mmfIZfmaZcvGbZcrFb5YpF79Zplz8Zply8ZtlysVvlqn/A6coh78P0/2JAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 遮罩陣列當成索引陣列,將原陣列中符合門檻值條件的元素都設成 0\n",
    "I[mask] = 0\n",
    "# 顯示修改後的二維矩陣成影像\n",
    "fig3, ax3 = plt.subplots()\n",
    "ax3.imshow(I, cmap='gray')\n",
    "ax3.set_title('I[mask] set to 0')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([252, 253, 254, 255, 251])"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 遮罩索引的結果,會返回索引結果的元素值的一維陣列\n",
    "I[I > 250]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 0  1  2  3  4  5  6]\n",
      " [ 7  8  9 10 11 12 13]\n",
      " [14 15 16 17 18 19 20]\n",
      " [21 22 23 24 25 26 27]\n",
      " [28 29 30 31 32 33 34]]\n"
     ]
    }
   ],
   "source": [
    "# 5 x 7 陣列\n",
    "Amat = np.arange(35).reshape(5,7)\n",
    "print(Amat)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 7,  8,  9, 10, 11, 12, 13],\n",
       "       [28, 29, 30, 31, 32, 33, 34]])"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 遮罩陣列比被索引陣列的維度還要少時,不足的維度視爲片段全選\n",
    "mask = np.array([False, True, False, False, True])\n",
    "Amat[mask]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### § 索引技巧 - 使用整數索引陣列\n",
    "\n",
    "整數索引陣列裡的整數就是索引的序號,正整數或負整數的規則與單一索引值相同。 在索引陣列中,相同的索引序號可以重複出現,其結果就是重複選取相同元素。\n",
    "+ 對一維的陣列而言,索引陣列會返回一個結果的陣列,其維度與索引陣列相同。 \n",
    "+ 對高維的陣列而言,若索引陣列的維度比較少,不足的維度視爲片段全選。\n",
    "+ 片段、遮罩陣列、整數索引陣列可以同時穿插使用。\n",
    "\n",
    "以下索引技巧及片段示意圖來自 *scipy-lectures.org*\n",
    "\n",
    "![array of integer indexing](http://scipy-lectures.org/_images/numpy_fancy_indexing.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "v = [ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23\n",
      " 24 25 26 27 28 29 30 31 32 33 34]\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "array([ 7,  7, 21, 23, 28, 30])"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "v = np.arange(35)\n",
    "print('v =', v)\n",
    "\n",
    "# 一維索引陣列,注意索引陣列是 Python List\n",
    "v[[7, 7, 21, 23, -7, -5]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 7  7]\n",
      " [21 23]\n",
      " [28 30]]\n"
     ]
    }
   ],
   "source": [
    "# 返回索引結果與索引陣列維度及形狀相同\n",
    "print(v[np.array([[7, 7], [21, 23], [-7, -5]])])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 0  1  2  3  4  5  6 99  8  9 10 11 12 13 14 15 16 17 18 19 20 99 22 99\n",
      " 24 25 26 27 99 29 99 31 32 33 34]\n"
     ]
    }
   ],
   "source": [
    "# 可以直接指派新值給這樣的索引位置\n",
    "v[np.array([[7, 7], [21, 23], [-7, -5]])] = 99\n",
    "print(v)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 0  1  2  3  4  5  6]\n",
      " [99  8  9 10 11 12 13]\n",
      " [14 15 16 17 18 19 20]\n",
      " [99 22 99 24 25 26 27]\n",
      " [99 29 99 31 32 33 34]]\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "array([[99,  8,  9, 10, 11, 12, 13],\n",
       "       [99, 22, 99, 24, 25, 26, 27],\n",
       "       [99, 29, 99, 31, 32, 33, 34]])"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 索引陣列的維度比較少,不足的維度視爲片段全選\n",
    "v.shape = (5, 7)\n",
    "print(v)\n",
    "\n",
    "v[np.array([1, 3, 4])]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id=\"shape-manipulation\"></a>\n",
    "\n",
    "## 11.3 陣列形狀的操作\n",
    "\n",
    "陣列因不同運算的需求,經常會需要操作[形狀的改變](https://docs.scipy.org/doc/numpy/reference/routines.array-manipulation.html),如:轉置、增減維度、一維平坦化、堆疊串接、分拆重組等。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### § 一維平坦化 Flatten"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Amat =\n",
      " [[1 2 3]\n",
      " [4 5 6]\n",
      " [7 8 9]]\n",
      "Amat reshape = [1 2 3 4 5 6 7 8 9]\n",
      "Amat flatten = [1 2 3 4 5 6 7 8 9]\n"
     ]
    }
   ],
   "source": [
    "Amat = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])\n",
    "print('Amat =\\n', Amat)\n",
    "\n",
    "# 一維 row-major 平坦化,返回原陣列的 view(同物件參考)\n",
    "print('Amat reshape =', Amat.reshape(-1))\n",
    "\n",
    "# 一維 row-major 平坦化,返回原陣列的 copy\n",
    "print('Amat flatten =', Amat.flatten())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### § 轉置 Transpose"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Amat.T =\n",
      " [[1 4 7]\n",
      " [2 5 8]\n",
      " [3 6 9]]\n",
      "numpy.transpose(Amat) =\n",
      " [[1 4 7]\n",
      " [2 5 8]\n",
      " [3 6 9]]\n"
     ]
    }
   ],
   "source": [
    "# transpose\n",
    "print('Amat.T =\\n', Amat.T)\n",
    "print('numpy.transpose(Amat) =\\n', np.transpose(Amat))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### § 增減維度"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Aflat shape(9,) = [1 2 3 4 5 6 7 8 9]\n"
     ]
    }
   ],
   "source": [
    "Aflat = Amat.reshape(-1)\n",
    "print('Aflat shape{} = {}'.format(Aflat.shape, Aflat))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Aexp0 shape(1, 9) = [[1 2 3 4 5 6 7 8 9]]\n"
     ]
    }
   ],
   "source": [
    "# 擴增維度,以下操作與 Aflat[np.newaxis, :] 相同\n",
    "#Aexp0 = np.expand_dims(Aflat, axis=0)\n",
    "Aexp0 = Aflat[np.newaxis, :]\n",
    "print('Aexp0 shape{} = {}'.format(Aexp0.shape, Aexp0))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Aexp1 shape(9, 1) = [[1]\n",
      " [2]\n",
      " [3]\n",
      " [4]\n",
      " [5]\n",
      " [6]\n",
      " [7]\n",
      " [8]\n",
      " [9]]\n"
     ]
    }
   ],
   "source": [
    "# 擴增維度,以下操作與 Aflat[:, np.newaxis] 相同\n",
    "Aexp1 = np.expand_dims(Aflat, axis=1)\n",
    "print('Aexp1 shape{} = {}'.format(Aexp1.shape, Aexp1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Aexp0 squeeze to (9,) = [1 2 3 4 5 6 7 8 9]\n"
     ]
    }
   ],
   "source": [
    "# 移除陣列的單一維度\n",
    "Asqueeze = np.squeeze(Aexp0)\n",
    "print('Aexp0 squeeze to {} = {}'.format(Asqueeze.shape, Asqueeze))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### § 堆疊、串接、重組\n",
    "\n",
    "許多 numpy 操作或運算陣列的方法都有一個 `axis` 參數,例如以下範例中示範的 [`concatenate`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.concatenate.html)。 這個 `axis` 參數通常是用來指定該方法要套用的方向:\n",
    "\n",
    "+ 第一個維度(`axis=0`)是列(**row**)方向或稱垂直(**vertical**)方向\n",
    "+ 第二個維度(`axis=1`)的行(**column**)方向或稱水平(**horizontal**)方向\n",
    "+ 其他更高維度的方向(axis = 2, 3, 4, ...)\n",
    "\n",
    "有的方法還可以使用 `axis=None` 的設定,這個無軸向的操作則視不同方法有不同的意義。\n",
    "\n",
    "| row0 | col1 | col2 | col3 | col4 | ...  | colN  |\n",
    "|------|----- |----- |----- |----- |----- |-----  |\n",
    "| row1 |  \n",
    "| row2 |\n",
    "| row3 |\n",
    "| row4 |\n",
    "| ...  |\n",
    "| rowN |\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0. 0. 0.]\n",
      " [0. 0. 0.]\n",
      " [0. 0. 0.]] \n",
      "\n",
      "[[1. 1. 1.]\n",
      " [1. 1. 1.]\n",
      " [1. 1. 1.]] \n",
      "\n",
      "[[0. 0. 0. 1. 1. 1.]\n",
      " [0. 0. 0. 1. 1. 1.]\n",
      " [0. 0. 0. 1. 1. 1.]]\n"
     ]
    }
   ],
   "source": [
    "# 建立一黑一白的 3 x 3 陣列\n",
    "B, W = np.zeros((3,3)), np.ones((3,3))\n",
    "print(B, '\\n'); print(W, '\\n')\n",
    "\n",
    "# 沿水平方向串接\n",
    "BnW = np.concatenate((B, W), axis=1)\n",
    "print(BnW)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1. 1. 1. 0. 0. 0.]\n",
      " [1. 1. 1. 0. 0. 0.]\n",
      " [1. 1. 1. 0. 0. 0.]] \n",
      "\n"
     ]
    }
   ],
   "source": [
    "# 翻轉,用 axis 參數指定翻轉方向\n",
    "WnB = np.flip(BnW, axis=1)\n",
    "print(WnB, '\\n')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0. 0. 0. 1. 1. 1.]\n",
      " [0. 0. 0. 1. 1. 1.]\n",
      " [0. 0. 0. 1. 1. 1.]\n",
      " [1. 1. 1. 0. 0. 0.]\n",
      " [1. 1. 1. 0. 0. 0.]\n",
      " [1. 1. 1. 0. 0. 0.]]\n"
     ]
    }
   ],
   "source": [
    "# 沿垂直方向串接\n",
    "BnW_WnB = np.concatenate((BnW, WnB), axis=0)\n",
    "print(BnW_WnB)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x2c408ead048>"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 重複區塊如貼瓷磚\n",
    "ChessBoard = np.tile(BnW_WnB, (2,2))\n",
    "fig, ax = plt.subplots()\n",
    "ax.imshow(ChessBoard, cmap='gray')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id=\"numerical-operations\"></a>\n",
    "\n",
    "## 11.4 數值陣列運算\n",
    "\n",
    "### § Element-wise 算數及比較運算\n",
    "\n",
    "`ndarray` 常用的算數及比較運算操作是定義為對每個元素的逐項(element-wise)操作,然後返回運算結果的 `ndarray` 物件。\n",
    "\n",
    "+ **比較運算子** - 運算結果返回 `bool` 陣列。\n",
    "\n",
    "| 比較運算操作           | 說明          |\n",
    "|------------------------|---------------|\n",
    "| **X < Y**              | 小於          |\n",
    "| **X <= Y**             | 小於或等於    |\n",
    "| **X > Y**              | 大於          |\n",
    "| **X >= Y**             | 大於或等於    |\n",
    "| **X == Y**             | 等於          |\n",
    "| **X != Y**             | 不等於        |\n",
    "| **logical_and(X, Y)**  | 真值邏輯 AND  |\n",
    "| **logical_or(X, Y)**   | 真值邏輯 OR   |\n",
    "| **logical_xor(X, Y)**  | 真值邏輯 XOR  |\n",
    "| **logical_not(X)**     | 真值邏輯 NOT  |\n",
    "\n",
    "Note: 要比較兩個陣列(array-wise)是否形狀大小及元素全部相同,可以使用 `array_equal(X, Y)` 函式。\n",
    "\n",
    "+ **算數運算子** - 運算結果返回數值陣列。\n",
    "\n",
    "| 算數運算操作          | 說明               | in-place 操作   |\n",
    "|-----------------------|--------------------|-----------------|\n",
    "| **X + Y, X - Y**      | 加法,減法         | **+=, -=**      |\n",
    "| **X \\* Y, X / Y**     | 乘法,除法         | **\\*=, /=**     |\n",
    "| **X // Y, X % Y**     | 取商,取餘數       | **//=, %=**     |\n",
    "| **X\\*\\*Y**            | 指數次方           | **\\*\\*=**       |\n",
    "| **X &#124; Y, X & Y** | 位元 OR,AND       | **&#124;=, &=** |\n",
    "| **X << Y, X >> Y**    | 位元左位移,右位移 | **<<=, >>=**    |\n",
    "| **X ^ Y**             | 位元 XOR           | **^=**          |\n",
    "\n",
    "+ **一元算數運算子** - 運算結果返回數值陣列。\n",
    "\n",
    "| 算數運算操作  | 說明         |\n",
    "|---------------|--------------|\n",
    "| **-X**        | 取負數       |\n",
    "| **~X**        | 位元反相     |"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a == b => [False  True False  True]\n",
      "a > b => [False False  True False]\n"
     ]
    }
   ],
   "source": [
    "# 元素逐項(element-wise)比較\n",
    "a = np.array([1, 2, 3, 4])\n",
    "b = np.array([4, 2, 2, 4])\n",
    "print('a == b =>', a == b)\n",
    "print('a > b =>', a > b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a, b 陣列是否完全相等: False\n",
      "a, c 陣列是否完全相等: True\n"
     ]
    }
   ],
   "source": [
    "# 陣列整體(array-wise)比較\n",
    "a = np.array([1, 2, 3, 4])\n",
    "b = np.array([4, 2, 2, 4])\n",
    "c = np.array([1, 2, 3, 4])\n",
    "print('a, b 陣列是否完全相等:', np.array_equal(a, b))\n",
    "print('a, c 陣列是否完全相等:', np.array_equal(a, c))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "真值邏輯比較 a OR b: [ True  True  True False]\n",
      "真值邏輯比較 a AND b: [ True False False False]\n"
     ]
    }
   ],
   "source": [
    "# 陣列真值邏輯比較\n",
    "a = np.array([1, 1, 0, 0], dtype=bool)\n",
    "b = np.array([1, 0, 1, 0], dtype=bool)\n",
    "print('真值邏輯比較 a OR b:', np.logical_or(a, b))\n",
    "print('真值邏輯比較 a AND b:', np.logical_and(a, b))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a + b = [5 4 5 8]\n",
      "b * c = [ 4  4  6 16]\n",
      "a + b * c = [ 5  6  9 20]\n",
      "(a + b) / c = [5.         2.         1.66666667 2.        ]\n"
     ]
    }
   ],
   "source": [
    "# 陣列元素逐項(element-wise)運算\n",
    "a = np.array([1, 2, 3, 4])\n",
    "b = np.array([4, 2, 2, 4])\n",
    "c = np.array([1, 2, 3, 4])\n",
    "print('a + b =', a + b)\n",
    "print('b * c =', b * c)\n",
    "print('a + b * c =', a + b * c)\n",
    "print('(a + b) / c =', (a + b) / c)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### § 散播 Broadcasting\n",
    "\n",
    "上述二元運算的一般形式中,除了兩個陣列運算元(**X, Y**)的形狀大小都一致以外,numpy 也容許在符合散播(**broadcasting**)條件下運算元形狀大小不一樣。 基本的散播相容的規則是:\n",
    "1. 兩個陣列維度大小相等,或\n",
    "2. 其中有一個維度大小是 1。\n",
    "\n",
    "以下散播機制的示意圖來自 *scipy-lectures.org*\n",
    "![numpy broadcasting 1](http://scipy-lectures.org/_images/numpy_broadcasting.png)\n",
    "\n",
    "看似複雜的散播機制,其實都是為了簡化計算及程式碼的算式,讓程式碼更直覺、更自然、有更高的可讀性。以下範例及示意圖來自 [numpy 官方手冊](https://docs.scipy.org/doc/numpy/user/theory.broadcasting.html):\n",
    "```\n",
    ">>> a = array([1.0, 2.0, 3.0])\n",
    ">>> b = 2.0\n",
    ">>> a * b\n",
    "array([ 2.,  4.,  6.])\n",
    "```\n",
    "![numpy broadcasting 2](https://numpy.org/doc/stable/_images/theory.broadcast_1.gif)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 0  1  2  3]\n",
      " [ 4  5  6  7]\n",
      " [ 8  9 10 11]]\n",
      "[[0 1 2 3]\n",
      " [4 5 6 7]\n",
      " [0 0 0 0]]\n"
     ]
    }
   ],
   "source": [
    "Amat = np.arange(12).reshape(3, 4)\n",
    "print(Amat)\n",
    "\n",
    "# 之前看過的片段指派新值,其實暗中運用了 broadcasting\n",
    "Amat[2] = 0\n",
    "print(Amat)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0.         1.         2.         3.         4.         5.        ]\n",
      " [1.         1.41421356 2.23606798 3.16227766 4.12310563 5.09901951]\n",
      " [2.         2.23606798 2.82842712 3.60555128 4.47213595 5.38516481]\n",
      " [3.         3.16227766 3.60555128 4.24264069 5.         5.83095189]\n",
      " [4.         4.12310563 4.47213595 5.         5.65685425 6.40312424]\n",
      " [5.         5.09901951 5.38516481 5.83095189 6.40312424 7.07106781]]\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.colorbar.Colorbar at 0x2c408fdce10>"
      ]
     },
     "execution_count": 51,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 計算距離\n",
    "x, y = np.arange(6).reshape((6,1)), np.arange(6).reshape((1,6))\n",
    "distance = np.sqrt(x ** 2 + y ** 2)\n",
    "print(distance)\n",
    "plt.pcolor(distance, cmap='jet')\n",
    "plt.colorbar()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0.         1.         2.         3.         4.         5.        ]\n",
      " [1.         1.41421356 2.23606798 3.16227766 4.12310563 5.09901951]\n",
      " [2.         2.23606798 2.82842712 3.60555128 4.47213595 5.38516481]\n",
      " [3.         3.16227766 3.60555128 4.24264069 5.         5.83095189]\n",
      " [4.         4.12310563 4.47213595 5.         5.65685425 6.40312424]\n",
      " [5.         5.09901951 5.38516481 5.83095189 6.40312424 7.07106781]]\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "(array([[0],\n",
       "        [1],\n",
       "        [2],\n",
       "        [3],\n",
       "        [4],\n",
       "        [5]]), array([[0, 1, 2, 3, 4, 5]]))"
      ]
     },
     "execution_count": 52,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 前一個計算距離的範例,使用 np.ogrid 可達到相同目的\n",
    "x, y = np.ogrid[0:6, 0:6]\n",
    "print(np.sqrt(x ** 2 + y ** 2))\n",
    "x, y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0.         1.         2.         3.         4.         5.        ]\n",
      " [1.         1.41421356 2.23606798 3.16227766 4.12310563 5.09901951]\n",
      " [2.         2.23606798 2.82842712 3.60555128 4.47213595 5.38516481]\n",
      " [3.         3.16227766 3.60555128 4.24264069 5.         5.83095189]\n",
      " [4.         4.12310563 4.47213595 5.         5.65685425 6.40312424]\n",
      " [5.         5.09901951 5.38516481 5.83095189 6.40312424 7.07106781]]\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "(array([[0, 0, 0, 0, 0, 0],\n",
       "        [1, 1, 1, 1, 1, 1],\n",
       "        [2, 2, 2, 2, 2, 2],\n",
       "        [3, 3, 3, 3, 3, 3],\n",
       "        [4, 4, 4, 4, 4, 4],\n",
       "        [5, 5, 5, 5, 5, 5]]), array([[0, 1, 2, 3, 4, 5],\n",
       "        [0, 1, 2, 3, 4, 5],\n",
       "        [0, 1, 2, 3, 4, 5],\n",
       "        [0, 1, 2, 3, 4, 5],\n",
       "        [0, 1, 2, 3, 4, 5],\n",
       "        [0, 1, 2, 3, 4, 5]]))"
      ]
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 不想要 broadcasting 的話,使用 np.mgrid 可達到相同目的\n",
    "x, y = np.mgrid[0:6, 0:6]\n",
    "print(np.sqrt(x ** 2 + y ** 2))\n",
    "x, y"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### § 有無向量運算優化的差異\n",
    "\n",
    "對 `list` 裡的所有數值操作相同運算,免不了要使用迴圈。 使用 `numpy.ndarray` 運算,不僅程式碼的算式精簡、可讀性較高,還可以運用處理器的向量運算引擎,獲得更快的運算能力。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "509 µs ± 5.46 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n"
     ]
    }
   ],
   "source": [
    "# 使用迴圈計算 10000 個整數加法\n",
    "L = list(range(10000))\n",
    "%timeit [x+1 for x in L]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "6.17 µs ± 125 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)\n"
     ]
    }
   ],
   "source": [
    "# 使用 numpy 陣列的向量運算 10000 個整數加法\n",
    "A = np.arange(10000, dtype=int)\n",
    "%timeit A + 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.46 ms ± 15.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n"
     ]
    }
   ],
   "source": [
    "# 使用迴圈計算 10000 個浮點數指數運算\n",
    "import random\n",
    "L = [random.random() for x in range(10000)]\n",
    "%timeit [x**2.0 for x in L]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4.58 µs ± 16.6 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)\n"
     ]
    }
   ],
   "source": [
    "# 使用 numpy 陣列的向量運算 10000 個浮點數指數運算\n",
    "A = np.random.rand(10000)\n",
    "%timeit A ** 2.0"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### § 數學、統計、線性代數\n",
    "\n",
    "Numpy 提供了可利用陣列處理向量運算的 [數學函式](https://docs.scipy.org/doc/numpy/reference/routines.math.html),包含了多種和積及差分、三角函數、雙曲線函數、指數與對數、複數等函數。 也有常用的基本 [統計函式](https://docs.scipy.org/doc/numpy/reference/routines.statistics.html) 如平均、變異、標準差、中位數、相關係數、共變異數等。 [線性代數](https://docs.scipy.org/doc/numpy/reference/routines.linalg.html) 的矩陣運算在 `numpy.linalg` 模組中,提供了包含矩陣及向量乘積、矩陣分解、特徵值與特徵向量、矩陣線性方程式求解等函式。 還有更多進階工程及科學運算的函式另外在 [scipy](https://docs.scipy.org/doc/scipy/reference/) 套件中。\n",
    "\n",
    "這些函式比較適合用完整的應用範例來展示。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "y = [-1.   0.2  0.9  2.1]\n",
      "A =\n",
      " [[0. 1.]\n",
      " [1. 1.]\n",
      " [2. 1.]\n",
      " [3. 1.]]\n",
      "\n",
      "solution: m = 0.9999999999999997, c = -0.949999999999999\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x2c40904fb38>"
      ]
     },
     "execution_count": 58,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# least-squares solution to a linear matrix equation\n",
    "# 已知點座標 (x1,y1), (x2,y2), (x3,y3), (x4,y4), ...\n",
    "x = np.array([0, 1, 2, 3])\n",
    "y = np.array([-1, 0.2, 0.9, 2.1])\n",
    "print('y =', y)\n",
    "\n",
    "# 匹配直線方程式 y = mx + c (線性回歸)\n",
    "# 將方程式重新改寫成陣列形式 y = Ap, where A = [x 1], p = [m c]'\n",
    "A = np.vstack([x, np.ones(len(x))]).T\n",
    "print('A =\\n', A)\n",
    "\n",
    "# 最小平方法解線性方程式最佳解\n",
    "m, c = np.linalg.lstsq(A, y, rcond=None)[0]\n",
    "print('\\nsolution: m = {}, c = {}'.format(m, c))\n",
    "\n",
    "fig, ax = plt.subplots()\n",
    "ax.plot(x, y, 'o', label='Original data', markersize=10)\n",
    "ax.plot(x, m*x + c, 'r', label='Fitted line')\n",
    "ax.legend()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 作業練習\n",
    "\n",
    "改寫上面的最小平方法範例,使用 arange() + random 雜訊產生 x, y 的測試資料,再執行求解方程式看看。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}