转载地址:
https://bbs.huaweicloud.com/forum/thread-66135-1-1.html
作者:Yesterday
最近开始学习mindspore,发现Mindspore对于一位向量的定义是非常不明确的,导致后续操作非常不方便,所以关于这方面我提一下建议,希望Mindspore的开发部门可以注意一下:
一维向量的默认是行向量还是列向量,在不同的软件库中定义是不同的,然而在Mindspore中,情况却非常奇怪:
-
Tensor类型如果是一维,在矩阵乘法【P.MatMul()】中既不是行向量也不是列向量,无法直接参与矩阵乘法,必须显式地声明为(N,1)维【列向量】或者(1,N)维【行向量】才能进行乘法运算。但是矩阵加法中一维向量默认是行向量,可以按行向量进行加法运算。此外transpose函数也无法直接作用于一维向量,不能用transpose函数在行向量和列向量之间进行转换
-
W
=
Tensor(np.random.randn(
3
,
3
),mindspore.float32)
x
=
Tensor(np.arange(
1
,
4
)),mindspore.float32)
xr
=
Tensor(np.arange(
1
,
4
).reshape((
1
,
3
)),mindspore.float32)
# 行向量
xc
=
Tensor(np.arange(
1
,
4
).reshape((
3
,
1
)),mindspore.float32)
# 列向量
mm
=
P.MatMul()
mm(xr,W)
# 可执行
mm(W,xc)
# 可执行
# mm(W,x) 报错
# mm(x,W) 报错
b
=
Tensor(np.random.randn(
3
),mindspore.float32)
br
=
Tensor(np.random.randn(
1
,
3
),mindspore.float32)
bc
=
Tensor(np.random.randn(
3
,
1
),mindspore.float32)
x
+
b
# (3)维向量
x
+
br
# (1,3)维向量
x
+
bc
# (3,3)维矩阵,广播机制
xr
+
b
# (1,3)维向量
xr
+
br
# (1,3)维向量
xr
+
bc
# (3,3)维矩阵,广播机制
xc
+
b
# (3,3)维矩阵,广播机制
xc
+
br
# (3,3)维矩阵,广播机制
xc
+
bc
# (3,1)维向量
T
=
P.Transpose()
# T(x,(1,0)) 报错
T(xr,(
1
,
0
))
# 可执行,得(3,1)维向量
T(xc,(
1
,
0
))
# 可执行,得(1,3)维向量
-
如果从二维的矩阵中提取单独一行或者单独一列,提取之后都会变成一维向量,无法进行矩阵乘法运算,而加法运算中无论提取的是行是列都会按行向量进行计算。提取的时候必须用P.Reshape()转换为行向量((1,N)维)或列向量((N,1)维)才能保持
-
从二维的矩阵中提取出单独的每一行行或每一列之后,如果想要将其用concat再组装回去,也必须先将每一行或者每一列转化为(1,N)维或 (N,1)维才能使用concat函数
-
a
=
Tensor(np.arange(
1
,
13
).reshape((
3
,
4
),order
=
'F'
),mindspore.float32)
-
[[ 1. 4. 7. 10.]
[ 2. 5. 8. 11.]
[ 3. 6. 9. 12.]]
-
va
=
[]
reshape
=
P.Reshape()
# 按列读取,对每一列进行单独的操作
for
i
in
range
(
4
):
# 这里如果不用reshape,aa就会变成(3)维向量,a[i,:]则是(4)维向量
aa
=
reshape(a[:,i],(
3
,
1
))
aa
*
=
i
+
1
va.append(aa)
# 将处理后的每一列拼接会原来维度的矩阵
concat
=
P.Concat(axis
=
1
)
concat(
tuple
(va))
# 前面如果不reshape这里会报错
-
[[ 1. 8. 21. 40.]
[ 2. 10. 24. 44.]
[ 3. 12. 27. 48.]]
综上所述,Mindspore中一维向量的不明确导致后续操作非常麻烦。其他的库一般都有明确定义,例如我之前一直使用的DyNet(C++版)中所有一维向量默认是列向量,(N)维和(N,1)维的定义是完全等价的,这样从(N,M)维的矩阵中如果抽出某一行就是(1,M)维,抽出某一列就是(N,1)维【等价于(N)维】。提取出行或列之后,可以直接用concatenate函数拼接回原来的二维矩阵。更重要的是,一维向量可以直接参与二维矩阵的运算,也可以用transpose函数在行和列之间进行切换,这样时候起来会方便很多。
所以建议Mindspore明确一下一维向量的定义,并且和高维Tensor兼容,这样一维向量不需要reshape就可以直接参与矩阵运算。最好设置一个默认值,但是在声明的时候定义的时候可以按照自己的需求设定是行向量还是列向量。而且如果直接用M[:,i]或着M[i,:]提取矩阵的某一行或列的话,也会使维度降到一维,这样也是很不方便,当然为了兼容Python这一点我也不是不能理解,但是我觉得可以另外设置一个算子(比如DyNet里面有select_rows和select_cols函数),从矩阵中提取行或者列的时候保持形状不变。