01_vector_matrix_ops.py

Download
python 284 lines 8.4 KB
  1"""
  2Vector and Matrix Operations for AI/ML
  3
  4Demonstrates fundamental linear algebra concepts:
  5- Vector spaces: basis, span, linear independence
  6- Matrix operations: multiplication, transpose, inverse
  7- Rank computation
  8- ML applications: feature vectors, weight matrices
  9
 10Dependencies: numpy, matplotlib
 11"""
 12
 13import numpy as np
 14import matplotlib.pyplot as plt
 15
 16
 17def vector_space_basics():
 18    """Demonstrate vector space concepts: basis, span, linear independence"""
 19    print("=" * 60)
 20    print("VECTOR SPACE BASICS")
 21    print("=" * 60)
 22
 23    # Standard basis in R^3
 24    e1 = np.array([1, 0, 0])
 25    e2 = np.array([0, 1, 0])
 26    e3 = np.array([0, 0, 1])
 27
 28    print("\nStandard basis vectors in R^3:")
 29    print(f"e1 = {e1}")
 30    print(f"e2 = {e2}")
 31    print(f"e3 = {e3}")
 32
 33    # Any vector can be expressed as linear combination of basis
 34    v = np.array([3, -2, 5])
 35    print(f"\nVector v = {v}")
 36    print(f"v = 3*e1 + (-2)*e2 + 5*e3")
 37    reconstructed = 3*e1 + (-2)*e2 + 5*e3
 38    print(f"Reconstructed: {reconstructed}")
 39    print(f"Match: {np.allclose(v, reconstructed)}")
 40
 41    # Linear independence check
 42    print("\n--- Linear Independence ---")
 43    v1 = np.array([1, 2, 3])
 44    v2 = np.array([4, 5, 6])
 45    v3 = np.array([7, 8, 9])  # v3 is in span of v1, v2
 46
 47    # Stack vectors as columns and check rank
 48    A = np.column_stack([v1, v2, v3])
 49    rank = np.linalg.matrix_rank(A)
 50    print(f"\nVectors: {v1}, {v2}, {v3}")
 51    print(f"Matrix A (vectors as columns):\n{A}")
 52    print(f"Rank(A) = {rank}")
 53    print(f"Linearly independent: {rank == 3} (expect False)")
 54
 55    # Linearly independent set
 56    w1 = np.array([1, 0, 0])
 57    w2 = np.array([0, 1, 0])
 58    w3 = np.array([1, 1, 1])
 59    B = np.column_stack([w1, w2, w3])
 60    rank_B = np.linalg.matrix_rank(B)
 61    print(f"\nVectors: {w1}, {w2}, {w3}")
 62    print(f"Matrix B:\n{B}")
 63    print(f"Rank(B) = {rank_B}")
 64    print(f"Linearly independent: {rank_B == 3}")
 65
 66
 67def matrix_operations():
 68    """Demonstrate matrix multiplication, transpose, inverse"""
 69    print("\n" + "=" * 60)
 70    print("MATRIX OPERATIONS")
 71    print("=" * 60)
 72
 73    # Matrix multiplication
 74    A = np.array([[1, 2, 3],
 75                  [4, 5, 6]])
 76    B = np.array([[7, 8],
 77                  [9, 10],
 78                  [11, 12]])
 79
 80    print("\nMatrix A (2x3):")
 81    print(A)
 82    print("\nMatrix B (3x2):")
 83    print(B)
 84
 85    C = A @ B  # Matrix multiplication
 86    print("\nC = A @ B (2x2):")
 87    print(C)
 88    print(f"Shape: {C.shape}")
 89
 90    # Transpose
 91    print("\n--- Transpose ---")
 92    print(f"A^T (3x2):\n{A.T}")
 93    print(f"(A^T)^T == A: {np.allclose((A.T).T, A)}")
 94
 95    # Inverse (square matrix)
 96    print("\n--- Matrix Inverse ---")
 97    D = np.array([[4, 7],
 98                  [2, 6]])
 99    print(f"Matrix D:\n{D}")
100
101    D_inv = np.linalg.inv(D)
102    print(f"\nD_inv:\n{D_inv}")
103
104    # Verify D @ D_inv = I
105    identity = D @ D_inv
106    print(f"\nD @ D_inv:\n{identity}")
107    print(f"Is identity: {np.allclose(identity, np.eye(2))}")
108
109    # Determinant (must be non-zero for invertible)
110    det_D = np.linalg.det(D)
111    print(f"\ndet(D) = {det_D:.4f}")
112    print(f"Invertible: {not np.isclose(det_D, 0)}")
113
114
115def rank_computation():
116    """Demonstrate rank computation and its significance"""
117    print("\n" + "=" * 60)
118    print("MATRIX RANK")
119    print("=" * 60)
120
121    # Full rank matrix
122    print("\n--- Full Rank Matrix ---")
123    A = np.array([[1, 2, 3],
124                  [0, 1, 4],
125                  [5, 6, 0]])
126    rank_A = np.linalg.matrix_rank(A)
127    print(f"Matrix A (3x3):\n{A}")
128    print(f"Rank(A) = {rank_A}")
129    print(f"Full rank: {rank_A == min(A.shape)}")
130
131    # Rank deficient matrix (linearly dependent rows)
132    print("\n--- Rank Deficient Matrix ---")
133    B = np.array([[1, 2, 3],
134                  [2, 4, 6],  # 2 * row1
135                  [4, 5, 6]])
136    rank_B = np.linalg.matrix_rank(B)
137    print(f"Matrix B (3x3):\n{B}")
138    print(f"Rank(B) = {rank_B}")
139    print(f"Full rank: {rank_B == min(B.shape)}")
140    print("Row 2 = 2 * Row 1, hence rank deficient")
141
142    # Rectangular matrix
143    print("\n--- Rectangular Matrix ---")
144    C = np.array([[1, 2, 3, 4],
145                  [5, 6, 7, 8],
146                  [9, 10, 11, 12]])
147    rank_C = np.linalg.matrix_rank(C)
148    print(f"Matrix C (3x4):\n{C}")
149    print(f"Rank(C) = {rank_C}")
150    print(f"Max possible rank = min(3, 4) = {min(C.shape)}")
151
152
153def ml_application_example():
154    """ML application: feature matrix and weight matrix multiplication"""
155    print("\n" + "=" * 60)
156    print("ML APPLICATION: LINEAR MODEL")
157    print("=" * 60)
158
159    # Feature matrix X: each row is a sample, each column is a feature
160    # 5 samples, 3 features
161    X = np.array([[1.0, 2.0, 3.0],
162                  [1.5, 2.5, 3.5],
163                  [2.0, 3.0, 4.0],
164                  [2.5, 3.5, 4.5],
165                  [3.0, 4.0, 5.0]])
166
167    # Weight matrix W: (3 features, 2 outputs)
168    W = np.array([[0.5, -0.3],
169                  [0.2, 0.8],
170                  [-0.1, 0.4]])
171
172    # Bias vector b: (2 outputs)
173    b = np.array([1.0, -0.5])
174
175    print(f"Feature matrix X (5 samples, 3 features):\n{X}")
176    print(f"\nWeight matrix W (3 features, 2 outputs):\n{W}")
177    print(f"\nBias vector b (2 outputs): {b}")
178
179    # Linear transformation: Y = X @ W + b
180    Y = X @ W + b
181    print(f"\nOutput Y = X @ W + b (5 samples, 2 outputs):\n{Y}")
182
183    print("\nInterpretation:")
184    print("- Each row of X is a feature vector for one sample")
185    print("- W maps 3D feature space to 2D output space")
186    print("- Each row of Y is the model output for one sample")
187
188    # Compute rank of feature matrix
189    rank_X = np.linalg.matrix_rank(X)
190    print(f"\nRank(X) = {rank_X}")
191    print(f"Max rank = min(5, 3) = {min(X.shape)}")
192
193    if rank_X < min(X.shape):
194        print("Warning: Feature matrix is rank deficient!")
195        print("Some features may be linearly dependent (redundant)")
196    else:
197        print("Feature matrix has full rank (good!)")
198
199
200def visualize_vector_operations():
201    """Visualize 2D vector operations"""
202    print("\n" + "=" * 60)
203    print("VISUALIZING VECTOR OPERATIONS")
204    print("=" * 60)
205
206    # Create figure
207    fig, axes = plt.subplots(1, 2, figsize=(12, 5))
208
209    # Plot 1: Vector addition
210    ax1 = axes[0]
211    v1 = np.array([2, 1])
212    v2 = np.array([1, 3])
213    v_sum = v1 + v2
214
215    origin = np.array([0, 0])
216    ax1.quiver(*origin, *v1, angles='xy', scale_units='xy', scale=1,
217               color='r', width=0.006, label='v1')
218    ax1.quiver(*origin, *v2, angles='xy', scale_units='xy', scale=1,
219               color='b', width=0.006, label='v2')
220    ax1.quiver(*origin, *v_sum, angles='xy', scale_units='xy', scale=1,
221               color='g', width=0.006, label='v1+v2')
222
223    # Parallelogram
224    ax1.plot([v1[0], v_sum[0]], [v1[1], v_sum[1]], 'k--', alpha=0.3)
225    ax1.plot([v2[0], v_sum[0]], [v2[1], v_sum[1]], 'k--', alpha=0.3)
226
227    ax1.set_xlim(-0.5, 4)
228    ax1.set_ylim(-0.5, 5)
229    ax1.set_aspect('equal')
230    ax1.grid(True, alpha=0.3)
231    ax1.legend()
232    ax1.set_title('Vector Addition')
233    ax1.set_xlabel('x')
234    ax1.set_ylabel('y')
235
236    # Plot 2: Linear transformation (matrix multiplication)
237    ax2 = axes[1]
238
239    # Transformation matrix (rotation + scaling)
240    theta = np.pi / 4  # 45 degrees
241    A = np.array([[np.cos(theta), -np.sin(theta)],
242                  [np.sin(theta), np.cos(theta)]]) * 1.5
243
244    # Original vectors
245    vectors = np.array([[1, 0], [0, 1], [1, 1]])
246
247    for i, v in enumerate(vectors):
248        v_transformed = A @ v
249
250        # Original vector
251        ax2.quiver(*origin, *v, angles='xy', scale_units='xy', scale=1,
252                   color='blue', width=0.005, alpha=0.5)
253
254        # Transformed vector
255        ax2.quiver(*origin, *v_transformed, angles='xy', scale_units='xy', scale=1,
256                   color='red', width=0.005, label='Transformed' if i == 0 else '')
257
258    ax2.set_xlim(-2, 2)
259    ax2.set_ylim(-2, 2)
260    ax2.set_aspect('equal')
261    ax2.grid(True, alpha=0.3)
262    ax2.legend(['Original (blue)', 'Transformed (red)'])
263    ax2.set_title('Linear Transformation (Rotation + Scale)')
264    ax2.set_xlabel('x')
265    ax2.set_ylabel('y')
266
267    plt.tight_layout()
268    plt.savefig('/opt/projects/01_Personal/03_Study/examples/Math_for_AI/vector_ops.png', dpi=150)
269    print("Visualization saved to vector_ops.png")
270    plt.close()
271
272
273if __name__ == "__main__":
274    # Run all demonstrations
275    vector_space_basics()
276    matrix_operations()
277    rank_computation()
278    ml_application_example()
279    visualize_vector_operations()
280
281    print("\n" + "=" * 60)
282    print("All demonstrations completed!")
283    print("=" * 60)