三、练习

Ex1:利用列表推导式写矩阵乘法

一般的矩阵乘法根据公式,可以由三重循环写出:

In [140]: M1 = np.random.rand(2,3)
In [141]: M2 = np.random.rand(3,4)
In [142]: res = np.empty((M1.shape[0],M2.shape[1]))
In [143]: 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
   .....: 
In [144]: (np.abs((M1@M2 - res) < 1e-15)).all() # 排除数值误差
Out[144]: True

请将其改写为列表推导式的形式。

Ex2:更新矩阵

设矩阵 (A_{m\times n}) ,现在对 (A) 中的每一个元素进行更新生成矩阵 (B) ,更新方法是 (\displaystyle B_{ij}=A_{ij}\sum_{k=1}^n\frac{1}{A_{ik}}) ,例如下面的矩阵为 (A) ,则 (B_{2,2}=5\times(\frac{1}{4}+\frac{1}{5}+\frac{1}{6})=\frac{37}{12}) ,请利用 Numpy 高效实现。

[\begin{split}A=\left[ \begin{matrix} 1 & 2 &3\4&5&6\7&8&9 \end{matrix} \right]\end{split}]

Ex3:卡方统计量

设矩阵 (A_{m\times n}) ,记 (B_{ij} = \frac{(\sum_{i=1}^mA_{ij})\times (\sum_{j=1}^nA_{ij})}{\sum_{i=1}^m\sum_{j=1}^nA_{ij}}) ,定义卡方值如下:

[\chi^2 = \sum_{i=1}^m\sum_{j=1}^n\frac{(A_{ij}-B_{ij})^2}{B_{ij}}]

请利用 Numpy 对给定的矩阵 (A) 计算 (\chi^2)

In [145]: np.random.seed(0)
In [146]: A = np.random.randint(10, 20, (8, 5))

Ex4:改进矩阵计算的性能

(Z)(m\times n) 的矩阵, (B)(U) 分别是 (m\times p)(p\times n) 的矩阵, (B_i)(B) 的第 (i) 行, (U_j)(U) 的第 (j) 列,下面定义 (\displaystyle R=\sum_{i=1}^m\sum_{j=1}^n|B_i-U_j|2^2Z{ij}) ,其中 (|\mathbf{a}|_2^2) 表示向量 (\mathbf{a}) 的分量平方和 (\sum_i a_i^2)

现有某人根据如下给定的样例数据计算 (R) 的值,请充分利用 Numpy 中的函数,基于此问题改进这段代码的性能。

In [147]: np.random.seed(0)
In [148]: m, n, p = 100, 80, 50
In [149]: B = np.random.randint(0, 2, (m, p))
In [150]: U = np.random.randint(0, 2, (p, n))
In [151]: Z = np.random.randint(0, 2, (m, n))
In [152]: 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)
   .....: 
In [153]: solution(B, U, Z)
Out[153]: 100566

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 函数)