{ "cells": [ { "cell_type": "markdown", "metadata": { "id": "WUZm-Jbl3V6n" }, "source": [ "## $\\Large{Numpy\\; Tutorial\\; (part2)}$\n", "\n", "Numpy 是使用Python進行科學運算中最基礎的模組,主要的功能環繞在**ndarray (n-dimensional array,中文為多維陣列)**物件上。\n", "\n", "上一個部份我們已經知道Numpy中多維陣列的一些特性以及常見的用法,在這個部分當中我們將會介紹如何操作一個或多個陣列、以及Numpy所提供的其他模組。" ] }, { "cell_type": "markdown", "metadata": { "id": "Yu2EwrJLEXg7" }, "source": [ "### 本章節內容大綱\n", "* [操作多維陣列(Array Manipulation)](#操作多維陣列)\n", " - [改變陣列維度](#改變陣列維度)\n", " - [取得陣列元素](#取得陣列元素)\n", " - [取得陣列片段](#取得陣列片段)\n", " - [陣列搜尋與判斷](#陣列搜尋與判斷)\n", " - [重複陣列元素](#重複陣列元素)\n", " - [排序陣列內元素](#排序陣列內元素)\n", "* [合併或堆疊多個陣列(Array Concatenation / Stacking)](#合併或堆疊多個陣列)\n", " - [合併陣列](#合併陣列)\n", " - [堆疊陣列](#堆疊陣列)\n", "* [Numpy內的其他模組](#Numpy內的其他模組)\n", " - [線性代數模組](#線性代數模組)\n", " - [隨機模組](#隨機模組)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "KVj80H7XEXhG" }, "outputs": [], "source": [ "import numpy as np" ] }, { "cell_type": "markdown", "metadata": { "id": "3q1YeiIuEXhJ" }, "source": [ "---\n", "\n", "## 操作多維陣列\n", "\n", "Reference: 手把手打開資料分析大門\n", "https://www.slideshare.net/tw_dsconf/python-83977705/47" ] }, { "cell_type": "markdown", "metadata": { "id": "05eDQfOH3V7O" }, "source": [ "\n", "- ### 改變陣列維度\n", "\n", "Numpy所提供的多維陣列除了在計算上很便利之外,也可以彈性地改變陣列的維度。在此我們主要介紹以下三個函數功能\n", " - reshape:改變陣列維度\n", " - expand_dim:增加陣列維度\n", " - squeeze:壓縮陣列維度" ] }, { "cell_type": "markdown", "metadata": { "id": "QiSbKpouEXhV" }, "source": [ "#### reshape 功能\n", "\n", "reshape是在改變陣列維度中最常被使用的函數,它可以彈性地重塑陣列的形狀、增加、或是減少陣列維度。\n", "\n", "\n", "\n", "\n", "如上面這個例子,原先儲存 [0,1,2,3,4,5] 共六個元素的陣列維度可以是(6, )的一維陣列,也可以是(3,2)的二維陣列,甚至是(2,3,1)的三維陣列,唯一的需求就是改變後陣列的元素總數需與改變前相同。另外值得注意的是在改變形狀後陣列元素會依照維度依序排列,不會隨便亂跑!" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "Y15a15b93V7P" }, "outputs": [], "source": [ "# 創建一個一維陣列,裡面共有6個元素\n", "x = np.arange(6)\n", "\n", "print(x)\n", "print(x.shape)\n", "# [0 1 2 3 4 5]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "UKcv2MESEXhZ" }, "outputs": [], "source": [ "# 使用reshape 將原本的陣列改成(3,2)的形狀\n", "new_x = x.reshape(3, 2)\n", "print(new_x)\n", "print(new_x.shape)\n", "# [[0 1]\n", "# [2 3]\n", "# [4 5]]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "n_aDLDnMEXhk" }, "outputs": [], "source": [ "# 使用reshape 將原本的陣列改成(2,3,1)的形狀\n", "new_x2 = np.arange(6).reshape(2, 3, 1)\n", "print(new_x2)\n", "print(new_x2.shape)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "ZcQTzVDLfZlV" }, "outputs": [], "source": [ "x" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "jUkjmyo1EXhm" }, "outputs": [], "source": [ "# extra\n", "\n", "# 如果懶得算要轉換的維度,也可以給予 -1 讓numpy自已計算\n", "new_x4 = x.reshape(2, -1)\n", "print(new_x4, new_x4.shape)" ] }, { "cell_type": "markdown", "metadata": { "id": "cONtt7hWEXhn" }, "source": [ "#### expand_dims 與 squeeze 功能\n", "\n", "相較於reshape強大且彈性的功能,expand_dims與squeeze各自負責的是在不改變陣列形狀的前提下增加或是減少維度。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "2jzW8qiNEXhx" }, "outputs": [], "source": [ "# 創建一個一維陣列\n", "x = np.arange(6)\n", "print(x, x.shape)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "LfvDCa1HEXh2" }, "outputs": [], "source": [ "# 在x這個陣列額外增加一個維度並且命名為x2,在這邊我們加在第一個軸,因此axis = 0\n", "x2 = np.expand_dims(x, axis=0)\n", "print(x2, x2.shape)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "9SQ5WmXhEXh3" }, "outputs": [], "source": [ "# 將x2這個陣列裡面多的維度(長度為一的維度)壓縮\n", "x3 = np.squeeze(x2)\n", "print(x3, x3.shape)" ] }, { "cell_type": "markdown", "metadata": { "id": "_mwttuJm3V7a" }, "source": [ "\n", "- ### 取得陣列元素\n", "\n", "如果我們想要取出一個或多個陣列的元素的話,我們就需要使用陣列內元素的索引去取得元素本身,還記得python原生的列表(list)嗎?陣列元素索引的使用方式與列表其實非常類似,只要在陣列後面以中括號**[ ]**並在裡面填入索引就可以了,差異在於陣列的維度是多維的,因此陣列元素的索引也是多維的。\n", "\n", "" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "_fcHtZer3V7b" }, "outputs": [], "source": [ "# 創建一個一維陣列\n", "x = np.arange(6)\n", "print(x)\n", "# array([0, 1, 2, 3, 4, 5])\n", "\n", "# 取出這個陣列的第三個元素\n", "print(x[2])\n", "# 2\n", "\n", "# 取出這個陣列的倒數第二個元素\n", "print(x[-2])\n", "# 4" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "90MR0Zb1EXiB" }, "outputs": [], "source": [ "# 創建一個二維陣列\n", "x = np.arange(6).reshape(2, 3)\n", "print(x)\n", "# [[0, 1, 2],\n", "# [3, 4, 5]])\n", "\n", "# 取出第一個維度索引為0,第二個維度索引為2的元素\n", "print(x[0, 2])\n", "# 2\n", "\n", "# 取出第一個維度索引為1,第二個維度索引為-1 (倒數第一)的元素\n", "print(x[1, -1])\n", "# 5" ] }, { "cell_type": "markdown", "metadata": { "id": "1Z5PpmM83V7g" }, "source": [ "\n", "- ### 取得陣列片段\n", "\n", "同樣地,在陣列中要取得某一部份的元素我們同樣可以利用和列表(list)相似的辦法。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "3XkOklq73V7h" }, "outputs": [], "source": [ "# 創建一個一維陣列\n", "x = np.arange(6)\n", "# array([0, 1, 2, 3, 4, 5])" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "hJznhi2OfZlZ" }, "outputs": [], "source": [ "x" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "HKNEwbJ6EXiJ" }, "outputs": [], "source": [ "# 取出這個陣列第二到第六個元素的片段(不含第六個元素)\n", "print(x[1:5])\n", "# [1, 2, 3, 4]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "phjTnhZIEXlH" }, "outputs": [], "source": [ "# 取出這個陣列從頭開始到第三個元素的片段(不含第三個元素)\n", "print(x[:2])\n", "# [0, 1]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "aI8nKwTsEXlI" }, "outputs": [], "source": [ "# 取出這個陣列第二個到第六個元素的片段(不含第六個元素),且每隔兩個值取一個元素\n", "print(x[1:5:2])\n", "# [1, 3]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "5llncKKIEXlL" }, "outputs": [], "source": [ "# 創建一個二維陣列\n", "x = np.arange(6).reshape(2, 3)\n", "# [[0, 1, 2],\n", "# [3, 4, 5]])" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "HQ47dYETfZla" }, "outputs": [], "source": [ "x" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "yU1zOBG4EXlS" }, "outputs": [], "source": [ "# 取出這個陣列第一個維度索引為0,第二個維度從第一個到第三個元素的片段(不含第三個元素)\n", "print(x[0, 0:2])\n", "# [0, 1]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "o6vy3XdJEXlT" }, "outputs": [], "source": [ "# 取出這個陣列第一個維度的所有索引,第二個維度從第二個到最後一個元素的片段\n", "print(x[:, 1:])\n", "# [[1, 2],\n", "# [4, 5]]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "NHuPkEsVEXlU" }, "outputs": [], "source": [ "# 取出這個陣列第一個維度從頭到尾且每隔一個值取一個元素,第二個維度從頭到尾且每隔兩個值取一個元素的片段\n", "print(x[::1, ::2])\n", "# [[0, 2],\n", "# [3, 5]]" ] }, { "cell_type": "markdown", "metadata": { "id": "41_qi6yyEXlU" }, "source": [ "\n", "- ### 陣列搜尋與判斷\n", "\n", "在一個陣列中我們也可以做搜尋或是每個元素的判斷,讓我們來看一下要如何操作吧。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "-Rsy8DsHEXlW" }, "outputs": [], "source": [ "# 創建一個一維陣列\n", "x = np.arange(6)\n", "# array([0, 1, 2, 3, 4, 5])\n", "\n", "# 針對每個元素判斷是不是小於3,若小於3則為True、大於等於3則為False\n", "condition = x < 3\n", "\n", "# 這個只有True / Fasle 的陣列也被稱為布林遮罩(boolean mask)\n", "print(condition)\n", "# [ True True True False False False]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "-wYqXmfjEXlb" }, "outputs": [], "source": [ "# 創建一個一維陣列\n", "x = np.array([3, 1, 6, 4, 2])\n", "\n", "# 使用argmax去找陣列中最大的元素索引\n", "idx_ = np.argmax(x)\n", "print('陣列x中最大數值的索引是:', idx_)\n", "print('陣列x中最大數值是 : ', x[idx_])" ] }, { "cell_type": "markdown", "metadata": { "id": "nwLTG7yE3V7m" }, "source": [ "我們也可以使用判斷過後的遮罩幫助我們取出陣列中的元素" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "cI4Eqxbj3V7n" }, "outputs": [], "source": [ "# 創建一個一維陣列\n", "x = np.arange(6)\n", "# array([0, 1, 2, 3, 4, 5])\n", "\n", "# 判斷這個陣列的元素是否小於3\n", "condition = x < 3\n", "\n", "# 可以在索引當中放入剛剛的判斷式,就可以只取出小於3的元素們\n", "print(x[condition])\n", "# [0, 1, 2]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "taXuSVjwEXlh" }, "outputs": [], "source": [ "# 也可以應用這樣個方法直接取代陣列中的元素數值\n", "x[condition] = 0\n", "print(x)\n", "# [0, 0, 0, 3, 4, 5]" ] }, { "cell_type": "markdown", "metadata": { "id": "AC5qdsD1EXlk" }, "source": [ "\n", "- ### 重複陣列元素\n", "\n", "如果需要快速複製陣列中的元素,我們可以使用repeat函數功能,而若需要做的是重複整個陣列內容則可以用tile函數做到這件事情。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "bK5VwyRbEXll" }, "outputs": [], "source": [ "# 創建一個二維陣列\n", "x = np.array([[0, 1], [2, 3]])\n", "print(x)\n", "# [[0, 1]\n", "# [2, 3]]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "pohFXXVkEXll" }, "outputs": [], "source": [ "# 重複陣列中的元素兩次,預設會將陣列攤平成一維陣列\n", "np.repeat(x, repeats=2)\n", "# [0, 0, 1, 1, 2, 2, 3, 3]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "XbhYyBtEEXlu" }, "outputs": [], "source": [ "# 指定每個元素的重複次數\n", "np.repeat(x, repeats=(1, 2, 3, 4))\n", "# [0, 1, 1, 2, 2, 2, 3, 3, 3, 3]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "1UZjDVaeEXly" }, "outputs": [], "source": [ "# 以axis參數指定要重複時所依據的維度\n", "# 指定axis = 0,numpy就會將第一軸index相同的元素(ex.[0, 1])當作同一組做重複。\n", "np.repeat(x, repeats=2, axis=0)\n", "# [[0, 1],\n", "# [0, 1],\n", "# [2, 3],\n", "# [2, 3]]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "QzaWaTu1EXlz" }, "outputs": [], "source": [ "# 以axis參數指定要重複時所依據的維度\n", "# 指定axis = 1,numpy就會將第二軸index相同的元素當作同一組做重複。\n", "# (ex.[0\n", "# 2])\n", "\n", "np.repeat(x, repeats=2, axis=1)\n", "# [[0, 0, 1, 1],\n", "# [2, 2, 3, 3]]" ] }, { "cell_type": "markdown", "metadata": { "id": "OAgW1sYCEXl0" }, "source": [ "#### tile 功能" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "9WRnzx34EXl1" }, "outputs": [], "source": [ "# 創建一個二維陣列\n", "x = np.array([[0, 1], [2, 3]])\n", "print(x)\n", "# [[0, 1]\n", "# [2, 3]]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "RRtBKeLQEXl2" }, "outputs": [], "source": [ "# 預設在重複時會沿著最後一個維度(在這邊是axis=1)增加\n", "np.tile(x, reps=2)\n", "# [[0, 1, 0, 1],\n", "# [2, 3, 2, 3]]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "X9j7loFzEXl2" }, "outputs": [], "source": [ "# 在reps參數中也可以指定每個維度的重複次數\n", "np.tile(x, reps=(1, 2))\n", "# [[0, 1, 0, 1],\n", "# [2, 3, 2, 3]]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "gBeDjZ0JEXl3" }, "outputs": [], "source": [ "# 設定在第一個維度重複兩次,第二個維度不做重複動作\n", "np.tile(x, reps=(2, 1))\n", "# [[0, 1],\n", "# [2, 3],]\n", "# [0, 1],]\n", "# [2, 3],]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "0hZRUldcEXl4" }, "outputs": [], "source": [ "# 若reps參數中填入的維度大於原本陣列的維度,則會自動增加陣列維度\n", "np.tile(x, reps=(2, 2, 2))\n", "# [[[0, 1, 0, 1],\n", "# [2, 3, 2, 3],\n", "# [0, 1, 0, 1],\n", "# [2, 3, 2, 3]],\n", "#\n", "# [[0, 1, 0, 1],\n", "# [2, 3, 2, 3],\n", "# [0, 1, 0, 1],\n", "# [2, 3, 2, 3]]]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "dggPVbGvEXl4" }, "outputs": [], "source": [ "np.tile(x, reps=(2, 2, 2)).shape" ] }, { "cell_type": "markdown", "metadata": { "id": "uSZTvc1rEXl5" }, "source": [ "\n", "- ### 排序陣列內元素\n", "\n", "針對陣列中的元素,我們也可以進行排序讓他們交換位置,另外在這邊我們也可以利用axis參數讓功能更加彈性。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "bZlctJGIEXl6" }, "outputs": [], "source": [ "# 創建一個二維陣列\n", "x = np.array([[6, 5, 4], [1, 2, 3]])\n", "print(x)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "nRpAxi_dEXl7" }, "outputs": [], "source": [ "# 使用np.sort排序陣列內元素,預設會沿著最後一個維度做排序\n", "np.sort(x)\n", "# [[4, 5, 6],\n", "# [1, 2, 3]]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "ZR0DdZN9EXl7" }, "outputs": [], "source": [ "# 也可以直接使用axis參數指定要依照哪個維度做排序\n", "# 在此範例中因為x的維度有(0,1)兩種可能性,指定axis=-1 將等於 axis=1\n", "np.sort(x, axis=-1)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "a-G_tBhLEXmF" }, "outputs": [], "source": [ "# 依據第一個維度做排序\n", "np.sort(x, axis=0)\n", "# [[1, 2, 3],\n", "# [6, 5, 4]]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "I3-KUIFpEXmG" }, "outputs": [], "source": [ "# 若指定axis = None,則會排序陣列中所有元素並且攤平\n", "np.sort(x, axis=None)\n", "# [1, 2, 3, 4, 5, 6]" ] }, { "cell_type": "markdown", "metadata": { "id": "JyTdvATW3V7r" }, "source": [ "\n", "## 合併或堆疊多個陣列\n", "\n", "除了對一個陣列做操作之外,有的時候也會遇到將多個陣列合併在一起的狀況,此時依據需求不同我們可以使用concatenate或是stack幫我們做到這件事情。" ] }, { "cell_type": "markdown", "metadata": { "id": "83eTK_aoEXmI" }, "source": [ "\n", "- ### 合併陣列\n", "\n", "concatenate可以幫助我們把多個陣列沿著某一個維度合併在一起,合併之後的陣列維度會跟原本的維度數量相同,不會額外增加新的維度。\n", "\n", "要注意的是要合併的陣列除了要合併的維度之外,其餘的維度長度都要一樣喔!\n", "\n", "\n", "\n", "---\n", "\n", "" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "t8yIrW_L3V7s" }, "outputs": [], "source": [ "# 創建兩個二維陣列\n", "a = np.array([[1, 2, 3], [4, 5, 6]])\n", "b = np.array([[7, 8, 9]])\n", "\n", "print(a)\n", "print('--------')\n", "print(b)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "mu8FxsqbEXmJ" }, "outputs": [], "source": [ "# 將兩個陣列沿著第一個維度合併起來,我們可以用三個陣列的shape看一下到底發生了甚麼事情\n", "c = np.concatenate((a, b), axis=0)\n", "print(c)\n", "print(a.shape, b.shape, c.shape)\n", "# [[1, 2, 3],\n", "# [4, 5, 6],\n", "# [7, 8, 9]]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "i3BUIdeMEXmL" }, "outputs": [], "source": [ "# 創建另外一個二維陣列\n", "d = np.array([[0], [0]])\n", "\n", "# 將a與d兩個陣列沿著第二個維度合併起來\n", "np.concatenate((a, d), axis=1)\n", "# [[1, 2, 3, 0],\n", "# [4, 5, 6, 0]]" ] }, { "cell_type": "markdown", "metadata": { "id": "cLcs0Nvz3V8A" }, "source": [ "\n", "- ### 堆疊陣列\n", "\n", "stack與concatenate不同的地方在於,需要合併的陣列無論是維度或是各維度的長度都需要相同,另外合併後的陣列會額外新增一個維度。\n", "\n", "而vstack(vertical stacking)與hstack(horizontal stacking)則與concatenate功能類似,只是不需要指定合併的維度。\n", "\n", "" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "VyE0M7WS3V8B" }, "outputs": [], "source": [ "# 創建三個二維陣列\n", "a = np.array([[0, 1], [2, 3]])\n", "\n", "b = np.array([[4, 5], [6, 7]])\n", "\n", "c = np.array([[8, 9], [10, 11]])" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "lnjYObbiEXmR" }, "outputs": [], "source": [ "# 將三個陣列在第一個維度堆疊起來\n", "s = np.stack([a, b, c], axis=0)\n", "print(s)\n", "print(s.shape)\n", "# (3, 2, 2)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "k3eh8WjVEXmS" }, "outputs": [], "source": [ "# 將三個陣列沿著第一個維度合併起來\n", "v = np.vstack([a, b, c])\n", "print(v)\n", "print(v.shape)\n", "# (6, 2)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "NQZ5KArLEXmS" }, "outputs": [], "source": [ "# 將三個陣列沿著第二個維度合併起來\n", "h = np.hstack([a, b, c])\n", "print(h)\n", "print(h.shape)\n", "# (2, 6)" ] }, { "cell_type": "markdown", "metadata": { "id": "6lEVdrjmEXmT" }, "source": [ "---\n", "\n", "## Numpy內的其他模組\n", "\n", "由於numpy提供的是通用性的陣列物件,除了上述的基本功能之外,也有其他模組供使用者進行其他的數學運算,在此我們介紹兩個較常使用的模組,分別為線性代數模組與隨機模組。" ] }, { "cell_type": "markdown", "metadata": { "id": "L-uLxLnm3V77" }, "source": [ "\n", "- ### 線性代數模組\n", "\n", "在numpy中,二維的陣列即可以當作矩陣來使用,因此在numpy.linalg 模組中提供許多針對矩陣進行操作的函數和方法。在此我們簡單介紹如何將一個矩陣作轉置、得到它的反矩陣、以及做內積。\n", "\n", "轉置矩陣:m \\* n 矩陣在向量空間上轉置為 n \\* m 矩陣 \n", "反矩陣:n \\* n 矩陣 A 存在一個 n \\* n 矩陣 B,使得 AB = BA = I" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "ELGfnIl53V78" }, "outputs": [], "source": [ "# 創建一個二維陣列,可視為矩陣\n", "x = np.array([[0, 1], [2, 3]])\n", "\n", "print(x)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "2yqjqeOkEXmV" }, "outputs": [], "source": [ "# 取得x的轉置矩陣\n", "print(x.T)\n", "# [[0, 2],\n", "# [1, 3]]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "IMuHm9LrEXmW" }, "outputs": [], "source": [ "# 取得x的反矩陣\n", "inverse = np.linalg.inv(x)\n", "print(inverse)\n", "# [[-1.5, 0.5],\n", "# [1, 0]]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "rtjVndSGEXmW" }, "outputs": [], "source": [ "# 將x與x的反矩陣進行內積,結果應為單位矩陣\n", "print(np.dot(x, inverse))\n", "# [[ 1. 0.]\n", "# [ 0. 1.]]" ] }, { "cell_type": "markdown", "metadata": { "id": "waNAnYMUEXmX" }, "source": [ "\n", "- ### 隨機模組\n", "\n", "在數學運算或模擬的過程中,我們很常需要隨機地產生數字,此時我們就可以使用numpy的隨機模組。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "mgERenOeEXmY" }, "outputs": [], "source": [ "# 設定隨機種子\n", "np.random.seed(seed=818)\n", "\n", "# 使用np.random模組產生隨機整數\n", "# 設定範圍為1到10,並且產生5個隨機整數 (每個整數出現的機率相同)\n", "print(np.random.randint(low=1, high=10, size=5))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "ZcEI5dlNEXmZ" }, "outputs": [], "source": [ "# 從標準常態分配中取得10個數字\n", "print(np.random.randn(10))" ] }, { "cell_type": "markdown", "metadata": { "id": "IAMRkrUwEXma" }, "source": [ "大家可能會疑惑一開始的隨機種子到底是甚麼意思,事實上在電腦裡面所取的隨機數並非真正的隨機,而是透過演算法所產生出來的隨機數字,這樣的方式又被稱為偽隨機(Pseudo-Randomness)。\n", "\n", "也因為這樣,只要我們給予相同的數字作為輸入給產生隨機數的演算法,就能夠得到一模一樣的同一組隨機數字,這個決定隨機演算法輸出的數字也被稱為隨機種子。在numpy內我們可以使用np.random.seed 設定當使用到隨機模組時要使用的隨機種子數值是多少。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "zMEni-4WEXmb" }, "outputs": [], "source": [ "# 設定隨機種子為10,並且從標準常態分配中抽取一個樣本\n", "np.random.seed(seed=10)\n", "print(np.random.randn(1))\n", "\n", "# 再一次設定這次要用的隨機種子是10,看看我們可不可以得到相同的結果\n", "np.random.seed(seed=10)\n", "print(np.random.randn(1))" ] } ], "metadata": { "colab": { "name": "Numpy_part2.ipynb", "provenance": [] }, "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.7.10" } }, "nbformat": 4, "nbformat_minor": 0 }