Python Numpy和矩阵的相关面试问题
通常,数据科学家被要求在Python中执行简单的矩阵运算,这应该很简单,但许多人会偏离正轨。
本文将介绍面试中经常出现的4个Numpy/matrix问题,并用Python编写代码。
问题1:
给定4x4 Numpy矩阵,如何反转矩阵?
#?步骤0:构造一个4*4?Numpy矩阵
import?numpy?as?np
matrix?=?np.arange(1,17).reshape(4,4)
print(matrix)
[[?1??2??3??4]
?[?5??6??7??8]
?[?9?10?11?12]
?[13?14?15?16]]
旁注,np.arange(1,17) 返回一个Numpy数组,并*reshape(4,4)生成一个44矩阵。
#?步骤1:展平numpy数组
matrix_flat?=?matrix.flatten()
matrix_flat
array([?1,??2,??3,??4,??5,??6,??7,??8,??9,?10,?11,?12,?13,?14,?15,?16])
有两种方法可以根据数据类型展平矩阵。对于Numpy数组,我们使用np.array.flatten() ;对于非数组矩阵,我们用matrix.ravel(). 请试一试。
#?步骤2:将元素读入一个新的矩阵
matrix_reversed?=?matrix_flat[::-1]
matrix_reversed
array([16,?15,?14,?13,?12,?11,?10,??9,??8,??7,??6,??5,??4,??3,??2,??1])
展平后,我们从最后一个元素开始向后读取矩阵。
#?步骤3:?将矩阵重塑为4*4矩阵
matrix_reversed.reshape(4,4)
最后,我们重塑矩阵并将其转换回4*4矩阵,如下所示:
array([[16,?15,?14,?13],
???????[12,?11,?10,??9],
???????[?8,??7,??6,??5],
???????[?4,??3,??2,??1]])
Numpy数组或矩阵的独特属性是,必须在反转它之前将其展平,并且有两种方法取决于数据格式(是否为Numpy)。
问题2:
两个矩阵如何相乘?
这类问题可能很棘手!
两个矩阵?是不是numpy?
解决方案在很大程度上取决于它所引用的数据类型。总的来说,有两种解决方案:用于Numpy数组的dot方法和用于非数组的循环方法。
解决方案1:Numpy数组
#?步骤1:?Numpy数组
A?=?np.arange(9).reshape(3,3)
B?=?np.arange(10,19).reshape(3,3)
A
B
#?A
array([[0,?1,?2],
???????[3,?4,?5],
???????[6,?7,?8]])
???????
#?B
array([[10,?11,?12],
???????[13,?14,?15],
???????[16,?17,?18]])
???????
#?步骤2:?dot?方法?
result?=?A.dot(B)
print(result)
[[?45??48??51]
?[162?174?186]
?[279?300?321]]
dot方法很容易解决Numpy数组的乘法问题,但我怀疑面试问题不会这么容易。
所以,对非数组做乘法题的可能性更大。
解决方案2:非数组
#?步骤0:构造两个矩阵。
X?=?[
????[1,2,3],
????[2,3,4,],
????[4,3,2]
]
Y?=?[
????[2,3,4],
????[3,4,6],
????[2,3,5]
]
Python没有matrix的内置数据类型,我们使用列表的列表(嵌套列表)。
#?步骤1:创建一个零矩阵来存储结果
Z?=?[
????[0,0,0],
????[0,0,0],
????[0,0,0]
]
创建空矩阵的原因是将乘法结果存储在下面的嵌套for循环中。
#?步骤2:嵌套for循环
#?在X的行上迭代;?len(X)返回行数
for?i?in?range(len(X)):
?????
????#?在Y的列上迭代;?len(Y[0])返回列数
????for?j?in?range(len(Y[0])):
????????
????????#?迭代Y的行
????????for?k?in?range(len(Y)):
????????????
????????????Z[i][j]?+=?X[i][k]*Y[k][j]
????????
Z
[[14,?20,?31],?[21,?30,?46],?[21,?30,?44]]
让我们解开嵌套for循环:
- for i in range(len(X)):返回行数;
- for j in range(len(Y[0])):返回Y的列数。旁注:我们使用Y[0]访问矩阵列,使用Y访问矩阵行;
- for k in range(len(Y)):迭代Y的行;
- Z[i][j]+=X[i][k]*Y[k][j]:按元素乘法的和填充Z中的值。
回想一下,两个矩阵的序列相乘:X的第一行中的元素与Y的第一列中的元素相乘再相加。重复这个过程直到结束。
上面的嵌套循环简单地遵循与我们通常所做的相同的计算矩阵乘法的过程。
问题3:
如何转置矩阵?
同样,有多种解决方案取决于是否允许你使用Numpy。
解决方案1:嵌套for循环(不要使用Numpy)
#?步骤0:创建矩阵
X?=?[
????[12,7],
????[1,2],
????[3,4]
]
#?步骤1:空列表
transpose?=?[
????[0,0,0],
????[0,0,0]
]
#步骤2:嵌套for循环
#?行上迭代
for?i?in?range(len(X)):
????
????#?列上迭代:?#?len(transpose)?=?len(X[0])
????for?j?in?range(len(transpose)):?
????????
????????#?替换
????????transpose[j][i]?=?X[i][j]
????????
for?r?in?transpose:?
????print(r)
[12,?1,?3]
[7,?2,?4]
解决方案2:对元组列表使用zip(不要使用Numpy)
#?步骤1:创建元组列表
matrix?=?[(1,2,3),(4,5,6),(7,8,9),(10,11,12)]#?元组列表
matrix
[(1,?2,?3),?(4,?5,?6),?(7,?8,?9),?(10,?11,?12)]
我们使用一个元组列表来创建一个矩阵。
#第二步:解压和压缩成一行
#?通过*解压
#?通过zip压缩
matrix_transpose?=?zip(*matrix)
for?i?in?matrix_transpose:
????print(i)
(1,?4,?7,?10)
(2,?5,?8,?11)
(3,?6,?9,?12)
解决方案3:使用Numpy数组
3.1 np.transpose()
X?=?[
????[12,7],
????[1,2],
????[3,4]
]
#?3.1?np.transpose()
import?numpy?as?np
transpose?=?np.transpose(X)
print(transpose)
如果我们能使用Numpy,一行就可以完成任务。
3.2 np.array.T
matrix_array?=?np.array(X)
matrix_array.T
array([[12,??1,??3],
???????[?7,??2,??4]])
或者,我们可以将矩阵(list)更改为Numpy数组并使用array.T。
问题4:
如何将两个Numpy矩阵相加?
同样,有两种解决方案取决于我们是否可以使用Numpy。
解决方案1:np.array()
X?=?[[12,7,3],
????[4?,5,6],
????[7?,8,9]]
Y?=?[[5,8,1],
????[6,7,3],
????[4,5,9]]
????
import?numpy?as?np?
X_np?=?np.array(X)
Y_np?=?np.array(Y)
result?=?X_np?+?Y_np
print(result)
[[17?15?4]
[10?12?9]
[11?13?18]]
Numpy可以轻松地处理元素添加。
解决方案2:普通矩阵的嵌套for循环
result?=?np.zeros((3,3))
#?行的迭代
for?i?in?range(len(X)):
????#?列的迭代
????for?j?in?range(len(X[0])):
????????result[i][j]?=?X[i][j]+Y[i][j]
????????
for?r?in?result:?
????print(r)
[17.?15.??4.]
[10.?12.??9.]
[11.?13.?18.]
代码是不言而喻的,我们已经在上面的问题中涵盖了它们。
另一方面,这个问题有两种不同的说法。
4.1如何垂直堆叠矩阵?
X?=?[[12,7,3],
????[4?,5,6],
????[7?,8,9]]
Y?=?[[5,8,1],
????[6,7,3],
????[4,5,9]]
np.vstack((X,Y))
array([[12,??7,??3],
???????[?4,??5,??6],
???????[?7,??8,??9],
???????[?5,??8,??1],
???????[?6,??7,??3],
???????[?4,??5,??9]])
4.2如何水平堆叠矩阵?
#?水平堆叠
X?=?[[12,7,3],
????[4?,5,6],
????[7?,8,9]]
Y?=?[[5,8,1],
????[6,7,3],
????[4,5,9]]
np.hstack((X,Y))
array([[12,??7,??3,??5,??8,??1],
???????[?4,??5,??6,??6,??7,??3],
???????[?7,??8,??9,??4,??5,??9]])
请参阅Github以获取完整的Python代码:https://github.com/LeihuaYe/Matrix_in_Python
备注
- 在面试过程中保持良好的沟通。
- 询问澄清问题和限制条件。例如: 能用Numpy数组吗?
- 在试图反转矩阵之前先将其展平。
- 嵌套for循环很有用。试着理解每一行是如何工作的。