|
| 1 | +# Basic Mathematics |
| 2 | +## What is a Matrix? |
| 3 | +A matrix is a collection of numbers ordered in rows and columns. Here is one. |
| 4 | + |
| 5 | +<body> |
| 6 | + <table> |
| 7 | + <tr> |
| 8 | + <td>1</td> |
| 9 | + <td>2</td> |
| 10 | + <td>3</td> |
| 11 | + </tr> |
| 12 | + <tr> |
| 13 | + <td>4</td> |
| 14 | + <td>5</td> |
| 15 | + <td>6</td> |
| 16 | + </tr> |
| 17 | + <tr> |
| 18 | + <td>7</td> |
| 19 | + <td>8</td> |
| 20 | + <td>9</td> |
| 21 | + </tr> |
| 22 | + </table> |
| 23 | +</body> |
| 24 | + |
| 25 | + |
| 26 | +A matrix is generally written within square brackets[]. The dimensions of a matrix is represented by (Number of rows x Number of columns).The dimensions of the above matrix is 3x3. |
| 27 | + |
| 28 | +Matrices are the main characters in mathematical operations like addition, subtraction etc, especially those used in Pandas and NumPy. They can contain only numbers, symbols or expressions. |
| 29 | + |
| 30 | +In order to refer to a particular element in the matrix we denote it by : |
| 31 | +A<sub>ij</sub> |
| 32 | + |
| 33 | +where i represents the ith row and j represents the jth column of the matrix. |
| 34 | + |
| 35 | +## Scalars and Vectors |
| 36 | +### Scalars |
| 37 | +There exists specific cases of matrices which are also widely used. |
| 38 | + |
| 39 | +A matrix with only one row and column i.e. containing only one element is commonly referred to as a scalar. |
| 40 | + |
| 41 | +The numbers ```[12] ; [-5] ; [0] ; [3.14]``` all represent scalars. Scalars have 0 dimensions. |
| 42 | + |
| 43 | +### Vectors |
| 44 | +Vectors are objects with 1 dimension. They sit somewhere between scalars and matrices. They can also be referred to as one dimensional matrices. |
| 45 | + |
| 46 | +```[1 3 5]``` represents a vector with dimension 1x3. |
| 47 | + |
| 48 | +A vector is the simplest linear algebraic object.A matrix can be refered to as a collection of vectors |
| 49 | + |
| 50 | +Vectors are broadly classified into 2 types: |
| 51 | +- Row Vectors: Is of the form 1 x n where n refers to the number of columns the vector has. |
| 52 | +- Column Vectors: Is of the form m x 1 where m refers to the number of rows the vector has. |
| 53 | + |
| 54 | +m or n are also called as the length of the column and row vector respectively. |
| 55 | + |
| 56 | +## Arrays in Python |
| 57 | + |
| 58 | +To understand arrays, first let us start by declaring scalars, vectors and matrices in Python. |
| 59 | + |
| 60 | +First we need to import numpy. We do so by importing it as 'np' as it provides better readability, namespace clarity and also aligns with the community guidelines. |
| 61 | + |
| 62 | +```python |
| 63 | +import numpy as np |
| 64 | +``` |
| 65 | +Next up, we declare a scalar s as, |
| 66 | +``` |
| 67 | +s = 5 |
| 68 | +``` |
| 69 | + |
| 70 | + |
| 71 | + |
| 72 | +Now we declare a vector, |
| 73 | +```python |
| 74 | +v = np.array([5,-2,4]) |
| 75 | +``` |
| 76 | +On printing v we get the following output, |
| 77 | +```python |
| 78 | +array([5,-2,4]) |
| 79 | +``` |
| 80 | +By default, a vector is declared as a **'row vector'**. |
| 81 | + |
| 82 | +Finally, we declare matrices, |
| 83 | +```python |
| 84 | +m=np.array([[5,12,6],[-3,0,14]]) |
| 85 | +``` |
| 86 | +On printing m we get, |
| 87 | +```python |
| 88 | +array([[5,12,6], |
| 89 | + [-3,0,14]]) |
| 90 | +``` |
| 91 | +> The type() function is used to return the data type of a given variable. |
| 92 | +
|
| 93 | +* The type(s) will return **'int'**. |
| 94 | + |
| 95 | +* The type(v) will return **'numpy.ndarray'** which represents a **n-dimensional array**, since it is a 1 dimensional array. |
| 96 | + |
| 97 | + * The type(m) will also return **'numpy.ndarray'** since it is a 2-dimensional array. |
| 98 | + |
| 99 | +These are some ways in which arrays are useful in python. |
| 100 | + |
| 101 | +> The shape() function is used to return the shape of a given variable. |
| 102 | +
|
| 103 | +* m.shape() returns (2,3) since we are dealing with a (2,3) matrix. |
| 104 | + |
| 105 | +* v.shape() returns(3,) indicates it has only one dimensional or that it stores 3 elements in order. |
| 106 | + |
| 107 | +* However, 'int' objects do not have shape and therefore s.shape() gives an error. |
| 108 | + |
| 109 | +## What is a Tensor? |
| 110 | +A Tensor can be thought of as a collection of matrices. It has dimensions k x m x n. |
| 111 | + |
| 112 | +**NOTE:** Scalars, vectors and matrices are also tensors of rank 0,1,2 respectively. |
| 113 | + |
| 114 | +Tensors can be stored in ndarrays. |
| 115 | + |
| 116 | +Let's create a tensor with 2 matrices, |
| 117 | +```python |
| 118 | +m1=np.array([[5,12,6],[-3,0,14]]) |
| 119 | +m2=np.array([[2,1,8],[-6,2,0]]) |
| 120 | +t=np.array([m1,m2]) |
| 121 | +``` |
| 122 | +Upon printing t we get, |
| 123 | +```python |
| 124 | +array([[[5,12,6], |
| 125 | + [-3,0,14]], |
| 126 | + |
| 127 | + [[2,1,8], |
| 128 | + [-6,2,0]]]) |
| 129 | +``` |
| 130 | +If we check it's shape, we see that is is a **(2,2,3)** object. |
| 131 | + |
| 132 | +If we want to manually create a tensor we write, |
| 133 | +```python |
| 134 | +t=np.array([[[5,12,6], [-3,0,14]],[[2,1,8], [-6,2,0]]]) |
| 135 | +``` |
| 136 | + ## Addition and Subtraction in Matrices |
| 137 | + |
| 138 | + ### Addition |
| 139 | + For 2 matrices to be added to one another they must have **same dimensions**. |
| 140 | + |
| 141 | + If we have 2 matrices say, |
| 142 | + |
| 143 | +```python |
| 144 | +A=np.array([[5,12,6],[-3,0,14]]) |
| 145 | +B=np.array([[2,1,8],[-6,2,0]]) |
| 146 | +C= A+B |
| 147 | + ``` |
| 148 | +The element at position A<sub>ij</sub> gets added to the element at position B<sub>ij</sub>. It's that simple! |
| 149 | +The above input will give the resultant C as: |
| 150 | +```python |
| 151 | +array([[7,13,14], |
| 152 | + [-9,2,14]]) |
| 153 | +``` |
| 154 | +### Subtraction |
| 155 | + |
| 156 | +As we know, subtraction is a type of addition, the same rules apply here. |
| 157 | + |
| 158 | + If we have 2 matrices say, |
| 159 | + |
| 160 | +```python |
| 161 | +A=np.array([[5,12,6],[-3,0,14]]) |
| 162 | +B=np.array([[2,1,8],[-6,2,0]]) |
| 163 | +C= A-B |
| 164 | + ``` |
| 165 | + |
| 166 | +The element at position B<sub>ij</sub> gets subtracted from the element at position A<sub>ij</sub>. |
| 167 | +The above input will give the resultant C as: |
| 168 | +```python |
| 169 | +array([[3,11,-2], |
| 170 | + [3,-2,14]]) |
| 171 | +``` |
| 172 | +Similarly the same operations can be done with **floating point numbers** as well. |
| 173 | + |
| 174 | +In a similar fashion, we can add or subtract vectors as well with the condition that they must be of the **same length**. |
| 175 | +```python |
| 176 | +A=np.array([1,2,3,4,5]) |
| 177 | +B=np.array([6,7,8,9,10]) |
| 178 | +C= A+B |
| 179 | + ``` |
| 180 | +The result is a vector of length 5 with C as, |
| 181 | +```python |
| 182 | +array([7,9,11,13,15]) |
| 183 | +``` |
| 184 | + ### Addition of scalars with vectors & matrices |
| 185 | + |
| 186 | + Scalars show unique behaviour when added to matrices or vectors. |
| 187 | + |
| 188 | + To demonstrate their behaviour, let's use an example, |
| 189 | + Let's declare a matrix, |
| 190 | + |
| 191 | +```python |
| 192 | +A=np.array([[5,12,6],[-3,0,14]]) |
| 193 | +A+1 |
| 194 | +``` |
| 195 | +We see that if we perform the above function, i.e. add scalar [1] to the matrix A we get the output, |
| 196 | +```python |
| 197 | +array([[6,13,7],[-2,1,15]]) |
| 198 | +``` |
| 199 | +We see that the scalar is added to the matrix elementwise, i.e. each element gets incremented by 1. |
| 200 | + |
| 201 | +**The same applies to vectors as well.** |
| 202 | + |
| 203 | +Mathematically, it is not allowed as the shape of scalars are different from vectors or matrices but while programming in Python it works. |
| 204 | + |
| 205 | +## Transpose of Matrices & Vectors |
| 206 | +### Transposing Vectors |
| 207 | + |
| 208 | +If X is the vector, then the transpose of the vector is represented as X<sup>T</sup>. It changes a vector of dimension n x 1 into a vector of dimension 1 x n, i.e. a row vector to a column vector and vice versa. |
| 209 | + |
| 210 | +> * The values are not changing or transforming ; only their position is. |
| 211 | +> * Transposing the same vector (object) twice yields the initial vector (object). |
| 212 | +
|
| 213 | +```python |
| 214 | +x=np.array([1,2,3)) |
| 215 | +``` |
| 216 | +Transposing this in python using ```x.T``` will give |
| 217 | +```python |
| 218 | +array([1,2,3)) |
| 219 | +``` |
| 220 | +which is the same vector as the one taken as input. |
| 221 | + |
| 222 | +> 1-Dimensional arrays don't really get transposed (in the memory of the computer) |
| 223 | + |
| 224 | +To transpose a vector, we need to reshape it first. |
| 225 | +```python |
| 226 | +x_new= x.reshape(1,3) |
| 227 | +x_new.T |
| 228 | +``` |
| 229 | +will now result in the vector getting transposed, |
| 230 | +```python |
| 231 | +array([[1], |
| 232 | + [2], |
| 233 | + [3]]) |
| 234 | +``` |
| 235 | + |
| 236 | +### Transposing Matrices |
| 237 | + |
| 238 | +If M is a matrix, then the transpose of the matrix M is represented as M<sup>T</sup>. When transposed, a m x n matrix becomes a n x m matrix. |
| 239 | + |
| 240 | +The element M<sub>ij</sub> of the initial matrix becomes the N<sub>ji</sub> where N is the transposed matrix of M. |
| 241 | + |
| 242 | +Let's understand this further with the help of of an example, |
| 243 | +```python |
| 244 | +A = np.array([[1,5,-6],[8,-2,0]]) |
| 245 | +``` |
| 246 | +The output for the above code snippet will be, |
| 247 | +```python |
| 248 | +array([[1,5,-6], |
| 249 | + [8,-2,0]]) |
| 250 | +``` |
| 251 | +> **array.T** returns the transpose of an array (matrix). |
| 252 | + |
| 253 | +```python |
| 254 | +A.T |
| 255 | +``` |
| 256 | +will give the output as, |
| 257 | +```python |
| 258 | +array([[1,8], |
| 259 | + [5,-2], |
| 260 | + [-6,0]]) |
| 261 | +``` |
| 262 | + |
| 263 | +Hope the following examples have cleared your concept on transposing. |
| 264 | + |
| 265 | +## Dot Product |
| 266 | + |
| 267 | +> **np.dot()** returns the dot product of two objects |
| 268 | +> Dot product is represented by ( * ), for example, x(dot)y = x * y |
| 269 | +> |
| 270 | +### Scalar * Scalar |
| 271 | +Let's start with scalar multiplication first. |
| 272 | + |
| 273 | +``` [6] * [5] = [30] |
| 274 | + [10] * [-2] = [-20] |
| 275 | +``` |
| 276 | +It is the same multiplication that we are familiar with since learnt as kids. |
| 277 | + Therefore, ```np.dot([6]*[5])``` returns ```30```. |
| 278 | + |
| 279 | +### Vector * Vector |
| 280 | +To multiply vectors with one another, they must be of **same length**. |
| 281 | + |
| 282 | +Now let's understand this with an example, |
| 283 | +```python |
| 284 | +x = np.array([2,8,-4]) |
| 285 | +y = np.array([1,-7,3]) |
| 286 | +``` |
| 287 | + |
| 288 | +The dot product returns the elementwise product of the vector i.e. |
| 289 | +x * y = ( x<sub>1</sub> * y<sub>1</sub> ) + ( x<sub>2</sub> * y<sub>2</sub> ) + ( x<sub>3</sub> * y<sub>3</sub> ) in the above example. |
| 290 | + |
| 291 | +Therefore, ```np.dot(x,y)``` gives ```[-66]``` as the input. |
| 292 | + |
| 293 | +We observe that **dot product of 2 vectors returns a scalar**. |
| 294 | + |
| 295 | +### Scalar * Vector |
| 296 | + |
| 297 | +When we multiply a scalar with a vector, we observe that each element of the vector gets multiplied to the scalar individually. |
| 298 | + |
| 299 | +A scalar k when multiplied to a vector v([x1,x2,x3]) gives the product = [(k * x1) + (k * x2) + (k * x3)] |
| 300 | + |
| 301 | +An example would bring further clarity, |
| 302 | +```python |
| 303 | +y = np.array([1,-7,3]) |
| 304 | +y*5 |
| 305 | +``` |
| 306 | +will give the following output |
| 307 | +```python |
| 308 | +array[(5,-35,15)] |
| 309 | +``` |
| 310 | + |
| 311 | +We observe that **dot product of 2 vectors returns a scalar**. |
| 312 | + |
| 313 | +We observe that **dot product of a vector and a scalar returns a vector**. |
| 314 | + |
| 315 | +## Dot Product of Matrices |
| 316 | + |
| 317 | +### Scalar * Matrix |
| 318 | + Dot product of a scalar with a matrix works similar to dot product of a vector with a scalar. |
| 319 | +Now, we come to a very important concept which will be very useful to us while working in Python. |
| 320 | + |
| 321 | +Each element of the vector gets multiplied to the scalar individually. |
| 322 | + |
| 323 | +```python |
| 324 | +A = np.array([[1,5,-6],[8,-2,0]]) |
| 325 | +B = 3 * A |
| 326 | +``` |
| 327 | +will give the resultant B as |
| 328 | +```python |
| 329 | +array([[3,15,-18], |
| 330 | + [24,-6,0]]) |
| 331 | +``` |
| 332 | +Thus each element gets multiplied by 3. |
| 333 | +> NOTE: The dot product of a scalar and a matrix gives a matrix of the same shape as the input matrix. |
| 334 | + |
| 335 | +### Matrix * Matrix |
| 336 | + A matrix can be multipied to a matrix. However it has certain compatibility measures, |
| 337 | + * We can only multiply an m x n matrix with an n x k matrix |
| 338 | + * Basically the 2nd dimension of the first matrix has to match the 1st dimension of the 2nd matrix. |
| 339 | +> The output of a m x n matrix with a n x k matrix gives a **m x k** matrix. |
| 340 | + |
| 341 | +**Whenever we have a dot product of 2 matrices, we multiply row vectors within one matrix to the column vector of 2nd matrix.** |
| 342 | + |
| 343 | +For example, let's use multiply a row vector to a column vector to understand it further. |
| 344 | + |
| 345 | +``` |
| 346 | + ([[1] |
| 347 | + ([2 8 4]) * [2] = [(2*1) + (8*2) + (4*3)] = [30] |
| 348 | + [3]]) |
| 349 | +``` |
| 350 | +Now, let's multiply a 2 x 3 matrix with a 3 x 2 matrix. |
| 351 | +``` |
| 352 | + ([[A1,A2,A3], * ([[B1,B2] ([[(A1 * B1 + A2 * B3 + A3 * B5) , (A1 * B2 + A2 * B4 + A3 * B6)] |
| 353 | + [A4,A5,A6]]) [B3,B4], = [ (A4 * B1 + A5 * B3 + A6 * B5) , (A4 * B2 + A5 * B4 + A6 * B6)]]) |
| 354 | + [B5,B6]]) |
| 355 | +``` |
| 356 | +Thus we obtain a 2 x 2 matrix. |
| 357 | + |
| 358 | +We use the np.dot() method to directly obtain the dot product of the 2 matrices. |
| 359 | + |
| 360 | +Now let's do an example using python just to solidify our knowledge. |
| 361 | + |
| 362 | +```python |
| 363 | +A=np.array([[5,12,6],[-3,0,14]]) |
| 364 | +B=np.array([[2,-1],[8,0],[3,0]]) |
| 365 | +np.dot(A,B) |
| 366 | +``` |
| 367 | +The output we obtain is, |
| 368 | +```python |
| 369 | +array[[124,-5], |
| 370 | + [36, 3]]) |
| 371 | +``` |
0 commit comments