Ex1:利用列表推导式写矩阵乘法
一般的矩阵乘法根据公式,可以由三重循环写出。请将其改写为列表推导式的形式。
答案:
# 作业
M1 = np.random.rand(2,3)
M2 = np.random.rand(3,4)
res = np.empty((M1.shape[0],M2.shape[1]))
for i in range(M1.shape[0]):
for j in range(M2.shape[1]):
item = 0
for k in range(M1.shape[1]):
item += M1[i][k] * M2[k][j]
res[i][j] = item
(abs(M1@M2 - res) < 1e-15).all() # 排除数值误差
print(res)
# 方法1:三层遍历
res1 = [[sum([M1[i][k] * M2[k][j] for k in range(M1.shape[1])]) for j in range(M2.shape[1])] for i in range(M1.shape[0])]
print(res1)
# 方法2:双层遍历
res2 = np.array([[np.sum(row*col) for col in M2.T ] for row in M1 ])
print(res2)
Ex2:更新矩阵
答案:
A= np.arange(1,10).reshape(3,3)
# (1/A).sum(1).reshape(-1,1) 先计算出矩阵A每行的和,再点成
B = A*(1/A).sum(1).reshape(-1,1)
B
Ex3:卡方统计量
答案:
np.random.seed(0)
A = np.random.randint(10, 20, (8, 5))
print(A)
B = (A.sum(axis=0)*A.sum(axis=1).reshape(-1,1))/A.sum()
print(B)
((A-B)**2/B).sum()
Ex4:改进矩阵计算的性能
答案:
np.random.seed(0)
m, n, p = 100, 80, 50
B = np.random.randint(0, 2, (m, p))
U = np.random.randint(0, 2, (p, n))
Z = np.random.randint(0, 2, (m, n))
def solution(B=B, U=U, Z=Z):
L_res = []
for i in range(m):
for j in range(n):
norm_value = ((B[i]-U[:,j])**2).sum()
L_res.append(norm_value*Z[i][j])
return sum(L_res)
print(f'改进前结果:{solution(B, U, Z)}')
%timeit -n 30 solution(B, U, Z)
print(f'改进后结果:{(((B**2).sum(1).reshape(-1,1) + (U**2).sum(0) - 2*B@U)*Z).sum()}')
%timeit -n 30 (((B**2).sum(1).reshape(-1,1) + (U**2).sum(0) - 2*B@U)*Z).sum()
Ex5:连续整数的最大长度
输入一个整数的 Numpy 数组,返回其中严格递增连续整数子数组的最大长度。例如,输入 [1,2,5,6,7],[5,6,7]为具有最大长度的递增连续整数子数组,因此输出3;输入[3,2,1,2,3,4,6],[1,2,3,4]为具有最大长度的递增连续整数子数组,因此输出4。请充分利用 Numpy 的内置函数完成。(提示:考虑使用 nonzero, diff 函数)
答案:
f = lambda x:np.diff(np.nonzero(np.r_[1,np.diff(x)!=1,1])).max()
print(f'案列1:{f([1,4,5,6,2,7])}')
print(f'案列1:{f([7,5,6,7,8,7,2,4,5,6,7,9])}')