ML03
ML03
多特征
- Fw,b(x)=w1x1+w2x2+…+wnxn+b
向量化
f = np.dot(w,x) + b(可以理解为点向量,这里使用的是python中的numpy库,可以调用计算机并行硬件计算,代码简洁,运行速度快)
向量化参数运算,能够更高效的实现机器学习的运行效率
代码示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120import numpy as np
import time
import sys
# 定义一个辅助函数来测量代码执行时间并打印结果
def measure_performance(func, *args, method_name=""):
start_time = time.perf_counter()
result = func(*args)
end_time = time.perf_counter()
duration = (end_time - start_time) * 1000 # 转换为毫秒
# 注意:sys.getsizeof() 测量的是 Python 对象本身的内存大小,
# 对于 NumPy 数组,它不包含底层实际存储数据所占用的内存。
# NumPy 的核心优势在于其底层数据存储和运算的高度优化(通常由 C/Fortran 实现)。
result_memory_mb = sys.getsizeof(result) / (1024 * 1024)
print(f"--- 方法: {method_name} ---")
print(f"时间消耗: {duration:.4f} 毫秒")
print(f"结果对象大小 (Python层): {result_memory_mb:.4f} MB")
print("(请注意:NumPy 数组的实际数据存储在底层,通常更高效且不计入此处的 Python 对象大小。)")
return result
print("我们将通过经典的向量和矩阵运算示例,对比普通 Python 方法和 NumPy dot 函数的性能差异(主要是时间)。")
# 修正了之前的语法错误,确保字符串在单行内正确闭合
print("NumPy 库的底层是高度优化的 C/Fortran 代码,所以在内存使用和计算速度上通常远优于纯 Python 实现。\n")
# --- 示例 1: 两个向量的点积 (Vector Dot Product) ---
print("--- 示例 1: 两个向量的点积 ---")
N_vec = 5000 # 向量维度
vec_a = np.random.rand(N_vec)
vec_b = np.random.rand(N_vec)
# 普通 Python 方法计算点积
def normal_dot_product(v1, v2):
return sum(v1[i] * v2[i] for i in range(len(v1)))
# 将 NumPy 数组转换为列表,以模拟纯 Python 操作的开销
list_a = vec_a.tolist()
list_b = vec_b.tolist()
result_normal_vec = measure_performance(normal_dot_product, list_a, list_b, method_name="纯 Python 循环计算向量点积")
# NumPy dot 函数计算点积
result_numpy_vec = measure_performance(np.dot, vec_a, vec_b, method_name="NumPy dot 函数计算向量点积")
print(f"两个结果是否接近: {np.isclose(result_normal_vec, result_numpy_vec)}\n")
# --- 示例 2: 矩阵与向量相乘 (Matrix-Vector Multiplication) ---
print("--- 示例 2: 矩阵与向量相乘 ---")
N_mat_row = 1000 # 矩阵行数
N_mat_col = 500 # 矩阵列数 (也为向量维度)
matrix = np.random.rand(N_mat_row, N_mat_col)
vector = np.random.rand(N_mat_col)
# 普通 Python 方法计算矩阵与向量相乘
def normal_mat_vec_multiply(mat, vec):
rows = len(mat)
cols = len(mat[0])
result = [0] * rows
for i in range(rows):
for j in range(cols):
result[i] += mat[i][j] * vec[j]
return result
# 将 NumPy 数组转换为列表的列表,以模拟纯 Python 操作的开销
list_matrix = matrix.tolist()
list_vector = vector.tolist()
result_normal_mat_vec = measure_performance(normal_mat_vec_multiply, list_matrix, list_vector, method_name="纯 Python 循环计算矩阵-向量乘法")
# NumPy dot 函数计算矩阵与向量相乘
result_numpy_mat_vec = measure_performance(np.dot, matrix, vector, method_name="NumPy dot 函数计算矩阵-向量乘法")
print(f"两个结果是否接近: {np.allclose(result_normal_mat_vec, result_numpy_mat_vec)}\n")
# --- 示例 3: 两个矩阵相乘 (Matrix-Matrix Multiplication) ---
print("--- 示例 3: 两个矩阵相乘 ---")
N_mat1_row = 500
N_common = 300
N_mat2_col = 400
mat_A = np.random.rand(N_mat1_row, N_common)
mat_B = np.random.rand(N_common, N_mat2_col)
# 普通 Python 方法计算矩阵相乘
def normal_mat_mat_multiply(mat1, mat2):
rows_a = len(mat1)
cols_a = len(mat1[0])
rows_b = len(mat2)
cols_b = len(mat2[0])
if cols_a != rows_b:
raise ValueError("矩阵维度不匹配,无法相乘")
result = [[0 for _ in range(cols_b)] for _ in range(rows_a)]
for i in range(rows_a):
for j in range(cols_b):
for k in range(cols_a): # 或者 rows_b
result[i][j] += mat1[i][k] * mat2[k][j]
return result
# 将 NumPy 数组转换为列表的列表
list_mat_A = mat_A.tolist()
list_mat_B = mat_B.tolist()
result_normal_mat_mat = measure_performance(normal_mat_mat_multiply, list_mat_A, list_mat_B, method_name="纯 Python 循环计算矩阵乘法")
# NumPy dot 函数计算矩阵相乘
result_numpy_mat_mat = measure_performance(np.dot, mat_A, mat_B, method_name="NumPy dot 函数计算矩阵乘法")
# 将 NumPy 结果转换为列表进行比较
print(f"两个结果是否接近: {np.allclose(result_normal_mat_mat, result_numpy_mat_mat)}\n")
print("总结:从上述示例可以看出,NumPy 的 dot 函数在处理大型多参数向量和矩阵运算时,相比纯 Python 循环具有压倒性的性能优势(尤其体现在时间消耗上)。")
print("这是因为它底层使用了高度优化的 C/Fortran 库(如 BLAS),能够高效地处理连续内存块和并行计算。")
print("在实际的机器学习和科学计算中,强烈建议使用 NumPy 等库提供的优化函数,而不是手写循环。")
输出结果:
1 | 我们将通过经典的向量和矩阵运算示例,对比普通 Python 方法和 NumPy dot 函数的性能差异(主要是时间)。 |
多重线性回归的梯度下降
1 | import numpy as np |
1 | 特征矩阵 X 的形状: (100, 3) |