Matrix Algebra for Machine Learning
# Matrix multiplication
# Perform Dot product between each row in the first matrix and each column in the second matrix.
# the columns in the first matrix need to match the number of rows in the second matrix.
# Note that the order of multiplication also matters.
matrix_a = np.asarray([
[0.7, 3],
[1.7, 2],
[0.7, 9]
], dtype=np.float32)
matrix_b = np.asarray([
[113, 3, 10],
[1, 0, 1],
], dtype=np.float32)
product_ab = np.dot(matrix_a, matrix_b)
product_ba = np.dot(matrix_b, matrix_a)
print("product_ab:\n", product_ab)
print("product_ba:\n", product_ba)
# Matrix operations using NumPy
import numpy as np
# Matrix Vector multiplication -
# To multiply a matrix by a vector, the number of columns in the matrix needs to match the number of rows in the vector.
# Assign the matrix to a numpy array named matrix_a
matrix_a = np.asarray([
[0.7,3,9],
[1.7,2,9],
[0.7,9,2]
], dtype=np.float32)
# Assign the vector to a NumPy array named vector_b
vector_b = np.asarray([
[1],
[2],
[1]
], dtype=np.float32)
# To multiply a matrix with a vector in NumPy, we need to use the numpy.dot() function
ab_product = np.dot(matrix_a, vector_b)
print(ab_product)
# Matrix Transpose
# To compute the transpose of a NumPy ndarray, we need to use the numpy.transpose() function
matrix_a = np.asarray([
[0.7, 3],
[1.7, 2],
[0.7, 9]
], dtype=np.float32)
matrix_b = np.asarray([
[113, 3, 10],
[1, 0, 1],
], dtype=np.float32)
transpose_a = np.transpose(matrix_a)
print("transpose_a:\n", transpose_a)
transpose_of_transpose_a = np.transpose(transpose_a)
print("transpose_of_transpose_a:\n", transpose_of_transpose_a)
transpose_b = np.transpose(matrix_b)
print("transpose_b:\n", transpose_b)
trans_ba = np.dot(transpose_b, transpose_a)
print("trans_ba:\n", trans_ba)
trans_ab = np.dot(transpose_a, transpose_b)
print("trans_ab:\n", trans_ab)
product_ab = np.dot(matrix_a, matrix_b)
print("product_ab:\n", product_ab)
trans_product_ab = np.transpose(product_ab)
print("trans_product_ab:\n", trans_product_ab) # Notice that transpose of product_ab is the same as trans_ba
# Identity matrix
i_2 = np.identity(2)
i_3 = np.identity(3)
matrix_33 = np.asarray([
[1,2,3],
[4,5,6],
[7,8,9]
])
matrix_23 = np.asarray([
[0.7,3,1],
[1.7,2,10]
], dtype=np.float32)
identity_33 = np.dot(i_3, matrix_33)
identity_23 = np.dot(i_2, matrix_23)
print("identity_33:\n", identity_33)
print("identity_23:\n", identity_23)
# We should expect identity_33 to match matrix_33 and identity_23 to match matrix_23
# This is because each element in the vector is multiplied exactly once by the diagonal 1 value in the identity matrix
# Matrix Inverse
# How to cancel the coefficient matrix A. In other words, we want to transform A into the identity matrix I
# Multiply the inverse of a matrix by the matrix
import numpy as np
matrix_a = np.asarray([
[1.5, 3],
[1, 4]
])
# Implement the matrix inverse in Python
def matrix_inverse_two(mat):
"""
Function accepts a 2x2 matrix, as a NumPy ndarray,
returns the matrix inverse.
Function first calculates the determinant of the matrix.
"""
determinant = (mat[0,0]*mat[1,1] - mat[0,1]*mat[1,0])
if determinant == 0:
raise ValueError("The matrix is not invertible")
right_matrix = np.asarray([
[mat[1,1], -mat[0,1]],
[-mat[1,0], mat[0,0]]
])
inverse_matrix = np.dot(1/determinant, right_matrix)
return inverse_matrix
inverse_a = matrix_inverse_two(matrix_a)
print(inverse_a)
i_2 = np.dot(inverse_a, matrix_a)
print(i_2)
# Solving the matrix equation
# Create a NumPy ndarray representing A and assign to matrix_a
matrix_a = np.asarray([
[30, -1],
[50, -1]
])
# Create a vector representing b the constants, and assign to vector_b
vector_b = np.asarray([
[-1000],
[-100]
])
# Use the numpy.linalg.inv() function to compute the inverse of a NumPy ndarray
matrix_a_inverse = np.linalg.inv(matrix_a)
# Multiply the inverse of matrix_a with vector_b using numpy.dot()
solution_x = np.dot(matrix_a_inverse, vector_b)
print(solution_x)
# Determinant For Higher Dimensions
# we can only compute the determinant and matrix inverse for square matrices
# we can only compute the matrix inverse of a square matrix when the determinant is not equal to 0
# The determinant of a higher-dimensional system involves breaking down the full matrix into minor matrices
# To compute the determinant in NumPy, we use the numpy.linalg.det() function
# Thankfully, the numpy.linalg.inv() function can work with any n-dimensional square matrix
matrix_22 = np.asarray([
[8, 4],
[4, 2]
])
matrix_33 = np.asarray([
[1, 1, 1],
[1, 1, 6],
[7, 8, 9]
])
det_22 = np.linalg.det(matrix_22)
det_33 = np.linalg.det(matrix_33)
print(det_22)
print(det_33)
# Matrix Inverse For Higher Dimensions
a = np.array([[1,2],[3,4]])
b = np.array([[1,1,1],[0,2,5],[2,5,-1]])
a_inv = np.linalg.inv(a)
b_inv = np.linalg.inv(b)
print(a_inv)
print(b_inv)
mat_22 = np.asarray([[8, 4],[4, 2]])
mat_22_inv = np.linalg.inv(mat_22)
print(mat_22_inv)
mat_33 = np.asarray([[1, 1, 1],[1, 1, 6],[7, 8, 9]])
mat_33_inv = np.linalg.inv(mat_33)
print(mat_33_inv)