├── .ipynb_checkpoints ├── Untitled-checkpoint.ipynb ├── batch_norm-checkpoint.ipynb ├── batch_norm2-checkpoint.ipynb └── conversion-checkpoint.ipynb ├── README.md ├── conversion.ipynb ├── conversion.m └── superstore.xls /.ipynb_checkpoints/Untitled-checkpoint.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [], 3 | "metadata": {}, 4 | "nbformat": 4, 5 | "nbformat_minor": 2 6 | } 7 | -------------------------------------------------------------------------------- /.ipynb_checkpoints/batch_norm2-checkpoint.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "## This code hopefully is to assit demonstrating Batch Normalziation - to be completed\n", 8 | "\n", 9 | "Richard Xu, 徐亦达\n", 10 | "\n", 11 | "Yida.Xu@uts.edu.au\n", 12 | "\n", 13 | "2018-02-16" 14 | ] 15 | }, 16 | { 17 | "cell_type": "markdown", 18 | "metadata": {}, 19 | "source": [ 20 | "### 1. Data whitening" 21 | ] 22 | }, 23 | { 24 | "cell_type": "markdown", 25 | "metadata": {}, 26 | "source": [ 27 | "To understand what is data whitening: let's started by sampling data from multivariate Gaussian distribution:\n", 28 | "$X \\sim \\mathcal{N}\\left(\\mu, \\Sigma \\right)$\n", 29 | "\n", 30 | "首先,想知道啥是数据 whitening,我们看从多元正态分布产生数据 $X \\sim \\mathcal{N}\\left(\\mu, \\Sigma \\right)$\n", 31 | "\n", 32 | "Let $\\mu = \\begin{bmatrix} 1 \\\\ 2 \\end{bmatrix}$ and \n", 33 | "$\\Sigma = \\begin{bmatrix} 2 & 1 \\\\ 1 & 1 \\end{bmatrix} $" 34 | ] 35 | }, 36 | { 37 | "cell_type": "code", 38 | "execution_count": 1, 39 | "metadata": { 40 | "collapsed": false 41 | }, 42 | "outputs": [ 43 | { 44 | "data": { 45 | "text/plain": [ 46 | "" 47 | ] 48 | }, 49 | "execution_count": 1, 50 | "metadata": {}, 51 | "output_type": "execute_result" 52 | }, 53 | { 54 | "data": { 55 | "image/png": "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\nMSYK/T/6KWCPA/c2UwAAAABJRU5ErkJggg==\n", 56 | "text/plain": [ 57 | "" 58 | ] 59 | }, 60 | "metadata": {}, 61 | "output_type": "display_data" 62 | } 63 | ], 64 | "source": [ 65 | "import numpy as np\n", 66 | "from mpl_toolkits.mplot3d import Axes3D\n", 67 | "import matplotlib.pyplot as plt\n", 68 | "%matplotlib inline \n", 69 | "\n", 70 | "mean = [1,2]\n", 71 | "Sigma = np.mat([[2,1],[1,1]])\n", 72 | "N = 500\n", 73 | "data = np.random.multivariate_normal(mean,Sigma,N)\n", 74 | "plt.plot(data[:,0], data[:,1],'.')\n", 75 | "#print data\n", 76 | "\n", 77 | "delta = 0.025\n", 78 | "Xmesh, Ymesh = np.meshgrid(np.arange(-2.0, 4.0, delta), np.arange(-2.0, 4.0, delta) )\n", 79 | "\n", 80 | "pos = np.empty(Xmesh.shape + (2,))\n", 81 | "pos[:, :, 0] = Xmesh\n", 82 | "pos[:, :, 1] = Ymesh\n", 83 | "\n", 84 | "from scipy.stats import multivariate_normal\n", 85 | "\n", 86 | "rv = multivariate_normal(mean, Sigma)\n", 87 | "\n", 88 | "plt.contour(Xmesh, Ymesh, rv.pdf(pos))\n", 89 | "plt.show" 90 | ] 91 | }, 92 | { 93 | "cell_type": "markdown", 94 | "metadata": {}, 95 | "source": [ 96 | "Data whitening means that you need to transform each dimension of data to be distributed as standard Gaussian: $\\mathcal{N}(0,1)$ \n", 97 | "\n", 98 | "1. compute the sample mean $\\mu$ and covariance matrix $\\Sigma$\n", 99 | "2. then transform the data with $x' = \\Sigma^{\\frac{1}{2}} (x - \\mu) $\n", 100 | "Therefore, each dimension: $x' \\sim \\mathcal{N} \\left(\\mu, \\Sigma \\right)$\n", 101 | "\n", 102 | "\n", 103 | "Data Whitening 就是让数据的每一个维度都是服从标准正态分布, 方法是:\n", 104 | "\n", 105 | "1. 计算出样本的均值 $\\mu$ 与协方差矩阵 $\\Sigma$\n", 106 | "2. 然后把数据样本转化成 $x' = \\Sigma^{\\frac{1}{2}} (x - \\mu) $\n", 107 | "\n", 108 | "然后,$x'$ 的每一个维度都是服从标准正态分布" 109 | ] 110 | }, 111 | { 112 | "cell_type": "code", 113 | "execution_count": 2, 114 | "metadata": { 115 | "collapsed": false 116 | }, 117 | "outputs": [ 118 | { 119 | "name": "stdout", 120 | "output_type": "stream", 121 | "text": [ 122 | "\n" 123 | ] 124 | }, 125 | { 126 | "data": { 127 | "text/plain": [ 128 | "[]" 129 | ] 130 | }, 131 | "execution_count": 2, 132 | "metadata": {}, 133 | "output_type": "execute_result" 134 | }, 135 | { 136 | "data": { 137 | "image/png": "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\n", 138 | "text/plain": [ 139 | "" 140 | ] 141 | }, 142 | "metadata": {}, 143 | "output_type": "display_data" 144 | } 145 | ], 146 | "source": [ 147 | "from scipy import linalg\n", 148 | "\n", 149 | "s_mean = np.mean(data,axis=0)\n", 150 | "s_Sigma = np.cov(np.transpose(data))\n", 151 | "\n", 152 | "# mean subtracted array\n", 153 | "mean_array = np.reshape(np.repeat(s_mean,data.shape[0]),[data.shape[0],-1],1)\n", 154 | "\n", 155 | "inv_Sigma = np.mat(linalg.fractional_matrix_power(s_Sigma, -0.5))\n", 156 | "print type(inv_Sigma)\n", 157 | "\n", 158 | "data_prime = inv_Sigma * np.transpose(data - mean_array)\n", 159 | "\n", 160 | "data_prime = np.transpose(data_prime)\n", 161 | "\n", 162 | "# note that plt.plot treats horizontal and vertical data very differently\n", 163 | "plt.plot(data_prime[:,0], data_prime[:,1],'.')\n" 164 | ] 165 | }, 166 | { 167 | "cell_type": "markdown", 168 | "metadata": {}, 169 | "source": [ 170 | "### 2. Batch Normalization" 171 | ] 172 | }, 173 | { 174 | "cell_type": "markdown", 175 | "metadata": {}, 176 | "source": [ 177 | "Imagine we have the following error function: (we demonstrate it using 2-d)\n", 178 | "\n", 179 | "想象一下我们有以下的损失函数:\n", 180 | "\n", 181 | "$\\begin{equation} \n", 182 | "\\mathcal{L}_{\\bf w}(X,Y) = \\mathbb{E}_{{\\bf x} \\sim } \\left[ \\sum_{i=1}^N \\left( y_i - {\\bf w}^\\top {\\bf x}_i \\right)^2 \\right] \\\\\n", 183 | "%---------------------\n", 184 | "= \\mathbb{E}_{{\\bf x} \\sim } \\left[ \\sum_{i=1}^N y_i^2 - 2 y_i {\\bf w}^\\top {\\bf x}_i + ( {\\bf w}^\\top {\\bf x}_i )^2 \\right] \\\\\n", 185 | "= \\mathbb{E}_{{\\bf x} \\sim } \\left[ \\sum_{i=1}^N y_i^2 - 2 y_i (w_1 x_1 + w_2 x_2 ) + ( w_1 x_1 + w_2 x_2 )^2 \\right] \\\\\n", 186 | "= \\sum_{i=1}^N y_i^2 - 2 y_i w_1 \\mathbb{E}_{x_1 \\sim } \\big[x_1 \\big] - 2 y_i w_2 \\mathbb{E}_{x_2 \\sim } \\big[ x_2 \\big] + w_1^2 \\mathbb{E}_{x_1 \\sim } \\big[ x_1^2 \\big] + w_2^2 \\mathbb{E}_{x_2 \\sim } \\big[ x_2^2 \\big] + 2 w_1 w_2 \\mathbb{E}_{ {\\bf x} \\sim } \\big[ x_1 x_2 \\big] \\\\\n", 187 | "\\end{equation}\n", 188 | "$" 189 | ] 190 | }, 191 | { 192 | "cell_type": "markdown", 193 | "metadata": {}, 194 | "source": [ 195 | "#### \"whitened\" neurons: " 196 | ] 197 | }, 198 | { 199 | "cell_type": "markdown", 200 | "metadata": {}, 201 | "source": [ 202 | "In Batch Normalization, we force neuron at each layer $x_1 \\sim \\mathcal{N}(0,1)$ and $x_2 \\sim \\mathcal{N}(0,1)$\n", 203 | "\n", 204 | "用Batch Normalization, 我们硬是让每层的神经原子$x_1$ and $x_1$从标准正态分布产生的:\n", 205 | "\n", 206 | "$\\mathcal{L}_{\\bf w}(X,Y) = \n", 207 | "\\sum_{i=1}^N y_i^2 + w_1^2 \\mathbb{E}_{x_1 \\sim } \\big[ x_1^2 \\big] + w_2^2 \\mathbb{E}_{x_2 \\sim } \\big[ x_2^2 \\big] \\\\\n", 208 | "$\n", 209 | "\n", 210 | "Then the error surface $\\mathcal{L}_{\\bf w}(X,Y)$ is a symmetric quadratic, i.e., the contour is circular, rather than elliptical:" 211 | ] 212 | }, 213 | { 214 | "cell_type": "code", 215 | "execution_count": 11, 216 | "metadata": { 217 | "collapsed": false 218 | }, 219 | "outputs": [ 220 | { 221 | "name": "stdout", 222 | "output_type": "stream", 223 | "text": [ 224 | "(500, 2)\n" 225 | ] 226 | }, 227 | { 228 | "data": { 229 | "image/png": "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\n", 230 | "text/plain": [ 231 | "" 232 | ] 233 | }, 234 | "metadata": {}, 235 | "output_type": "display_data" 236 | } 237 | ], 238 | "source": [ 239 | "import numpy as np\n", 240 | "import matplotlib.pyplot as plt\n", 241 | "\n", 242 | "print(data.shape)\n", 243 | "data_prime = np.array(data_prime)\n", 244 | "\n", 245 | "@np.vectorize\n", 246 | "\n", 247 | "def objective(w0, w1):\n", 248 | " return sum((data_prime[:,0] * np.repeat(w0,N))**2 + (data_prime[:,1] * np.repeat(w1,N))**2)\n", 249 | "\n", 250 | "delta = 0.025\n", 251 | "W0mesh, W1mesh = np.meshgrid(np.arange(-3.0, 3.0, delta), np.arange(-2.0, 2.0, delta))\n", 252 | "\n", 253 | "Z = objective(W0mesh, W1mesh)\n", 254 | "\n", 255 | "plt.figure()\n", 256 | "plt.contour(W0mesh, W1mesh, Z)\n", 257 | "plt.title('symmetric quadratic error surface')\n", 258 | "plt.axes().set_aspect('equal', 'datalim')" 259 | ] 260 | }, 261 | { 262 | "cell_type": "markdown", 263 | "metadata": { 264 | "collapsed": true 265 | }, 266 | "source": [ 267 | "We know that if we have an error function has square contour, the gradient descent is going to be much faster.\n", 268 | "\n", 269 | "我们都知道如果损失函数有圆形的contour, 梯度下降会快很多" 270 | ] 271 | } 272 | ], 273 | "metadata": { 274 | "kernelspec": { 275 | "display_name": "Python 2", 276 | "language": "python", 277 | "name": "python2" 278 | }, 279 | "language_info": { 280 | "codemirror_mode": { 281 | "name": "ipython", 282 | "version": 2 283 | }, 284 | "file_extension": ".py", 285 | "mimetype": "text/x-python", 286 | "name": "python", 287 | "nbconvert_exporter": "python", 288 | "pygments_lexer": "ipython2", 289 | "version": "2.7.11" 290 | } 291 | }, 292 | "nbformat": 4, 293 | "nbformat_minor": 2 294 | } 295 | -------------------------------------------------------------------------------- /.ipynb_checkpoints/conversion-checkpoint.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "#### This is a growing tutorial demonstrates some MATLAB examples and their equivalent code in Python\n", 8 | "##### Each Matlab block function corresponds a block in conversion.ipynb, i.e., the block heading start with \"block_\"\n", 9 | "##### written by Richard Xu (yida.xu@uts.edu.au)\n", 10 | "##### Feb 2018" 11 | ] 12 | }, 13 | { 14 | "cell_type": "markdown", 15 | "metadata": {}, 16 | "source": [ 17 | "# block_read_csv" 18 | ] 19 | }, 20 | { 21 | "cell_type": "code", 22 | "execution_count": 1, 23 | "metadata": {}, 24 | "outputs": [ 25 | { 26 | "name": "stdout", 27 | "output_type": "stream", 28 | "text": [ 29 | " Row ID Order ID Order Date Ship Date Ship Mode Customer ID \\\n", 30 | "0 1 CA-2016-152156 2016-11-08 2016-11-11 Second Class CG-12520 \n", 31 | "\n", 32 | " Customer Name Segment Country City ... Postal Code \\\n", 33 | "0 Claire Gute Consumer United States Henderson ... 42420 \n", 34 | "\n", 35 | " Region Product ID Category Sub-Category \\\n", 36 | "0 South FUR-BO-10001798 Furniture Bookcases \n", 37 | "\n", 38 | " Product Name Sales Quantity Discount Profit \n", 39 | "0 Bush Somerset Collection Bookcase 261.96 2 0.0 41.9136 \n", 40 | "\n", 41 | "[1 rows x 21 columns]\n", 42 | " Customer ID Profit\n", 43 | "0 AA-10315 103.5146\n", 44 | "1 AA-10375 69.6989\n", 45 | "2 AA-10480 15.3288\n", 46 | "3 AB-10060 1461.5343\n", 47 | "4 AB-10105 -204.4458\n", 48 | "time times = 1.243\n", 49 | " \n", 50 | "\n", 51 | "\n", 52 | " customer ID Profit\n", 53 | "0 CG-12520 261.4956\n", 54 | "1 DV-13045 6.8714\n", 55 | "2 SO-20335 -380.5146\n", 56 | "3 BH-11710 300.7687\n", 57 | "4 AA-10480 15.3288\n", 58 | "time times = 0.396\n", 59 | "\n", 60 | "\n", 61 | "Customer ID\n", 62 | "AA-10315 103.5146\n", 63 | "AA-10375 69.6989\n", 64 | "AA-10480 15.3288\n", 65 | "AB-10060 1461.5343\n", 66 | "AB-10105 -204.4458\n", 67 | "Name: Profit, dtype: float64\n", 68 | "time times = 0.008\n" 69 | ] 70 | } 71 | ], 72 | "source": [ 73 | "import pandas as pd\n", 74 | "import numpy as np\n", 75 | "import time\n", 76 | "\n", 77 | "store = pd.read_excel('superstore.xls');\n", 78 | "\n", 79 | "# print the first row\n", 80 | "print store[:1]\n", 81 | "\n", 82 | "# ---------------------------------------------------------------\n", 83 | "# The task is to compute the total profits that a customer made\n", 84 | "# ---------------------------------------------------------------\n", 85 | "\n", 86 | "\n", 87 | "# --------------------------------------------------------------\n", 88 | "# METHOD 1: insert element by element into DataFrame\n", 89 | "# --------------------------------------------------------------\n", 90 | "\n", 91 | "t1 = time.time()\n", 92 | "\n", 93 | "val = pd.unique(store['Customer ID'])\n", 94 | "\n", 95 | "# in-place function, i.e., the val changes its values internally\n", 96 | "val.sort()\n", 97 | "\n", 98 | "profit_1 = pd.DataFrame(columns = ['Customer ID', 'Profit' ] )\n", 99 | "\n", 100 | "i = 0\n", 101 | "\n", 102 | "for v in val:\n", 103 | " #cus_list = store[store['Customer ID'].str.contains(v,na=False)]\n", 104 | " index = store['Customer ID']==v\n", 105 | " \n", 106 | " p_series = store[index].Profit\n", 107 | " \n", 108 | " #print type(profit_series), type(profit_series.values) \n", 109 | " \n", 110 | " profit_1.loc[i] = [v, p_series.values.sum()]\n", 111 | " \n", 112 | " i = i + 1\n", 113 | "\n", 114 | "print profit_1[:5]\n", 115 | "print \"time times = %0.3f\" % (time.time() - t1)\n", 116 | "\n", 117 | "\n", 118 | "# get that Series into array\n", 119 | "print type(store['Profit']), type(store['Profit'].values)\n", 120 | "\n", 121 | "print '\\n'\n", 122 | "\n", 123 | "\n", 124 | "# --------------------------------------------------------------\n", 125 | "# METHOD 2: construct array first, then put into DataFrame\n", 126 | "# --------------------------------------------------------------\n", 127 | "\n", 128 | "t1 = time.time()\n", 129 | "\n", 130 | "val = pd.unique(store['Customer ID'])\n", 131 | "val.sort()\n", 132 | "\n", 133 | "profit = np.zeros(len(val))\n", 134 | "customer_ID = []\n", 135 | "\n", 136 | "i = 0\n", 137 | "\n", 138 | "for v in val:\n", 139 | " index = store['Customer ID']==v\n", 140 | " p_series = store[index].Profit\n", 141 | " customer_ID.append(v)\n", 142 | " profit[i] = sum(p_series)\n", 143 | " i = i + 1\n", 144 | "\n", 145 | " \n", 146 | "profit_2 = pd.DataFrame(columns = ['customer ID', 'Profit' ] )\n", 147 | "profit_2['customer ID'] = customer_ID\n", 148 | "profit_2['Profit'] = profit\n", 149 | "\n", 150 | " \n", 151 | "print profit_2[:5]\n", 152 | "\n", 153 | "print \"time times = %0.3f\" % (time.time() - t1)\n", 154 | "\n", 155 | "\n", 156 | "print '\\n'\n", 157 | "\n", 158 | "\n", 159 | "# --------------------------------------------------------------\n", 160 | "# METHOD 3: use groupby => get Series \n", 161 | "# instead of DataFrame, Series has a (key, value) pair like Dictionary\n", 162 | "# --------------------------------------------------------------\n", 163 | "\n", 164 | "t1 = time.time()\n", 165 | "\n", 166 | "profit_3 = store.groupby('Customer ID', sort=True).Profit.sum()\n", 167 | " \n", 168 | "print profit_3[:5]\n", 169 | "print \"time times = %0.3f\" % (time.time() - t1)\n", 170 | "\n", 171 | "\n" 172 | ] 173 | }, 174 | { 175 | "cell_type": "markdown", 176 | "metadata": {}, 177 | "source": [ 178 | "# block_numpy_multiply" 179 | ] 180 | }, 181 | { 182 | "cell_type": "code", 183 | "execution_count": 2, 184 | "metadata": { 185 | "scrolled": true 186 | }, 187 | "outputs": [ 188 | { 189 | "name": "stdout", 190 | "output_type": "stream", 191 | "text": [ 192 | "type (A) = \n", 193 | "np.dot(A,B) = \n", 194 | "[[27 26]\n", 195 | " [25 22]]\n", 196 | "np.matmul(A,B) = \n", 197 | "[[27 26]\n", 198 | " [25 22]]\n", 199 | "reduce(np.dot, [A, B, C]) = \n", 200 | "[[215 184]\n", 201 | " [197 160]]\n", 202 | "type (A) = \n", 203 | "np.multiply(A,B) = \n", 204 | "[[15 24]\n", 205 | " [ 6 10]]\n", 206 | " A * B * C = \n", 207 | "[[105 48]\n", 208 | " [ 6 50]]\n", 209 | "type (A) = \n", 210 | " A * B * C = \n", 211 | "[[215 184]\n", 212 | " [197 160]]\n" 213 | ] 214 | } 215 | ], 216 | "source": [ 217 | "import numpy as np\n", 218 | "\n", 219 | "A = [[3, 4],[2, 5]]\n", 220 | "B = [[5, 6],[3, 2]]\n", 221 | "C = [[7, 2],[1, 5]]\n", 222 | "\n", 223 | "\n", 224 | "# before cast them to numpy types, they are type \"list\" \n", 225 | "print \"type (A) = \", type (A)\n", 226 | "\n", 227 | "\n", 228 | "# these are matrix multipications\n", 229 | "\n", 230 | "print \"np.dot(A,B) = \\n\", np.dot(A,B)\n", 231 | "print \"np.matmul(A,B) = \\n\", np.matmul(A,B)\n", 232 | "\n", 233 | "# to make \"np.dot\" to take more than two inputs:\n", 234 | "print \"reduce(np.dot, [A, B, C]) = \\n\", reduce(np.dot, [A, B, C])\n", 235 | "\n", 236 | "\n", 237 | "# after cast them to numpy types, they are type \"ndarray'\" \n", 238 | "\n", 239 | "A = np.array(A)\n", 240 | "B = np.array(B)\n", 241 | "\n", 242 | "print \"type (A) = \", type (A)\n", 243 | "\n", 244 | "# the following does element-wise \n", 245 | "print \"np.multiply(A,B) = \\n\", np.multiply(A,B)\n", 246 | "\n", 247 | "# then you can perform things such as element-wise multipication:\n", 248 | "print \" A * B * C = \\n\", A * B * C\n", 249 | "\n", 250 | "\n", 251 | "# then we cast them into matrix\n", 252 | "\n", 253 | "A = np.mat(A)\n", 254 | "B = np.mat(B)\n", 255 | "C = np.mat(C)\n", 256 | "\n", 257 | "print \"type (A) = \", type (A)\n", 258 | "\n", 259 | "W2 = A * B * C\n", 260 | "\n", 261 | "print \" A * B * C = \\n\", A * B * C" 262 | ] 263 | }, 264 | { 265 | "cell_type": "markdown", 266 | "metadata": {}, 267 | "source": [ 268 | "# block_matrix_find" 269 | ] 270 | }, 271 | { 272 | "cell_type": "code", 273 | "execution_count": 3, 274 | "metadata": {}, 275 | "outputs": [ 276 | { 277 | "name": "stdout", 278 | "output_type": "stream", 279 | "text": [ 280 | "[[8, 1, 6], [3, 5, 7], [4, 9, 2]] \n", 281 | "\n", 282 | " True \n", 283 | "\n", 284 | "[[8 1 6]\n", 285 | " [3 5 7]\n", 286 | " [4 9 2]] \n", 287 | "\n", 288 | " \n", 289 | "\n", 290 | "[[ True False True]\n", 291 | " [False False True]\n", 292 | " [False True False]] \n", 293 | "\n", 294 | "a_list[2,1] = 9 \n", 295 | "\n", 296 | "a_list[2,:] = [4 9 2] \n", 297 | "\n", 298 | "a_list[:,1] = [1 5 9] \n", 299 | "\n", 300 | "np.where( a_list > 5 ) \n", 301 | "(array([0, 0, 1, 2]), array([0, 2, 2, 1]))\n", 302 | "np.argwhere(a_list > 5) =\n", 303 | "[[0 0]\n", 304 | " [0 2]\n", 305 | " [1 2]\n", 306 | " [2 1]]\n", 307 | "a_list[np.where( a_list > 5 )] = [8 6 7 9]\n", 308 | "a_list[a_list > 5] = [8 6 7 9]\n" 309 | ] 310 | } 311 | ], 312 | "source": [ 313 | "## hello\n", 314 | "\n", 315 | "a_list = [[ 8, 1, 6], [3, 5, 7], [4, 9, 2]]\n", 316 | "print a_list,\"\\n\"\n", 317 | "print type(a_list), a_list > 5, \"\\n\"\n", 318 | "\n", 319 | "a_list = np.array(a_list)\n", 320 | "print a_list,\"\\n\"\n", 321 | "\n", 322 | "print type(a_list), \"\\n\"\n", 323 | "\n", 324 | "# should see a matrix of True and False\n", 325 | "print a_list > 5, \"\\n\"\n", 326 | "\n", 327 | "print \"a_list[2,1] = \", a_list[2,1], \"\\n\"\n", 328 | "print \"a_list[2,:] = \", a_list[2,:], \"\\n\"\n", 329 | "print \"a_list[:,1] = \", a_list[:,1], \"\\n\"\n", 330 | "\n", 331 | "# this will return two arrays indicating the row and column element, equivlent to \"find\" in MATLAB\n", 332 | "print \"np.where( a_list > 5 ) \\n\", np.where( a_list > 5 )\n", 333 | "\n", 334 | "print \"np.argwhere(a_list > 5) =\\n\", np.argwhere(a_list > 5)\n", 335 | "print \"a_list[np.where( a_list > 5 )] = \", a_list[np.where( a_list > 5 )]\n", 336 | "\n", 337 | "print \"a_list[a_list > 5] = \", a_list[a_list > 5]" 338 | ] 339 | }, 340 | { 341 | "cell_type": "markdown", 342 | "metadata": {}, 343 | "source": [ 344 | "# block_numpy_reshape_repeat" 345 | ] 346 | }, 347 | { 348 | "cell_type": "code", 349 | "execution_count": 4, 350 | "metadata": {}, 351 | "outputs": [ 352 | { 353 | "name": "stdout", 354 | "output_type": "stream", 355 | "text": [ 356 | "[[16, 2, 3, 13], [5, 11, 10, 8], [9, 7, 6, 12], [4, 14, 15, 1]] \n", 357 | "\n", 358 | "[[16 2 3 13 5 11 10 8]\n", 359 | " [ 9 7 6 12 4 14 15 1]] \n", 360 | "\n", 361 | "[[16 2]\n", 362 | " [ 3 13]\n", 363 | " [ 5 11]\n", 364 | " [10 8]\n", 365 | " [ 9 7]\n", 366 | " [ 6 12]\n", 367 | " [ 4 14]\n", 368 | " [15 1]] \n", 369 | "\n", 370 | "[[16 5]\n", 371 | " [ 9 4]\n", 372 | " [ 2 11]\n", 373 | " [ 7 14]\n", 374 | " [ 3 10]\n", 375 | " [ 6 15]\n", 376 | " [13 8]\n", 377 | " [12 1]] \n", 378 | "\n", 379 | "[[16 5 9 4 2 11 7 14 3 10 6 15 13 8 12 1]] \n", 380 | "\n", 381 | "np.repeat(np.mat([1, 2]), 4,0) = \n", 382 | "[[1 2]\n", 383 | " [1 2]\n", 384 | " [1 2]\n", 385 | " [1 2]]\n", 386 | "np.repeat(np.mat([1, 2]), 4,0) = \n", 387 | "[[1 1 1 1 2 2 2 2]]\n" 388 | ] 389 | } 390 | ], 391 | "source": [ 392 | "import numpy as np\n", 393 | "\n", 394 | "a_list = [[16, 2, 3, 13], [5, 11, 10, 8], [9, 7, 6, 12] ,[4, 14, 15, 1]]\n", 395 | "print a_list,\"\\n\"\n", 396 | "\n", 397 | "b_list = np.reshape(a_list,[2,8])\n", 398 | "print b_list, \"\\n\"\n", 399 | "\n", 400 | "b_list = np.reshape(a_list,[8,2])\n", 401 | "print b_list, \"\\n\"\n", 402 | "\n", 403 | "b_list = np.reshape(np.transpose(a_list),[8,2])\n", 404 | "print b_list, \"\\n\"\n", 405 | "\n", 406 | "b_list = np.reshape(np.transpose(a_list),[1,-1])\n", 407 | "print b_list, \"\\n\"\n", 408 | "\n", 409 | "\n", 410 | "''' to get [ 1 2 \n", 411 | " 1 2 \n", 412 | " 1 2 \n", 413 | " 1 2] '''\n", 414 | "\n", 415 | "print \"np.repeat(np.mat([1, 2]), 4,0) = \\n\", np.repeat(np.mat([1, 2]), 4,0)\n", 416 | "\n", 417 | "# to get [1 1 1 1 2 2 2 2]\n", 418 | "print \"np.repeat(np.mat([1, 2]), 4,0) = \\n\", np.repeat(np.mat([1, 2]), 4,1)\n", 419 | "\n", 420 | "\n", 421 | "# --------------------------------------------------------------------------\n", 422 | "# Exercise: how to get [1 2 1 2 1 2 1 2]:\n", 423 | "# --------------------------------------------------------------------------\n", 424 | "answer = np.reshape(np.repeat(np.mat([1, 2]), 4,0),[1,-1])" 425 | ] 426 | }, 427 | { 428 | "cell_type": "markdown", 429 | "metadata": {}, 430 | "source": [ 431 | "# block_numpy_unique" 432 | ] 433 | }, 434 | { 435 | "cell_type": "code", 436 | "execution_count": 5, 437 | "metadata": {}, 438 | "outputs": [ 439 | { 440 | "name": "stdout", 441 | "output_type": "stream", 442 | "text": [ 443 | "[[13. 13. 12. 12. 13.]\n", 444 | " [12. 10. 12. 10. 12.]\n", 445 | " [13. 10. 14. 10. 11.]\n", 446 | " [11. 11. 14. 10. 14.]\n", 447 | " [12. 11. 11. 11. 10.]] \n", 448 | "\n", 449 | "[10. 11. 12. 13. 14.] \n", 450 | "\n", 451 | "[ 6 14 2 0 12] [3 3 2 2 3 2 0 2 0 2 3 0 4 0 1 1 1 4 0 4 2 1 1 1 0] [6 6 6 4 3] \n", 452 | "\n", 453 | "[10. 11. 12. 13. 14.] \n", 454 | "\n", 455 | "[10. 10. 10. 10. 10. 10.]\n", 456 | "[11. 11. 11. 11. 11. 11.]\n", 457 | "[12. 12. 12. 12. 12. 12.]\n", 458 | "[13. 13. 13. 13.]\n", 459 | "[14. 14. 14.]\n" 460 | ] 461 | } 462 | ], 463 | "source": [ 464 | "a_list = np.random.rand(5,5) * 5 + 10\n", 465 | "a_list = np.floor(a_list)\n", 466 | "\n", 467 | "print a_list,\"\\n\"\n", 468 | "\n", 469 | "print np.unique(a_list), \"\\n\"\n", 470 | "\n", 471 | "val, indices, inv_indices, counts = np.unique(a_list, return_index = True, return_inverse = True, return_counts = True)\n", 472 | "\n", 473 | "print indices, inv_indices, counts,\"\\n\"\n", 474 | "one_a_list = a_list.flatten()\n", 475 | "print one_a_list[indices],\"\\n\"\n", 476 | "\n", 477 | "for v in val:\n", 478 | " print one_a_list[np.where( one_a_list == v )]\n" 479 | ] 480 | }, 481 | { 482 | "cell_type": "markdown", 483 | "metadata": {}, 484 | "source": [ 485 | "# block_direction_plot" 486 | ] 487 | }, 488 | { 489 | "cell_type": "code", 490 | "execution_count": 6, 491 | "metadata": { 492 | "scrolled": true 493 | }, 494 | "outputs": [ 495 | { 496 | "name": "stdout", 497 | "output_type": "stream", 498 | "text": [ 499 | "3.11780049709 \n", 500 | "\n", 501 | "[[3.1 7. ]\n", 502 | " [1.2 2.4]\n", 503 | " [1. 1.8]\n", 504 | " [2.5 5.2]] \n", 505 | "\n", 506 | "1.0 \n", 507 | "\n", 508 | "[1. 1.8] \n", 509 | "\n" 510 | ] 511 | }, 512 | { 513 | "data": { 514 | "image/png": "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\n", 515 | "text/plain": [ 516 | "" 517 | ] 518 | }, 519 | "metadata": {}, 520 | "output_type": "display_data" 521 | } 522 | ], 523 | "source": [ 524 | "import matplotlib.pyplot as plt\n", 525 | "import math\n", 526 | "import numpy as np\n", 527 | "%matplotlib inline\n", 528 | "\n", 529 | "#A = np.array([[1.2, 2.4], [3.1, 7.0]]);\n", 530 | "A = np.array([[3.1, 7.0], [1.2, 2.4]]);\n", 531 | "B = np.array([[1.0, 1.8], [2.5, 5.2]]);\n", 532 | "\n", 533 | "\n", 534 | "plt.plot( A[0,0], A[0,1], 'bo', markersize=3, color='y')\n", 535 | "plt.plot( A[1,0], A[1,1], 'bo', markersize=3, color='k')\n", 536 | "plt.plot( A[:,0], A[:,1], color='g')\n", 537 | "\n", 538 | "\n", 539 | "plt.plot( B[0,0], B[0,1], 'bo', markersize=3, color='y')\n", 540 | "plt.plot( B[1,0], B[1,1], 'bo', markersize=3, color='k')\n", 541 | "plt.plot( B[:,0], B[:,1], color='c')\n", 542 | "\n", 543 | "A_dir = A[1,:] - A[0,:];\n", 544 | "A_dir = A_dir / np.linalg.norm(A_dir);\n", 545 | "\n", 546 | "B_dir = B[1,:] - B[0,:];\n", 547 | "B_dir = B_dir / np.linalg.norm(B_dir);\n", 548 | "\n", 549 | "theta = math.acos(np.dot(A_dir,B_dir))\n", 550 | "\n", 551 | "print theta,\"\\n\"\n", 552 | "\n", 553 | "text_m = np.append(A,B,axis=0)\n", 554 | "\n", 555 | "print text_m,\"\\n\"\n", 556 | "\n", 557 | "print np.amin(text_m), \"\\n\"\n", 558 | "\n", 559 | "text_min = np.amin(text_m, axis=0)\n", 560 | "\n", 561 | "print text_min, \"\\n\"\n", 562 | "\n", 563 | "\n", 564 | "# the following are equivalent, except the latter cap only to two decimal points\n", 565 | "# plt.text(text_min[0]+1,text_min[1], \"theta = \" + str(theta) + \": same direction\" ); \n", 566 | "\n", 567 | "if abs(theta)< 0.2:\n", 568 | " plt.text(text_min[0]+1,text_min[1], \"theta = \" + \"%0.2f\" % theta + \": same direction\" )\n", 569 | " \n", 570 | "if abs(theta) > math.pi - 0.2:\n", 571 | " plt.text(text_min[0]+1,text_min[1], \"theta = \" + \"%0.2f\" % theta + \": opposite direction\" ); \n", 572 | "\n", 573 | "plt.show()\n" 574 | ] 575 | }, 576 | { 577 | "cell_type": "markdown", 578 | "metadata": {}, 579 | "source": [ 580 | "# block_inline_function" 581 | ] 582 | }, 583 | { 584 | "cell_type": "code", 585 | "execution_count": 7, 586 | "metadata": { 587 | "scrolled": true 588 | }, 589 | "outputs": [ 590 | { 591 | "name": "stdout", 592 | "output_type": "stream", 593 | "text": [ 594 | "0.880797077978\n", 595 | "0.880797077978\n" 596 | ] 597 | } 598 | ], 599 | "source": [ 600 | "def sigmoid_func(x): \n", 601 | " return 1/(1 + math.exp(-x))\n", 602 | "\n", 603 | "print sigmoid_func(2)\n", 604 | "\n", 605 | "sigmoid2 = lambda x: 1/(1 + math.exp(-x))\n", 606 | "\n", 607 | "print sigmoid2(2)" 608 | ] 609 | }, 610 | { 611 | "cell_type": "markdown", 612 | "metadata": { 613 | "collapsed": true 614 | }, 615 | "source": [ 616 | "# block_map_reduce" 617 | ] 618 | }, 619 | { 620 | "cell_type": "code", 621 | "execution_count": 8, 622 | "metadata": {}, 623 | "outputs": [ 624 | { 625 | "name": "stdout", 626 | "output_type": "stream", 627 | "text": [ 628 | "[-2, -1, 0, 1, 2] [0.11920292202211755, 0.2689414213699951, 0.5, 0.7310585786300049, 0.8807970779778823]\n", 629 | "[0.11920292202211755, 0.2689414213699951, 0.5, 0.7310585786300049, 0.8807970779778823]\n", 630 | "0.0103214959021\n", 631 | "0.0103214959021\n", 632 | "0.0865876081473\n" 633 | ] 634 | } 635 | ], 636 | "source": [ 637 | "items = range(-2,3)\n", 638 | "\n", 639 | "# without using MAP function\n", 640 | "sigmoids = []\n", 641 | "for i in items:\n", 642 | " sigmoids.append(sigmoid2(i))\n", 643 | "\n", 644 | "\n", 645 | "print items, sigmoids\n", 646 | "\n", 647 | "# using MAP function\n", 648 | "\n", 649 | "# both does the same thing of the above\n", 650 | "sigmoids2 = map(lambda x: 1/(1 + math.exp(-x)), items)\n", 651 | "sigmoids2 = map(lambda x: sigmoid_func(x), items)\n", 652 | "\n", 653 | "print sigmoids2\n", 654 | "\n", 655 | "\n", 656 | "# without using REDUCE function \n", 657 | "prod = 1\n", 658 | "for i in sigmoids2:\n", 659 | " prod = prod * i\n", 660 | "\n", 661 | "print prod\n", 662 | "\n", 663 | "# with using REDUCE function\n", 664 | "prod2 = reduce((lambda x, y: x * y), sigmoids2)\n", 665 | "\n", 666 | "print prod2\n", 667 | "\n", 668 | "\n", 669 | "# now apply a filter to input before REDUCE\n", 670 | "prod3 = reduce((lambda x, y: x * y), filter(lambda x: x >= 0.2, sigmoids2))\n", 671 | "\n", 672 | "print prod3\n" 673 | ] 674 | }, 675 | { 676 | "cell_type": "markdown", 677 | "metadata": {}, 678 | "source": [ 679 | "### non-MATLAB tutorial: dictionary example" 680 | ] 681 | }, 682 | { 683 | "cell_type": "code", 684 | "execution_count": 9, 685 | "metadata": { 686 | "scrolled": true 687 | }, 688 | "outputs": [ 689 | { 690 | "name": "stdout", 691 | "output_type": "stream", 692 | "text": [ 693 | "{'deep_learning': True, 'language': 'python', 'experience': 2.5, 'package': 'tensorflow'} \n", 694 | "{'deep_learning': True, 'language': 'python', 'experience': 2.5, 'package': 'keras'}\n", 695 | "keras\n", 696 | "len(skill) = 4\n", 697 | "\"language\" in skill = True\n", 698 | "\"language\" not in skill = True\n", 699 | "{'deep_learning': True, 'programming': 'python', 'experience': 2.5, 'package': 'keras'}\n", 700 | "\n", 701 | "for key in skill:\n", 702 | "\n", 703 | "deep_learning\n", 704 | "programming\n", 705 | "experience\n", 706 | "package\n", 707 | "\n", 708 | "for key in skill.iterkeys():\n", 709 | "\n", 710 | "deep_learning\n", 711 | "programming\n", 712 | "experience\n", 713 | "package\n", 714 | "\n", 715 | "for val in skill.itervalues():\n", 716 | "\n", 717 | "True\n", 718 | "python\n", 719 | "2.5\n", 720 | "keras\n", 721 | "for key in skill:\n", 722 | "\n", 723 | "True\n", 724 | "python\n", 725 | "2.5\n", 726 | "keras\n", 727 | "\n", 728 | "\n", 729 | "deep_learning True\n", 730 | "programming python\n", 731 | "experience 2.5\n", 732 | "package keras\n" 733 | ] 734 | } 735 | ], 736 | "source": [ 737 | "# dictionary isn't used in MATLAB, but a useful tool in Python\n", 738 | "skill = {\"package\" : \"tensorflow\", \"experience\": 2.5, \"language\": \"python\", \"deep_learning\": True}\n", 739 | "print skill, type(skill)\n", 740 | "\n", 741 | "skill[\"package\"] = \"keras\"\n", 742 | "\n", 743 | "# note that dictionary isn't indexed sequentially, so print skill[0] doens't work:\n", 744 | "print skill\n", 745 | "\n", 746 | "# -------- hierarchical access: -------------\n", 747 | "job = {\"required\": \"package\", \"optional\": \"langauge\"}\n", 748 | "\n", 749 | "print skill[job[\"required\"]]\n", 750 | "\n", 751 | "print 'len(skill) = ', len(skill)\n", 752 | "\n", 753 | "print '\"language\" in skill = ', \"language\" in skill\n", 754 | "del skill[\"language\"]\n", 755 | "\n", 756 | "\n", 757 | "print '\"language\" not in skill = ', \"language\" not in skill\n", 758 | "\n", 759 | "\n", 760 | "# -------- use d.pudate() instead of d.add() function -\n", 761 | "\n", 762 | "skill.update({'programming': \"python\"})\n", 763 | "print skill\n", 764 | "\n", 765 | "\n", 766 | "# -------- the followings are the same ---------------\n", 767 | "\n", 768 | "print('\\nfor key in skill:\\n')\n", 769 | "\n", 770 | "for key in skill:\n", 771 | " print key\n", 772 | "\n", 773 | "print('\\nfor key in skill.iterkeys():\\n')\n", 774 | " \n", 775 | "for key in skill.iterkeys():\n", 776 | " print key\n", 777 | " \n", 778 | "# -------- the followings are the same ---------------\n", 779 | " \n", 780 | "print('\\nfor val in skill.itervalues():\\n')\n", 781 | "\n", 782 | "for val in skill.itervalues():\n", 783 | " print val\n", 784 | "\n", 785 | "print('for key in skill:\\n')\n", 786 | " \n", 787 | "for key in skill:\n", 788 | " print skill[key]\n", 789 | "\n", 790 | "# -------- use something like ---------------\n", 791 | "\n", 792 | "print('\\n')\n", 793 | "\n", 794 | "for key in skill:\n", 795 | " print key, \" \", skill[key]\n", 796 | "\n" 797 | ] 798 | }, 799 | { 800 | "cell_type": "markdown", 801 | "metadata": {}, 802 | "source": [ 803 | "### non-MATLAB tutorial: quick pandas" 804 | ] 805 | }, 806 | { 807 | "cell_type": "code", 808 | "execution_count": 10, 809 | "metadata": {}, 810 | "outputs": [ 811 | { 812 | "name": "stdout", 813 | "output_type": "stream", 814 | "text": [ 815 | "0 1\n", 816 | "1 3\n", 817 | "2 5\n", 818 | "3 str\n", 819 | "4 6\n", 820 | "5 8\n", 821 | "dtype: object\n", 822 | "0 1\n", 823 | "1 3\n", 824 | "2 5\n", 825 | "3 67\n", 826 | "4 6\n", 827 | "5 8\n", 828 | "dtype: int64\n", 829 | "0 1\n", 830 | "1 1\n", 831 | "2 1\n", 832 | "3 1\n", 833 | "dtype: int64\n", 834 | "0 0\n", 835 | "1 1\n", 836 | "2 2\n", 837 | "3 3\n", 838 | "dtype: int64\n", 839 | "s.values = [0 1 2 3]\n", 840 | "\n", 841 | "\n", 842 | "DatetimeIndex(['2018-01-01', '2018-01-02', '2018-01-03', '2018-01-04',\n", 843 | " '2018-01-05'],\n", 844 | " dtype='datetime64[ns]', freq='D') \n", 845 | "\n", 846 | " exp_1 exp_2 exp_3\n", 847 | "2018-01-01 1.309386 -1.473402 0.990067\n", 848 | "2018-01-02 0.024094 0.689104 -2.017295\n", 849 | "2018-01-03 -1.050912 -0.765972 1.305284\n", 850 | "2018-01-04 -1.846148 0.917770 -1.869699\n", 851 | "2018-01-05 0.664957 1.200568 -1.259691\n", 852 | "np.array([3] * 4,dtype='int32') = [3 3 3 3]\n", 853 | "\n", 854 | "\n", 855 | " class comment date mark start stop\n", 856 | "0 3 TBA 2018-01-01 pass 1.0 1.0\n", 857 | "1 3 TBA 2018-01-02 fail 1.0 1.0\n", 858 | "2 3 TBA 2018-01-03 fail 1.0 1.0\n", 859 | "3 3 TBA 2018-01-04 pass 1.0 1.0\n" 860 | ] 861 | } 862 | ], 863 | "source": [ 864 | "import pandas as pd\n", 865 | "import numpy as np\n", 866 | "\n", 867 | "# ----------------------------------------------------------------\n", 868 | "# something about series \n", 869 | "# ----------------------------------------------------------------\n", 870 | "\n", 871 | "\n", 872 | "# series can be of different type:\n", 873 | "s = pd.Series([1,3,5,\"str\",6,8.])\n", 874 | "print s\n", 875 | "\n", 876 | "# series can be of same type:\n", 877 | "s = pd.Series([1,3,5,67,6,8])\n", 878 | "print s\n", 879 | "\n", 880 | "# series in value and range:\n", 881 | "s = pd.Series(1,index=list(range(4)))\n", 882 | "print s\n", 883 | "\n", 884 | "s = pd.Series(range(4),index=list(range(4)))\n", 885 | "print s\n", 886 | "\n", 887 | "print \"s.values = \", s.values\n", 888 | "\n", 889 | "print \"\\n\"\n", 890 | "\n", 891 | "\n", 892 | "# ----------------------------------------------------------------\n", 893 | "# create the first DataFrame\n", 894 | "# ----------------------------------------------------------------\n", 895 | "\n", 896 | "\n", 897 | "dates = pd.date_range('20180101', periods=5)\n", 898 | "print dates, \"\\n\"\n", 899 | "\n", 900 | "\n", 901 | "columns = ['exp_1', 'exp_2', 'exp_3']\n", 902 | "\n", 903 | "df = pd.DataFrame(np.random.randn(len(dates),len(columns)), index=dates, columns=columns)\n", 904 | "\n", 905 | "# swap inputs do not matter\n", 906 | "df = pd.DataFrame(np.random.randn(len(dates),len(columns)), columns=columns, index=dates)\n", 907 | "\n", 908 | "print df\n", 909 | "\n", 910 | "# following unlablled version doens't work:\n", 911 | "#df = pd.DataFrame(np.random.randn(6,4), columns, dates)\n", 912 | "\n", 913 | "print \"np.array([3] * 4,dtype='int32') = \", np.array([3] * 4, dtype='int32')\n", 914 | "\n", 915 | "print \"\\n\"\n", 916 | "\n", 917 | "# --------------------------------------------------------------------------------------\n", 918 | "# note that \"df2.start\" are repeating the same element for as many rows as possible:\n", 919 | "# --------------------------------------------------------------------------------------\n", 920 | "\n", 921 | "df2 = pd.DataFrame({'start' : 1.0,\n", 922 | " 'date' : pd.date_range('20180101', periods=4),\n", 923 | " 'stop' : pd.Series(1,index=range(4),dtype='float32'),\n", 924 | " 'class' : np.array([3] * 4,dtype='int32'),\n", 925 | " 'mark' : pd.Categorical([\"pass\",\"fail\",\"fail\",\"pass\"]),\n", 926 | " 'comment' : \"TBA\"})\n", 927 | "\n", 928 | "print df2" 929 | ] 930 | }, 931 | { 932 | "cell_type": "markdown", 933 | "metadata": {}, 934 | "source": [ 935 | "### non-MATLAB tutorial: numpy pass by reference" 936 | ] 937 | }, 938 | { 939 | "cell_type": "code", 940 | "execution_count": 11, 941 | "metadata": {}, 942 | "outputs": [ 943 | { 944 | "name": "stdout", 945 | "output_type": "stream", 946 | "text": [ 947 | "numpy.array(A)[2]=2: A = \n", 948 | "[[1. 1. 1.]\n", 949 | " [1. 1. 1.]\n", 950 | " [1. 1. 1.]]\n", 951 | "numpy.array(A)[2]=2: A = \n", 952 | "[[1. 1. 1.]\n", 953 | " [1. 1. 1.]\n", 954 | " [2. 2. 2.]]\n" 955 | ] 956 | } 957 | ], 958 | "source": [ 959 | "import numpy as np\n", 960 | "\n", 961 | "A = np.mat(np.ones((3,3)))\n", 962 | "\n", 963 | "# ---------------------------------------------------------------------------\n", 964 | "# pass by object\n", 965 | "# ---------------------------------------------------------------------------\n", 966 | "\n", 967 | "np.array(A)[2]=2\n", 968 | "print 'numpy.array(A)[2]=2: A = \\n', A\n", 969 | "\n", 970 | "# ---------------------------------------------------------------------------\n", 971 | "# pass by reference\n", 972 | "# ---------------------------------------------------------------------------\n", 973 | "np.asarray(A)[2]=2\n", 974 | "print 'numpy.array(A)[2]=2: A = \\n', A" 975 | ] 976 | }, 977 | { 978 | "cell_type": "markdown", 979 | "metadata": {}, 980 | "source": [ 981 | "### non-MATLAB tutorial: numpy shape conversion" 982 | ] 983 | }, 984 | { 985 | "cell_type": "code", 986 | "execution_count": 12, 987 | "metadata": {}, 988 | "outputs": [ 989 | { 990 | "name": "stdout", 991 | "output_type": "stream", 992 | "text": [ 993 | "np.array([3] * 4 = \n", 994 | "[3 3 3 3] \n", 995 | "\n", 996 | "np.array([3] * 4 = \n", 997 | "[3 3 3 3] \n", 998 | "\n", 999 | "np.squeeze(A.flatten()) = \n", 1000 | "[[1. 1. 1. 1. 1. 1. 2. 2. 2.]] (1, 9) \n", 1001 | "\n", 1002 | "nd array = \n", 1003 | "[[1. 1. 1.]\n", 1004 | " [1. 1. 1.]\n", 1005 | " [2. 2. 2.]] (3, 3) \n", 1006 | "\n", 1007 | "1d array = \n", 1008 | "[1. 1. 1. 1. 1. 1. 2. 2. 2.] (9,) \n", 1009 | "\n" 1010 | ] 1011 | } 1012 | ], 1013 | "source": [ 1014 | "import numpy as np\n", 1015 | "\n", 1016 | "print \"np.array([3] * 4 = \\n\", np.array([3] * 4), '\\n' \n", 1017 | "print \"np.array([3] * 4 = \\n\", np.array([3] * 4), '\\n' \n", 1018 | "\n", 1019 | "# ---------------------------------------------------------------------------\n", 1020 | "# convert a 3x3 matrix to 1x9 matrix\n", 1021 | "# ---------------------------------------------------------------------------\n", 1022 | "\n", 1023 | "ans = np.squeeze(A.flatten())\n", 1024 | "print \"np.squeeze(A.flatten()) = \\n\", ans, ans.shape, type(ans), '\\n'\n", 1025 | "\n", 1026 | "# ---------------------------------------------------------------------------\n", 1027 | "# convert a nd matrix to nd numpy array\n", 1028 | "# ---------------------------------------------------------------------------\n", 1029 | "\n", 1030 | "arr = np.array(A)\n", 1031 | "print \"nd array = \\n\", arr, arr.shape, type(arr), '\\n'\n", 1032 | "\n", 1033 | "# ---------------------------------------------------------------------------\n", 1034 | "# then, convert from nd numpy array to 1-d array,\n", 1035 | "# ---------------------------------------------------------------------------\n", 1036 | "ans = arr.ravel()\n", 1037 | "\n", 1038 | "print \"1d array = \\n\", ans, ans.shape, type(ans), '\\n'\n", 1039 | "\n" 1040 | ] 1041 | }, 1042 | { 1043 | "cell_type": "code", 1044 | "execution_count": null, 1045 | "metadata": {}, 1046 | "outputs": [], 1047 | "source": [] 1048 | } 1049 | ], 1050 | "metadata": { 1051 | "kernelspec": { 1052 | "display_name": "Python 2", 1053 | "language": "python", 1054 | "name": "python2" 1055 | }, 1056 | "language_info": { 1057 | "codemirror_mode": { 1058 | "name": "ipython", 1059 | "version": 2 1060 | }, 1061 | "file_extension": ".py", 1062 | "mimetype": "text/x-python", 1063 | "name": "python", 1064 | "nbconvert_exporter": "python", 1065 | "pygments_lexer": "ipython2", 1066 | "version": "2.7.14" 1067 | } 1068 | }, 1069 | "nbformat": 4, 1070 | "nbformat_minor": 2 1071 | } 1072 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # matlab2python 2 | This is a new set of machine learning tutorial Python code and demo by Prof Richard Xu 徐亦达 (Yida.Xu@uts.edu.au) 3 | 4 | ### conversion.ipynb 5 | 6 | contains some basic python code; The equivalence between Python and MATLAB are demonstrated blocks of the same name in both “conversion.ipynb” and “conversion.m” 7 | 8 | ### batch_norm.ipynb 9 | 10 | contains some explanation and demonstration on why batch normalisation makes gradient descent faster 11 | -------------------------------------------------------------------------------- /conversion.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "#### This is a growing tutorial demonstrates some MATLAB examples and their equivalent code in Python\n", 8 | "##### Each Matlab block function corresponds a block in conversion.ipynb, i.e., the block heading start with \"block_\"\n", 9 | "##### written by Richard Xu (yida.xu@uts.edu.au)\n", 10 | "##### Feb 2018" 11 | ] 12 | }, 13 | { 14 | "cell_type": "markdown", 15 | "metadata": {}, 16 | "source": [ 17 | "# block_read_csv" 18 | ] 19 | }, 20 | { 21 | "cell_type": "code", 22 | "execution_count": 13, 23 | "metadata": {}, 24 | "outputs": [ 25 | { 26 | "name": "stdout", 27 | "output_type": "stream", 28 | "text": [ 29 | " Row ID Order ID Order Date Ship Date Ship Mode Customer ID \\\n", 30 | "0 1 CA-2016-152156 2016-11-08 2016-11-11 Second Class CG-12520 \n", 31 | "\n", 32 | " Customer Name Segment Country City ... Postal Code \\\n", 33 | "0 Claire Gute Consumer United States Henderson ... 42420 \n", 34 | "\n", 35 | " Region Product ID Category Sub-Category \\\n", 36 | "0 South FUR-BO-10001798 Furniture Bookcases \n", 37 | "\n", 38 | " Product Name Sales Quantity Discount Profit \n", 39 | "0 Bush Somerset Collection Bookcase 261.96 2 0.0 41.9136 \n", 40 | "\n", 41 | "[1 rows x 21 columns]\n", 42 | " Customer ID Profit\n", 43 | "0 AA-10315 103.5146\n", 44 | "1 AA-10375 69.6989\n", 45 | "2 AA-10480 15.3288\n", 46 | "3 AB-10060 1461.5343\n", 47 | "4 AB-10105 -204.4458\n", 48 | "time times = 1.347\n", 49 | " \n", 50 | "\n", 51 | "\n", 52 | " customer ID Profit\n", 53 | "0 AA-10315 103.5146\n", 54 | "1 AA-10375 69.6989\n", 55 | "2 AA-10480 15.3288\n", 56 | "3 AB-10060 1461.5343\n", 57 | "4 AB-10105 -204.4458\n", 58 | "time times = 0.422\n", 59 | "\n", 60 | "\n", 61 | "Customer ID\n", 62 | "AA-10315 103.5146\n", 63 | "AA-10375 69.6989\n", 64 | "AA-10480 15.3288\n", 65 | "AB-10060 1461.5343\n", 66 | "AB-10105 -204.4458\n", 67 | "Name: Profit, dtype: float64\n", 68 | "time times = 0.005\n" 69 | ] 70 | } 71 | ], 72 | "source": [ 73 | "import pandas as pd\n", 74 | "import numpy as np\n", 75 | "import time\n", 76 | "\n", 77 | "store = pd.read_excel('superstore.xls');\n", 78 | "\n", 79 | "# print the first row\n", 80 | "print store[:1]\n", 81 | "\n", 82 | "# ---------------------------------------------------------------\n", 83 | "# The task is to compute the total profits that a customer made\n", 84 | "# ---------------------------------------------------------------\n", 85 | "\n", 86 | "\n", 87 | "# --------------------------------------------------------------\n", 88 | "# METHOD 1: insert element by element into DataFrame\n", 89 | "# --------------------------------------------------------------\n", 90 | "\n", 91 | "t1 = time.time()\n", 92 | "\n", 93 | "val = pd.unique(store['Customer ID'])\n", 94 | "\n", 95 | "# in-place function, i.e., the val changes its values internally\n", 96 | "val.sort()\n", 97 | "\n", 98 | "profit_1 = pd.DataFrame(columns = ['Customer ID', 'Profit' ] )\n", 99 | "\n", 100 | "i = 0\n", 101 | "\n", 102 | "for v in val:\n", 103 | " #cus_list = store[store['Customer ID'].str.contains(v,na=False)]\n", 104 | " index = store['Customer ID']==v\n", 105 | " \n", 106 | " p_series = store[index].Profit\n", 107 | " \n", 108 | " #print type(profit_series), type(profit_series.values) \n", 109 | " \n", 110 | " profit_1.loc[i] = [v, p_series.values.sum()]\n", 111 | " \n", 112 | " i = i + 1\n", 113 | "\n", 114 | "print profit_1[:5]\n", 115 | "print \"time times = %0.3f\" % (time.time() - t1)\n", 116 | "\n", 117 | "\n", 118 | "# get that Series into array\n", 119 | "print type(store['Profit']), type(store['Profit'].values)\n", 120 | "\n", 121 | "print '\\n'\n", 122 | "\n", 123 | "\n", 124 | "# --------------------------------------------------------------\n", 125 | "# METHOD 2: construct array first, then put into DataFrame\n", 126 | "# --------------------------------------------------------------\n", 127 | "\n", 128 | "t1 = time.time()\n", 129 | "\n", 130 | "val = pd.unique(store['Customer ID'])\n", 131 | "val.sort()\n", 132 | "\n", 133 | "profit = np.zeros(len(val))\n", 134 | "customer_ID = []\n", 135 | "\n", 136 | "i = 0\n", 137 | "\n", 138 | "for v in val:\n", 139 | " index = store['Customer ID']==v\n", 140 | " p_series = store[index].Profit\n", 141 | " customer_ID.append(v)\n", 142 | " profit[i] = sum(p_series)\n", 143 | " i = i + 1\n", 144 | "\n", 145 | " \n", 146 | "profit_2 = pd.DataFrame(columns = ['customer ID', 'Profit' ] )\n", 147 | "profit_2['customer ID'] = customer_ID\n", 148 | "profit_2['Profit'] = profit\n", 149 | "\n", 150 | " \n", 151 | "print profit_2[:5]\n", 152 | "\n", 153 | "print \"time times = %0.3f\" % (time.time() - t1)\n", 154 | "\n", 155 | "\n", 156 | "print '\\n'\n", 157 | "\n", 158 | "\n", 159 | "# --------------------------------------------------------------\n", 160 | "# METHOD 3: use groupby => get Series \n", 161 | "# instead of DataFrame, Series has a (key, value) pair like Dictionary\n", 162 | "# --------------------------------------------------------------\n", 163 | "\n", 164 | "t1 = time.time()\n", 165 | "\n", 166 | "profit_3 = store.groupby('Customer ID', sort=True).Profit.sum()\n", 167 | " \n", 168 | "print profit_3[:5]\n", 169 | "print \"time times = %0.3f\" % (time.time() - t1)\n", 170 | "\n", 171 | "\n" 172 | ] 173 | }, 174 | { 175 | "cell_type": "markdown", 176 | "metadata": {}, 177 | "source": [ 178 | "# block_numpy_multiply" 179 | ] 180 | }, 181 | { 182 | "cell_type": "code", 183 | "execution_count": 2, 184 | "metadata": { 185 | "scrolled": true 186 | }, 187 | "outputs": [ 188 | { 189 | "name": "stdout", 190 | "output_type": "stream", 191 | "text": [ 192 | "type (A) = \n", 193 | "np.dot(A,B) = \n", 194 | "[[27 26]\n", 195 | " [25 22]]\n", 196 | "np.matmul(A,B) = \n", 197 | "[[27 26]\n", 198 | " [25 22]]\n", 199 | "reduce(np.dot, [A, B, C]) = \n", 200 | "[[215 184]\n", 201 | " [197 160]]\n", 202 | "type (A) = \n", 203 | "np.multiply(A,B) = \n", 204 | "[[15 24]\n", 205 | " [ 6 10]]\n", 206 | " A * B * C = \n", 207 | "[[105 48]\n", 208 | " [ 6 50]]\n", 209 | "type (A) = \n", 210 | " A * B * C = \n", 211 | "[[215 184]\n", 212 | " [197 160]]\n" 213 | ] 214 | } 215 | ], 216 | "source": [ 217 | "import numpy as np\n", 218 | "\n", 219 | "A = [[3, 4],[2, 5]]\n", 220 | "B = [[5, 6],[3, 2]]\n", 221 | "C = [[7, 2],[1, 5]]\n", 222 | "\n", 223 | "\n", 224 | "# before cast them to numpy types, they are type \"list\" \n", 225 | "print \"type (A) = \", type (A)\n", 226 | "\n", 227 | "\n", 228 | "# these are matrix multipications\n", 229 | "\n", 230 | "print \"np.dot(A,B) = \\n\", np.dot(A,B)\n", 231 | "print \"np.matmul(A,B) = \\n\", np.matmul(A,B)\n", 232 | "\n", 233 | "# to make \"np.dot\" to take more than two inputs:\n", 234 | "print \"reduce(np.dot, [A, B, C]) = \\n\", reduce(np.dot, [A, B, C])\n", 235 | "\n", 236 | "\n", 237 | "# after cast them to numpy types, they are type \"ndarray'\" \n", 238 | "\n", 239 | "A = np.array(A)\n", 240 | "B = np.array(B)\n", 241 | "\n", 242 | "print \"type (A) = \", type (A)\n", 243 | "\n", 244 | "# the following does element-wise \n", 245 | "print \"np.multiply(A,B) = \\n\", np.multiply(A,B)\n", 246 | "\n", 247 | "# then you can perform things such as element-wise multipication:\n", 248 | "print \" A * B * C = \\n\", A * B * C\n", 249 | "\n", 250 | "\n", 251 | "# then we cast them into matrix\n", 252 | "\n", 253 | "A = np.mat(A)\n", 254 | "B = np.mat(B)\n", 255 | "C = np.mat(C)\n", 256 | "\n", 257 | "print \"type (A) = \", type (A)\n", 258 | "\n", 259 | "W2 = A * B * C\n", 260 | "\n", 261 | "print \" A * B * C = \\n\", A * B * C" 262 | ] 263 | }, 264 | { 265 | "cell_type": "markdown", 266 | "metadata": {}, 267 | "source": [ 268 | "# block_matrix_find" 269 | ] 270 | }, 271 | { 272 | "cell_type": "code", 273 | "execution_count": 3, 274 | "metadata": {}, 275 | "outputs": [ 276 | { 277 | "name": "stdout", 278 | "output_type": "stream", 279 | "text": [ 280 | "[[8, 1, 6], [3, 5, 7], [4, 9, 2]] \n", 281 | "\n", 282 | " True \n", 283 | "\n", 284 | "[[8 1 6]\n", 285 | " [3 5 7]\n", 286 | " [4 9 2]] \n", 287 | "\n", 288 | " \n", 289 | "\n", 290 | "[[ True False True]\n", 291 | " [False False True]\n", 292 | " [False True False]] \n", 293 | "\n", 294 | "a_list[2,1] = 9 \n", 295 | "\n", 296 | "a_list[2,:] = [4 9 2] \n", 297 | "\n", 298 | "a_list[:,1] = [1 5 9] \n", 299 | "\n", 300 | "np.where( a_list > 5 ) \n", 301 | "(array([0, 0, 1, 2]), array([0, 2, 2, 1]))\n", 302 | "np.argwhere(a_list > 5) =\n", 303 | "[[0 0]\n", 304 | " [0 2]\n", 305 | " [1 2]\n", 306 | " [2 1]]\n", 307 | "a_list[np.where( a_list > 5 )] = [8 6 7 9]\n", 308 | "a_list[a_list > 5] = [8 6 7 9]\n" 309 | ] 310 | } 311 | ], 312 | "source": [ 313 | "## hello\n", 314 | "\n", 315 | "a_list = [[ 8, 1, 6], [3, 5, 7], [4, 9, 2]]\n", 316 | "print a_list,\"\\n\"\n", 317 | "print type(a_list), a_list > 5, \"\\n\"\n", 318 | "\n", 319 | "a_list = np.array(a_list)\n", 320 | "print a_list,\"\\n\"\n", 321 | "\n", 322 | "print type(a_list), \"\\n\"\n", 323 | "\n", 324 | "# should see a matrix of True and False\n", 325 | "print a_list > 5, \"\\n\"\n", 326 | "\n", 327 | "print \"a_list[2,1] = \", a_list[2,1], \"\\n\"\n", 328 | "print \"a_list[2,:] = \", a_list[2,:], \"\\n\"\n", 329 | "print \"a_list[:,1] = \", a_list[:,1], \"\\n\"\n", 330 | "\n", 331 | "# this will return two arrays indicating the row and column element, equivlent to \"find\" in MATLAB\n", 332 | "print \"np.where( a_list > 5 ) \\n\", np.where( a_list > 5 )\n", 333 | "\n", 334 | "print \"np.argwhere(a_list > 5) =\\n\", np.argwhere(a_list > 5)\n", 335 | "print \"a_list[np.where( a_list > 5 )] = \", a_list[np.where( a_list > 5 )]\n", 336 | "\n", 337 | "print \"a_list[a_list > 5] = \", a_list[a_list > 5]" 338 | ] 339 | }, 340 | { 341 | "cell_type": "markdown", 342 | "metadata": {}, 343 | "source": [ 344 | "# block_numpy_reshape_repeat" 345 | ] 346 | }, 347 | { 348 | "cell_type": "code", 349 | "execution_count": 4, 350 | "metadata": {}, 351 | "outputs": [ 352 | { 353 | "name": "stdout", 354 | "output_type": "stream", 355 | "text": [ 356 | "[[16, 2, 3, 13], [5, 11, 10, 8], [9, 7, 6, 12], [4, 14, 15, 1]] \n", 357 | "\n", 358 | "[[16 2 3 13 5 11 10 8]\n", 359 | " [ 9 7 6 12 4 14 15 1]] \n", 360 | "\n", 361 | "[[16 2]\n", 362 | " [ 3 13]\n", 363 | " [ 5 11]\n", 364 | " [10 8]\n", 365 | " [ 9 7]\n", 366 | " [ 6 12]\n", 367 | " [ 4 14]\n", 368 | " [15 1]] \n", 369 | "\n", 370 | "[[16 5]\n", 371 | " [ 9 4]\n", 372 | " [ 2 11]\n", 373 | " [ 7 14]\n", 374 | " [ 3 10]\n", 375 | " [ 6 15]\n", 376 | " [13 8]\n", 377 | " [12 1]] \n", 378 | "\n", 379 | "[[16 5 9 4 2 11 7 14 3 10 6 15 13 8 12 1]] \n", 380 | "\n", 381 | "np.repeat(np.mat([1, 2]), 4,0) = \n", 382 | "[[1 2]\n", 383 | " [1 2]\n", 384 | " [1 2]\n", 385 | " [1 2]]\n", 386 | "np.repeat(np.mat([1, 2]), 4,0) = \n", 387 | "[[1 1 1 1 2 2 2 2]]\n" 388 | ] 389 | } 390 | ], 391 | "source": [ 392 | "import numpy as np\n", 393 | "\n", 394 | "a_list = [[16, 2, 3, 13], [5, 11, 10, 8], [9, 7, 6, 12] ,[4, 14, 15, 1]]\n", 395 | "print a_list,\"\\n\"\n", 396 | "\n", 397 | "b_list = np.reshape(a_list,[2,8])\n", 398 | "print b_list, \"\\n\"\n", 399 | "\n", 400 | "b_list = np.reshape(a_list,[8,2])\n", 401 | "print b_list, \"\\n\"\n", 402 | "\n", 403 | "b_list = np.reshape(np.transpose(a_list),[8,2])\n", 404 | "print b_list, \"\\n\"\n", 405 | "\n", 406 | "b_list = np.reshape(np.transpose(a_list),[1,-1])\n", 407 | "print b_list, \"\\n\"\n", 408 | "\n", 409 | "\n", 410 | "''' to get [ 1 2 \n", 411 | " 1 2 \n", 412 | " 1 2 \n", 413 | " 1 2] '''\n", 414 | "\n", 415 | "print \"np.repeat(np.mat([1, 2]), 4,0) = \\n\", np.repeat(np.mat([1, 2]), 4,0)\n", 416 | "\n", 417 | "# to get [1 1 1 1 2 2 2 2]\n", 418 | "print \"np.repeat(np.mat([1, 2]), 4,0) = \\n\", np.repeat(np.mat([1, 2]), 4,1)\n", 419 | "\n", 420 | "\n", 421 | "# --------------------------------------------------------------------------\n", 422 | "# Exercise: how to get [1 2 1 2 1 2 1 2]:\n", 423 | "# --------------------------------------------------------------------------\n", 424 | "answer = np.reshape(np.repeat(np.mat([1, 2]), 4,0),[1,-1])" 425 | ] 426 | }, 427 | { 428 | "cell_type": "markdown", 429 | "metadata": {}, 430 | "source": [ 431 | "# block_numpy_unique" 432 | ] 433 | }, 434 | { 435 | "cell_type": "code", 436 | "execution_count": 5, 437 | "metadata": {}, 438 | "outputs": [ 439 | { 440 | "name": "stdout", 441 | "output_type": "stream", 442 | "text": [ 443 | "[[13. 13. 12. 12. 13.]\n", 444 | " [12. 10. 12. 10. 12.]\n", 445 | " [13. 10. 14. 10. 11.]\n", 446 | " [11. 11. 14. 10. 14.]\n", 447 | " [12. 11. 11. 11. 10.]] \n", 448 | "\n", 449 | "[10. 11. 12. 13. 14.] \n", 450 | "\n", 451 | "[ 6 14 2 0 12] [3 3 2 2 3 2 0 2 0 2 3 0 4 0 1 1 1 4 0 4 2 1 1 1 0] [6 6 6 4 3] \n", 452 | "\n", 453 | "[10. 11. 12. 13. 14.] \n", 454 | "\n", 455 | "[10. 10. 10. 10. 10. 10.]\n", 456 | "[11. 11. 11. 11. 11. 11.]\n", 457 | "[12. 12. 12. 12. 12. 12.]\n", 458 | "[13. 13. 13. 13.]\n", 459 | "[14. 14. 14.]\n" 460 | ] 461 | } 462 | ], 463 | "source": [ 464 | "a_list = np.random.rand(5,5) * 5 + 10\n", 465 | "a_list = np.floor(a_list)\n", 466 | "\n", 467 | "print a_list,\"\\n\"\n", 468 | "\n", 469 | "print np.unique(a_list), \"\\n\"\n", 470 | "\n", 471 | "val, indices, inv_indices, counts = np.unique(a_list, return_index = True, return_inverse = True, return_counts = True)\n", 472 | "\n", 473 | "print indices, inv_indices, counts,\"\\n\"\n", 474 | "one_a_list = a_list.flatten()\n", 475 | "print one_a_list[indices],\"\\n\"\n", 476 | "\n", 477 | "for v in val:\n", 478 | " print one_a_list[np.where( one_a_list == v )]\n" 479 | ] 480 | }, 481 | { 482 | "cell_type": "markdown", 483 | "metadata": {}, 484 | "source": [ 485 | "# block_direction_plot" 486 | ] 487 | }, 488 | { 489 | "cell_type": "code", 490 | "execution_count": 6, 491 | "metadata": { 492 | "scrolled": true 493 | }, 494 | "outputs": [ 495 | { 496 | "name": "stdout", 497 | "output_type": "stream", 498 | "text": [ 499 | "3.11780049709 \n", 500 | "\n", 501 | "[[3.1 7. ]\n", 502 | " [1.2 2.4]\n", 503 | " [1. 1.8]\n", 504 | " [2.5 5.2]] \n", 505 | "\n", 506 | "1.0 \n", 507 | "\n", 508 | "[1. 1.8] \n", 509 | "\n" 510 | ] 511 | }, 512 | { 513 | "data": { 514 | "image/png": "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\n", 515 | "text/plain": [ 516 | "" 517 | ] 518 | }, 519 | "metadata": {}, 520 | "output_type": "display_data" 521 | } 522 | ], 523 | "source": [ 524 | "import matplotlib.pyplot as plt\n", 525 | "import math\n", 526 | "import numpy as np\n", 527 | "%matplotlib inline\n", 528 | "\n", 529 | "#A = np.array([[1.2, 2.4], [3.1, 7.0]]);\n", 530 | "A = np.array([[3.1, 7.0], [1.2, 2.4]]);\n", 531 | "B = np.array([[1.0, 1.8], [2.5, 5.2]]);\n", 532 | "\n", 533 | "\n", 534 | "plt.plot( A[0,0], A[0,1], 'bo', markersize=3, color='y')\n", 535 | "plt.plot( A[1,0], A[1,1], 'bo', markersize=3, color='k')\n", 536 | "plt.plot( A[:,0], A[:,1], color='g')\n", 537 | "\n", 538 | "\n", 539 | "plt.plot( B[0,0], B[0,1], 'bo', markersize=3, color='y')\n", 540 | "plt.plot( B[1,0], B[1,1], 'bo', markersize=3, color='k')\n", 541 | "plt.plot( B[:,0], B[:,1], color='c')\n", 542 | "\n", 543 | "A_dir = A[1,:] - A[0,:];\n", 544 | "A_dir = A_dir / np.linalg.norm(A_dir);\n", 545 | "\n", 546 | "B_dir = B[1,:] - B[0,:];\n", 547 | "B_dir = B_dir / np.linalg.norm(B_dir);\n", 548 | "\n", 549 | "theta = math.acos(np.dot(A_dir,B_dir))\n", 550 | "\n", 551 | "print theta,\"\\n\"\n", 552 | "\n", 553 | "text_m = np.append(A,B,axis=0)\n", 554 | "\n", 555 | "print text_m,\"\\n\"\n", 556 | "\n", 557 | "print np.amin(text_m), \"\\n\"\n", 558 | "\n", 559 | "text_min = np.amin(text_m, axis=0)\n", 560 | "\n", 561 | "print text_min, \"\\n\"\n", 562 | "\n", 563 | "\n", 564 | "# the following are equivalent, except the latter cap only to two decimal points\n", 565 | "# plt.text(text_min[0]+1,text_min[1], \"theta = \" + str(theta) + \": same direction\" ); \n", 566 | "\n", 567 | "if abs(theta)< 0.2:\n", 568 | " plt.text(text_min[0]+1,text_min[1], \"theta = \" + \"%0.2f\" % theta + \": same direction\" )\n", 569 | " \n", 570 | "if abs(theta) > math.pi - 0.2:\n", 571 | " plt.text(text_min[0]+1,text_min[1], \"theta = \" + \"%0.2f\" % theta + \": opposite direction\" ); \n", 572 | "\n", 573 | "plt.show()\n" 574 | ] 575 | }, 576 | { 577 | "cell_type": "markdown", 578 | "metadata": {}, 579 | "source": [ 580 | "# block_inline_function" 581 | ] 582 | }, 583 | { 584 | "cell_type": "code", 585 | "execution_count": 7, 586 | "metadata": { 587 | "scrolled": true 588 | }, 589 | "outputs": [ 590 | { 591 | "name": "stdout", 592 | "output_type": "stream", 593 | "text": [ 594 | "0.880797077978\n", 595 | "0.880797077978\n" 596 | ] 597 | } 598 | ], 599 | "source": [ 600 | "def sigmoid_func(x): \n", 601 | " return 1/(1 + math.exp(-x))\n", 602 | "\n", 603 | "print sigmoid_func(2)\n", 604 | "\n", 605 | "sigmoid2 = lambda x: 1/(1 + math.exp(-x))\n", 606 | "\n", 607 | "print sigmoid2(2)" 608 | ] 609 | }, 610 | { 611 | "cell_type": "markdown", 612 | "metadata": { 613 | "collapsed": true 614 | }, 615 | "source": [ 616 | "# block_map_reduce" 617 | ] 618 | }, 619 | { 620 | "cell_type": "code", 621 | "execution_count": 8, 622 | "metadata": {}, 623 | "outputs": [ 624 | { 625 | "name": "stdout", 626 | "output_type": "stream", 627 | "text": [ 628 | "[-2, -1, 0, 1, 2] [0.11920292202211755, 0.2689414213699951, 0.5, 0.7310585786300049, 0.8807970779778823]\n", 629 | "[0.11920292202211755, 0.2689414213699951, 0.5, 0.7310585786300049, 0.8807970779778823]\n", 630 | "0.0103214959021\n", 631 | "0.0103214959021\n", 632 | "0.0865876081473\n" 633 | ] 634 | } 635 | ], 636 | "source": [ 637 | "items = range(-2,3)\n", 638 | "\n", 639 | "# without using MAP function\n", 640 | "sigmoids = []\n", 641 | "for i in items:\n", 642 | " sigmoids.append(sigmoid2(i))\n", 643 | "\n", 644 | "\n", 645 | "print items, sigmoids\n", 646 | "\n", 647 | "# using MAP function\n", 648 | "\n", 649 | "# both does the same thing of the above\n", 650 | "sigmoids2 = map(lambda x: 1/(1 + math.exp(-x)), items)\n", 651 | "sigmoids2 = map(lambda x: sigmoid_func(x), items)\n", 652 | "\n", 653 | "print sigmoids2\n", 654 | "\n", 655 | "\n", 656 | "# without using REDUCE function \n", 657 | "prod = 1\n", 658 | "for i in sigmoids2:\n", 659 | " prod = prod * i\n", 660 | "\n", 661 | "print prod\n", 662 | "\n", 663 | "# with using REDUCE function\n", 664 | "prod2 = reduce((lambda x, y: x * y), sigmoids2)\n", 665 | "\n", 666 | "print prod2\n", 667 | "\n", 668 | "\n", 669 | "# now apply a filter to input before REDUCE\n", 670 | "prod3 = reduce((lambda x, y: x * y), filter(lambda x: x >= 0.2, sigmoids2))\n", 671 | "\n", 672 | "print prod3\n" 673 | ] 674 | }, 675 | { 676 | "cell_type": "markdown", 677 | "metadata": {}, 678 | "source": [ 679 | "### non-MATLAB tutorial: dictionary example" 680 | ] 681 | }, 682 | { 683 | "cell_type": "code", 684 | "execution_count": 9, 685 | "metadata": { 686 | "scrolled": true 687 | }, 688 | "outputs": [ 689 | { 690 | "name": "stdout", 691 | "output_type": "stream", 692 | "text": [ 693 | "{'deep_learning': True, 'language': 'python', 'experience': 2.5, 'package': 'tensorflow'} \n", 694 | "{'deep_learning': True, 'language': 'python', 'experience': 2.5, 'package': 'keras'}\n", 695 | "keras\n", 696 | "len(skill) = 4\n", 697 | "\"language\" in skill = True\n", 698 | "\"language\" not in skill = True\n", 699 | "{'deep_learning': True, 'programming': 'python', 'experience': 2.5, 'package': 'keras'}\n", 700 | "\n", 701 | "for key in skill:\n", 702 | "\n", 703 | "deep_learning\n", 704 | "programming\n", 705 | "experience\n", 706 | "package\n", 707 | "\n", 708 | "for key in skill.iterkeys():\n", 709 | "\n", 710 | "deep_learning\n", 711 | "programming\n", 712 | "experience\n", 713 | "package\n", 714 | "\n", 715 | "for val in skill.itervalues():\n", 716 | "\n", 717 | "True\n", 718 | "python\n", 719 | "2.5\n", 720 | "keras\n", 721 | "for key in skill:\n", 722 | "\n", 723 | "True\n", 724 | "python\n", 725 | "2.5\n", 726 | "keras\n", 727 | "\n", 728 | "\n", 729 | "deep_learning True\n", 730 | "programming python\n", 731 | "experience 2.5\n", 732 | "package keras\n" 733 | ] 734 | } 735 | ], 736 | "source": [ 737 | "# dictionary isn't used in MATLAB, but a useful tool in Python\n", 738 | "skill = {\"package\" : \"tensorflow\", \"experience\": 2.5, \"language\": \"python\", \"deep_learning\": True}\n", 739 | "print skill, type(skill)\n", 740 | "\n", 741 | "skill[\"package\"] = \"keras\"\n", 742 | "\n", 743 | "# note that dictionary isn't indexed sequentially, so print skill[0] doens't work:\n", 744 | "print skill\n", 745 | "\n", 746 | "# -------- hierarchical access: -------------\n", 747 | "job = {\"required\": \"package\", \"optional\": \"langauge\"}\n", 748 | "\n", 749 | "print skill[job[\"required\"]]\n", 750 | "\n", 751 | "print 'len(skill) = ', len(skill)\n", 752 | "\n", 753 | "print '\"language\" in skill = ', \"language\" in skill\n", 754 | "del skill[\"language\"]\n", 755 | "\n", 756 | "\n", 757 | "print '\"language\" not in skill = ', \"language\" not in skill\n", 758 | "\n", 759 | "\n", 760 | "# -------- use d.pudate() instead of d.add() function -\n", 761 | "\n", 762 | "skill.update({'programming': \"python\"})\n", 763 | "print skill\n", 764 | "\n", 765 | "\n", 766 | "# -------- the followings are the same ---------------\n", 767 | "\n", 768 | "print('\\nfor key in skill:\\n')\n", 769 | "\n", 770 | "for key in skill:\n", 771 | " print key\n", 772 | "\n", 773 | "print('\\nfor key in skill.iterkeys():\\n')\n", 774 | " \n", 775 | "for key in skill.iterkeys():\n", 776 | " print key\n", 777 | " \n", 778 | "# -------- the followings are the same ---------------\n", 779 | " \n", 780 | "print('\\nfor val in skill.itervalues():\\n')\n", 781 | "\n", 782 | "for val in skill.itervalues():\n", 783 | " print val\n", 784 | "\n", 785 | "print('for key in skill:\\n')\n", 786 | " \n", 787 | "for key in skill:\n", 788 | " print skill[key]\n", 789 | "\n", 790 | "# -------- use something like ---------------\n", 791 | "\n", 792 | "print('\\n')\n", 793 | "\n", 794 | "for key in skill:\n", 795 | " print key, \" \", skill[key]\n", 796 | "\n" 797 | ] 798 | }, 799 | { 800 | "cell_type": "markdown", 801 | "metadata": {}, 802 | "source": [ 803 | "### non-MATLAB tutorial: quick pandas" 804 | ] 805 | }, 806 | { 807 | "cell_type": "code", 808 | "execution_count": 10, 809 | "metadata": {}, 810 | "outputs": [ 811 | { 812 | "name": "stdout", 813 | "output_type": "stream", 814 | "text": [ 815 | "0 1\n", 816 | "1 3\n", 817 | "2 5\n", 818 | "3 str\n", 819 | "4 6\n", 820 | "5 8\n", 821 | "dtype: object\n", 822 | "0 1\n", 823 | "1 3\n", 824 | "2 5\n", 825 | "3 67\n", 826 | "4 6\n", 827 | "5 8\n", 828 | "dtype: int64\n", 829 | "0 1\n", 830 | "1 1\n", 831 | "2 1\n", 832 | "3 1\n", 833 | "dtype: int64\n", 834 | "0 0\n", 835 | "1 1\n", 836 | "2 2\n", 837 | "3 3\n", 838 | "dtype: int64\n", 839 | "s.values = [0 1 2 3]\n", 840 | "\n", 841 | "\n", 842 | "DatetimeIndex(['2018-01-01', '2018-01-02', '2018-01-03', '2018-01-04',\n", 843 | " '2018-01-05'],\n", 844 | " dtype='datetime64[ns]', freq='D') \n", 845 | "\n", 846 | " exp_1 exp_2 exp_3\n", 847 | "2018-01-01 1.309386 -1.473402 0.990067\n", 848 | "2018-01-02 0.024094 0.689104 -2.017295\n", 849 | "2018-01-03 -1.050912 -0.765972 1.305284\n", 850 | "2018-01-04 -1.846148 0.917770 -1.869699\n", 851 | "2018-01-05 0.664957 1.200568 -1.259691\n", 852 | "np.array([3] * 4,dtype='int32') = [3 3 3 3]\n", 853 | "\n", 854 | "\n", 855 | " class comment date mark start stop\n", 856 | "0 3 TBA 2018-01-01 pass 1.0 1.0\n", 857 | "1 3 TBA 2018-01-02 fail 1.0 1.0\n", 858 | "2 3 TBA 2018-01-03 fail 1.0 1.0\n", 859 | "3 3 TBA 2018-01-04 pass 1.0 1.0\n" 860 | ] 861 | } 862 | ], 863 | "source": [ 864 | "import pandas as pd\n", 865 | "import numpy as np\n", 866 | "\n", 867 | "# ----------------------------------------------------------------\n", 868 | "# something about series \n", 869 | "# ----------------------------------------------------------------\n", 870 | "\n", 871 | "\n", 872 | "# series can be of different type:\n", 873 | "s = pd.Series([1,3,5,\"str\",6,8.])\n", 874 | "print s\n", 875 | "\n", 876 | "# series can be of same type:\n", 877 | "s = pd.Series([1,3,5,67,6,8])\n", 878 | "print s\n", 879 | "\n", 880 | "# series in value and range:\n", 881 | "s = pd.Series(1,index=list(range(4)))\n", 882 | "print s\n", 883 | "\n", 884 | "s = pd.Series(range(4),index=list(range(4)))\n", 885 | "print s\n", 886 | "\n", 887 | "print \"s.values = \", s.values\n", 888 | "\n", 889 | "print \"\\n\"\n", 890 | "\n", 891 | "\n", 892 | "# ----------------------------------------------------------------\n", 893 | "# create the first DataFrame\n", 894 | "# ----------------------------------------------------------------\n", 895 | "\n", 896 | "\n", 897 | "dates = pd.date_range('20180101', periods=5)\n", 898 | "print dates, \"\\n\"\n", 899 | "\n", 900 | "\n", 901 | "columns = ['exp_1', 'exp_2', 'exp_3']\n", 902 | "\n", 903 | "df = pd.DataFrame(np.random.randn(len(dates),len(columns)), index=dates, columns=columns)\n", 904 | "\n", 905 | "# swap inputs do not matter\n", 906 | "df = pd.DataFrame(np.random.randn(len(dates),len(columns)), columns=columns, index=dates)\n", 907 | "\n", 908 | "print df\n", 909 | "\n", 910 | "# following unlablled version doens't work:\n", 911 | "#df = pd.DataFrame(np.random.randn(6,4), columns, dates)\n", 912 | "\n", 913 | "print \"np.array([3] * 4,dtype='int32') = \", np.array([3] * 4, dtype='int32')\n", 914 | "\n", 915 | "print \"\\n\"\n", 916 | "\n", 917 | "# --------------------------------------------------------------------------------------\n", 918 | "# note that \"df2.start\" are repeating the same element for as many rows as possible:\n", 919 | "# --------------------------------------------------------------------------------------\n", 920 | "\n", 921 | "df2 = pd.DataFrame({'start' : 1.0,\n", 922 | " 'date' : pd.date_range('20180101', periods=4),\n", 923 | " 'stop' : pd.Series(1,index=range(4),dtype='float32'),\n", 924 | " 'class' : np.array([3] * 4,dtype='int32'),\n", 925 | " 'mark' : pd.Categorical([\"pass\",\"fail\",\"fail\",\"pass\"]),\n", 926 | " 'comment' : \"TBA\"})\n", 927 | "\n", 928 | "print df2" 929 | ] 930 | }, 931 | { 932 | "cell_type": "markdown", 933 | "metadata": {}, 934 | "source": [ 935 | "### non-MATLAB tutorial: numpy pass by reference" 936 | ] 937 | }, 938 | { 939 | "cell_type": "code", 940 | "execution_count": 11, 941 | "metadata": {}, 942 | "outputs": [ 943 | { 944 | "name": "stdout", 945 | "output_type": "stream", 946 | "text": [ 947 | "numpy.array(A)[2]=2: A = \n", 948 | "[[1. 1. 1.]\n", 949 | " [1. 1. 1.]\n", 950 | " [1. 1. 1.]]\n", 951 | "numpy.array(A)[2]=2: A = \n", 952 | "[[1. 1. 1.]\n", 953 | " [1. 1. 1.]\n", 954 | " [2. 2. 2.]]\n" 955 | ] 956 | } 957 | ], 958 | "source": [ 959 | "import numpy as np\n", 960 | "\n", 961 | "A = np.mat(np.ones((3,3)))\n", 962 | "\n", 963 | "# ---------------------------------------------------------------------------\n", 964 | "# pass by object\n", 965 | "# ---------------------------------------------------------------------------\n", 966 | "\n", 967 | "np.array(A)[2]=2\n", 968 | "print 'numpy.array(A)[2]=2: A = \\n', A\n", 969 | "\n", 970 | "# ---------------------------------------------------------------------------\n", 971 | "# pass by reference\n", 972 | "# ---------------------------------------------------------------------------\n", 973 | "np.asarray(A)[2]=2\n", 974 | "print 'numpy.array(A)[2]=2: A = \\n', A" 975 | ] 976 | }, 977 | { 978 | "cell_type": "markdown", 979 | "metadata": {}, 980 | "source": [ 981 | "### non-MATLAB tutorial: numpy shape conversion" 982 | ] 983 | }, 984 | { 985 | "cell_type": "code", 986 | "execution_count": 12, 987 | "metadata": {}, 988 | "outputs": [ 989 | { 990 | "name": "stdout", 991 | "output_type": "stream", 992 | "text": [ 993 | "np.array([3] * 4 = \n", 994 | "[3 3 3 3] \n", 995 | "\n", 996 | "np.array([3] * 4 = \n", 997 | "[3 3 3 3] \n", 998 | "\n", 999 | "np.squeeze(A.flatten()) = \n", 1000 | "[[1. 1. 1. 1. 1. 1. 2. 2. 2.]] (1, 9) \n", 1001 | "\n", 1002 | "nd array = \n", 1003 | "[[1. 1. 1.]\n", 1004 | " [1. 1. 1.]\n", 1005 | " [2. 2. 2.]] (3, 3) \n", 1006 | "\n", 1007 | "1d array = \n", 1008 | "[1. 1. 1. 1. 1. 1. 2. 2. 2.] (9,) \n", 1009 | "\n" 1010 | ] 1011 | } 1012 | ], 1013 | "source": [ 1014 | "import numpy as np\n", 1015 | "\n", 1016 | "print \"np.array([3] * 4 = \\n\", np.array([3] * 4), '\\n' \n", 1017 | "print \"np.array([3] * 4 = \\n\", np.array([3] * 4), '\\n' \n", 1018 | "\n", 1019 | "# ---------------------------------------------------------------------------\n", 1020 | "# convert a 3x3 matrix to 1x9 matrix\n", 1021 | "# ---------------------------------------------------------------------------\n", 1022 | "\n", 1023 | "ans = np.squeeze(A.flatten())\n", 1024 | "print \"np.squeeze(A.flatten()) = \\n\", ans, ans.shape, type(ans), '\\n'\n", 1025 | "\n", 1026 | "# ---------------------------------------------------------------------------\n", 1027 | "# convert a nd matrix to nd numpy array\n", 1028 | "# ---------------------------------------------------------------------------\n", 1029 | "\n", 1030 | "arr = np.array(A)\n", 1031 | "print \"nd array = \\n\", arr, arr.shape, type(arr), '\\n'\n", 1032 | "\n", 1033 | "# ---------------------------------------------------------------------------\n", 1034 | "# then, convert from nd numpy array to 1-d array,\n", 1035 | "# ---------------------------------------------------------------------------\n", 1036 | "ans = arr.ravel()\n", 1037 | "\n", 1038 | "print \"1d array = \\n\", ans, ans.shape, type(ans), '\\n'\n", 1039 | "\n" 1040 | ] 1041 | }, 1042 | { 1043 | "cell_type": "code", 1044 | "execution_count": null, 1045 | "metadata": {}, 1046 | "outputs": [], 1047 | "source": [] 1048 | } 1049 | ], 1050 | "metadata": { 1051 | "kernelspec": { 1052 | "display_name": "Python 2", 1053 | "language": "python", 1054 | "name": "python2" 1055 | }, 1056 | "language_info": { 1057 | "codemirror_mode": { 1058 | "name": "ipython", 1059 | "version": 2 1060 | }, 1061 | "file_extension": ".py", 1062 | "mimetype": "text/x-python", 1063 | "name": "python", 1064 | "nbconvert_exporter": "python", 1065 | "pygments_lexer": "ipython2", 1066 | "version": "2.7.14" 1067 | } 1068 | }, 1069 | "nbformat": 4, 1070 | "nbformat_minor": 2 1071 | } 1072 | -------------------------------------------------------------------------------- /conversion.m: -------------------------------------------------------------------------------- 1 | % ------------------------------------------------------------- 2 | % This is a growing tutorial demonstrates some MATLAB examples and their 3 | % equivalent code in Python 4 | % 5 | % Each Matlab block function corresponds a block in conversion.ipynb 6 | % 7 | % 8 | % written by Richard Xu (yida.xu@uts.edu.au) 9 | % 10 | % Feb 2018 11 | % 12 | % ------------------------------------------------------------- 13 | 14 | function conversion 15 | 16 | clear all; 17 | clc; 18 | 19 | %block_numpy_multiply 20 | %block_matrix_find 21 | %block_numpy_reshape 22 | %block_numpy_unique 23 | %block_direction_plot 24 | %block_inline_function 25 | %block_map_reduce 26 | block_read_csv 27 | end 28 | 29 | 30 | % this is to create another table to compute the total sales 31 | function block_read_csv 32 | 33 | store = readtable('superstore.xls'); 34 | 35 | 36 | % ---------------------------------------------- 37 | % Method 2 38 | % ---------------------------------------------- 39 | 40 | tic; 41 | 42 | [val, indices, inv_indices] = unique(store.CustomerID); 43 | 44 | profit = zeros(length(val),1); 45 | 46 | for v = 1:length(val) 47 | cus_list = find(store.Profit(inv_indices == v)); 48 | profit(v)= sum(store.Profit(cus_list)); 49 | end 50 | 51 | profit_1 = table(val,profit); 52 | 53 | profit_1.Properties.VariableNames = {'CustomerID','Profit'}; 54 | 55 | toc; 56 | 57 | 58 | % ---------------------------------------------- 59 | % Method 3 60 | % ---------------------------------------------- 61 | 62 | tic; 63 | 64 | [val, indices, inv_indices] = unique(store.CustomerID); 65 | 66 | groupSums = accumarray(inv_indices,store.Profit); 67 | 68 | profit_3 = table(val,groupSums); 69 | 70 | profit_3.Properties.VariableNames = {'CustomerID','Profit'}; 71 | 72 | toc; 73 | 74 | end 75 | 76 | 77 | 78 | % this is a peudo map reduce 79 | 80 | function block_map_reduce 81 | 82 | items = -2:3-0.001 83 | sigmoid_func2 = @(x) 1 /(1 + exp(-x)); 84 | 85 | 86 | sigmoids = []; 87 | for i = 1:length(items) 88 | sigmoids = [sigmoids sigmoid_func2(items(i))]; 89 | end 90 | 91 | display(sigmoids) 92 | 93 | sigmoids = arrayfun(@(x) 1/(1 + exp(-x)), items) 94 | 95 | prods = prod(sigmoids); 96 | prod3 = prod(sigmoids(sigmoids>0.2)); 97 | 98 | display(prods); 99 | display(prod3); 100 | 101 | end 102 | 103 | 104 | function block_inline_function 105 | 106 | function val = sigmoid_func(x) 107 | val = 1 /(1 + exp(-x)); 108 | end 109 | 110 | display(sigmoid_func(2)) 111 | 112 | sigmoid_func2 = @(x) 1 /(1 + exp(-x)); 113 | 114 | display(sigmoid_func2(2)) 115 | 116 | end 117 | 118 | 119 | 120 | function block_numpy_multiply 121 | 122 | A = [3 4; 2 5]; 123 | B = [5 6; 3, 2]; 124 | 125 | % ---------------------------- 126 | 127 | C = A * B; 128 | C2 = A* B * C; 129 | display (C); 130 | display (C2); 131 | 132 | % ---------------------------- 133 | 134 | W1 = A .* B; 135 | W2 = A .* B .* C; 136 | 137 | display(W1) 138 | display(W2); 139 | 140 | end 141 | 142 | % -------------------------------------- 143 | 144 | function block_matrix_find 145 | 146 | a_list = magic(3); 147 | a_list = [ 8, 1, 6; 3, 5, 7; 4, 9, 2] 148 | 149 | display(a_list > 5) 150 | display(a_list( a_list > 5 )) 151 | 152 | end 153 | 154 | 155 | 156 | function block_numpy_reshape 157 | 158 | a_list = [16, 2, 3, 13; 5, 11, 10, 8; 9, 7, 6, 12 ;4, 14, 15, 1]; 159 | 160 | b_list = reshape(a_list,[2,8]); 161 | display(b_list); 162 | 163 | b_list = reshape(a_list,[8,2]); 164 | display(b_list); 165 | 166 | b_list = reshape(a_list',[8,2]); 167 | display(b_list); 168 | 169 | b_list = reshape(a_list',1,[]); 170 | display(b_list); 171 | 172 | display(a_list(1,4)) 173 | 174 | 175 | end 176 | 177 | 178 | 179 | function block_numpy_unique 180 | a_list = floor(rand(5,5) * 5) + 5 181 | display(a_list) 182 | [val, indices, inv_indices] = unique(a_list); 183 | 184 | % MATLAB can access elements directly without changing to 1-D 185 | for v = 1:length(val) 186 | display( a_list(find( a_list == val(v) ))) 187 | end 188 | 189 | end 190 | 191 | 192 | 193 | function block_direction_plot 194 | 195 | %A = [1.2 2.4; 3.1 7.0]; 196 | A = [3.1 7.0; 1.2 2.4]; 197 | B = [1.0 1.8; 2.5 5.2]; 198 | 199 | line(A(:,1),A(:,2),'color',[0 1 0]); 200 | hold on; 201 | plot(A(1,1),A(1,2),'o','MarkerFaceColor',[0.9 0.9 0.9]); 202 | plot(A(2,1),A(2,2),'o','MarkerFaceColor',[0 0 0]); 203 | 204 | line(B(:,1),B(:,2),'color',[0 1 1]); 205 | 206 | plot(B(1,1),B(1,2),'o','MarkerFaceColor',[0.9 0.9 0.9]); 207 | plot(B(2,1),B(2,2),'o','MarkerFaceColor',[0 0 0]); 208 | 209 | A_dir = A(2,:) - A(1,:); 210 | A_dir = A_dir /norm(A_dir); 211 | 212 | B_dir = B(2,:) - B(1,:); 213 | B_dir = B_dir /norm(B_dir); 214 | 215 | theta = acos(A_dir * B_dir') 216 | 217 | text_min = min([A;B]); 218 | 219 | if abs(theta)< 0.2 220 | text(text_min(1)+1,text_min(2),['theta = ' num2str(theta,'%.2f') ': same direction']); 221 | end 222 | 223 | if abs(theta) > pi - 0.2 224 | text(text_min(1)+1,text_min(2),['theta = ' num2str(theta,'%.2f') ': opposite direction']); 225 | end 226 | 227 | end 228 | -------------------------------------------------------------------------------- /superstore.xls: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roboticcam/matlab2python/5dedd80d0e75d195caf3e88a9efb9049d86c4f9f/superstore.xls --------------------------------------------------------------------------------