TensorFlow入门极简教程(五):Matrix

2019-03-05  本文已影响0人  Bobby0322

矩阵

矩阵的初始化

矩阵因为元素更多,所以初始化函数更多了。光靠tf.linspace,tf.range之类的线性生成函数已经不够用了。
可以通过先生成一个线性序列,然后再reshape成一个矩阵的方式来初始化。
例:

g1 = tf.linspace(1.0,10.0,16)
print(g1)

g2 = tf.constant(sess.run(tf.reshape(g1,[4,4])))
print(g2)

print(sess.run(g2))

Tensor("LinSpace:0", shape=(16,), dtype=float32)
Tensor("Const_4:0", shape=(4, 4), dtype=float32)
[[ 1. 1.6 2.2 2.8000002]
[ 3.4 4. 4.6000004 5.2000003]
[ 5.8 6.4 7. 7.6000004]
[ 8.200001 8.8 9.400001 10. ]]

tf.linspace生成了(16,)的一个向量,然后被reshape成(4,4)的矩阵。

生成全0值的矩阵

tf.zeros可以生成全0的矩阵,不指定类型时,默认为float32.

g7 = tf.zeros([4,5])
print(sess.run(g7))

[[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]]

可以指定数据类型:

g8 = tf.zeros([10,10],dtype=tf.int32)
print(sess.run(g8))

[[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]]

生成全1的矩阵

类似地,我们可以用tf.ones生成值全为1的矩阵。
例:

g9 = tf.ones([8,2],dtype=tf.int64)
print(sess.run(g9))

[[1 1]
[1 1]
[1 1]
[1 1]
[1 1]
[1 1]
[1 1]
[1 1]]

将矩阵全部设成一个值

tf.ones和tf.zeros其实是特例,tf.fill才是更通用的功能:

g10 = tf.fill([5,5],10.1)
print(sess.run(g10))

[[10.1 10.1 10.1 10.1 10.1]
[10.1 10.1 10.1 10.1 10.1]
[10.1 10.1 10.1 10.1 10.1]
[10.1 10.1 10.1 10.1 10.1]
[10.1 10.1 10.1 10.1 10.1]]

生成对角矩阵

矩阵一个特点是经常是只有稀疏的值。最常用的就是对角阵,只有一条对角线上有值。
例:

g11 = tf.diag([1, 1, 2, 2])
print(sess.run(g11))

[[1 0 0 0]
[0 1 0 0]
[0 0 2 0]
[0 0 0 2]]

除了生成对角阵,我们还可以从一个矩阵中将对角线值获取成一个向量:

g11 = tf.diag([1, 1, 2, 2])
g12 = tf.diag_part(g11)
print(sess.run(g12))
print(g12)

[1 1 2 2]
Tensor("DiagPart:0", shape=(4,), dtype=int32)

随机生成初始化值

除了全0,全1,全确定值和对角线值,还有一种非常常用的方式就是生成随机值。
我们可以按正态分布来生成初始值:

g13 = tf.random_normal([5, 5])
print(sess.run(g13))

[[ 0.25405225 0.44904745 -1.5468271 -0.835405 0.34003055]
[ 1.9063158 1.1063404 1.2292559 -0.83762854 -0.02943441]
[ 1.0375446 -1.0552472 -1.1881195 -0.3283966 0.812467 ]
[ 0.55426043 -0.4972653 0.6334804 0.262765 0.0152008 ]
[-1.7565544 -0.08327941 0.00738091 1.0632299 1.0563724 ]]

可以指定平均值和标准差,默认均值为0,标准差为1。默认的类型为float32,反正不支持整数。
例:

g14 = tf.random_normal([3,8], mean=1.0, stddev=2.0, dtype=tf.float32)
print(sess.run(g14))

[[ 0.8916285 2.2956815 3.2678025 0.8529626 0.60075164 -1.9739718
-0.01435184 0.9320197 ]
[-1.6734488 2.5063558 3.7253733 -0.50914896 3.712727 2.1626568
3.3386974 2.5216594 ]
[ 2.1141312 2.620947 1.0357903 -0.64942276 2.6657484 0.28470635
1.1828697 0.52249104]]

矩阵的转置

将矩阵中的元素基于对角线对称交换,叫做矩阵的转置transpose。

例:

g1 = tf.linspace(1.0,10.0,16)
g2 = tf.constant(sess.run(tf.reshape(g1,[4,4])))
g3 = tf.transpose(g2)
print(g3)
print(sess.run(g3))

Tensor("transpose:0", shape=(4, 4), dtype=float32)
[[ 1. 3.4 5.8 8.200001 ]
[ 1.6 4. 6.4 8.8 ]
[ 2.2 4.6000004 7. 9.400001 ]
[ 2.8000002 5.2000003 7.6000004 10. ]]

1,4,7,10是对角线,在转置时保持不变。

在非方阵的情况下,转置后对角线仍然保持不变。
我们看一个2*3矩阵的例子:

g4 = tf.linspace(1.0, 10.0, 6)
g5 = tf.reshape(g4,[2,3])
print(sess.run(g5))

[[ 1. 2.8 4.6 ]
[ 6.3999996 8.2 10. ]]

对角线是1和8.2.
我们转置一下:

[[ 1. 2.8 4.6 ]
[ 6.3999996 8.2 10. ]]
[[ 1. 6.3999996]
[ 2.8 8.2 ]
[ 4.6 10. ]]

虽然从一个宽矩阵变成了高矩阵,但是对角线仍然是1和8.2.

矩阵的数学运算

加减运算

两个行列相同的矩阵可以进行加减运算。
例:

h01 = tf.random_normal([4,4])
h02 = tf.fill([4,4],1.0)
h03 = h01 + h02
print(sess.run(h03))

[[ 1.336098 1.8155456 2.3138926 0.81175077]
[ 0.5926143 1.1805032 1.4293556 1.2853649 ]
[ 3.34655 2.0858011 2.020999 0.4845155 ]
[ 0.13710737 -0.1502235 0.58834183 2.3814282 ]]

广播运算

例:

h01 = tf.random_normal([4,4])
h02 = tf.fill([4,4],1.0)

h04 = h02 + 2.0
print(sess.run(h04))

[[1. 1. 1. 1.]
[1. 1. 1. 1.]
[1. 1. 1. 1.]
[1. 1. 1. 1.]]
[[3. 3. 3. 3.]
[3. 3. 3. 3.]
[3. 3. 3. 3.]
[3. 3. 3. 3.]]

矩阵乘积

“*”运算在矩阵乘法中,跟上节所讲一样,还是Hadamard积,就是对应元素的积,例:

h05 = tf.reshape(tf.linspace(1.0,10.0,16),[4,4])
print(sess.run(h05))
h06 = tf.reshape(tf.linspace(1.0,16.0,16),[4,4])
print(sess.run(h06))
print(sess.run(h05 * h06))

[[ 1. 1.6 2.2 2.8000002]
[ 3.4 4. 4.6000004 5.2000003]
[ 5.8 6.4 7. 7.6000004]
[ 8.200001 8.8 9.400001 10. ]]

[[ 1. 2. 3. 4.]
[ 5. 6. 7. 8.]
[ 9. 10. 11. 12.]
[13. 14. 15. 16.]]

[[ 1. 3.2 6.6000004 11.200001 ]
[ 17. 24. 32.200005 41.600002 ]
[ 52.2 64. 77. 91.200005 ]
[106.600006 123.200005 141.00002 160. ]]

我们也可以用matmul函数,或者”@”运算符计算矩阵相乘的结果:

h05 = tf.reshape(tf.linspace(1.0,10.0,16),[4,4])
h06 = tf.reshape(tf.linspace(1.0,16.0,16),[4,4])
print(h05 @ h06)
print(sess.run(h05 @ h06))

Tensor("matmul:0", shape=(4, 4), dtype=float32)

[[ 65.200005 72.8 80.40001 88. ]
[132.40001 149.6 166.80002 184. ]
[199.6 226.40002 253.20001 280. ]
[266.8 303.2 339.60004 376. ]]

“@”是高版本Python中支持的操作,在tensorflow中重载它的函数为matmul。

逆矩阵 Inverse Matrices

定义I为单位对角矩阵,如果BA=I,那么我就说B是A的逆矩阵。可以通过matrix_inverse函数来获得逆矩阵,例:

i01 = tf.diag([1.0,2.0,3.0,4.0])
print(sess.run(i01))

i01_rev = tf.matrix_inverse(i01)
print(sess.run(i01_rev))

[[1. 0. 0. 0.]
[0. 2. 0. 0.]
[0. 0. 3. 0.]
[0. 0. 0. 4.]]

[[1. 0. 0. 0. ]
[0. 0.5 0. 0. ]
[0. 0. 0.33333334 0. ]
[0. 0. 0. 0.25 ]]

我们来验算一下i01_rev与i01相乘是不是单位矩阵:

print(sess.run(i01_rev @ i01))

[[1. 0. 0. 0.]
[0. 1. 0. 0.]
[0. 0. 1. 0.]
[0. 0. 0. 1.]]

果然是。
对角阵比较特殊,还满足交换律:

print(sess.run(i01 @ i01_rev))

[[1. 0. 0. 0.]
[0. 1. 0. 0.]
[0. 0. 1. 0.]
[0. 0. 0. 1.]]

求行列式的值以判断是否有逆矩阵

我们学习线性代数知道,如果一个矩阵要想有逆矩阵,它的行列式一定不能为0。

在Matlab和mathematica两大著名数学软件中,求行列式的函数名字很简单,就是det。
Tensorflow因为是个库,所以名字比较长,叫tf.matrix_determinant.

我们来看一个例子:

A1 = [[1,1,1],[1,-1,-1],[5,-2,2]]
A = tf.constant(A1, tf.float32)
print(A)
print(sess.run(A))

d = tf.matrix_determinant(A)
print(sess.run(d))

Tensor("Const_4:0", shape=(3, 3), dtype=float32)

[[ 1. 1. 1.]
[ 1. -1. -1.]
[ 5. -2. 2.]]

-8.0

利用逆矩阵求解线性方程组

假设有下列方程组,求解:

x+y+z =1,
x-y-z = 2,
5x-2y+2z = 3

这个题中的系数矩阵就是我们刚才例子中的矩阵,我们已经求得行列式值为-8不等于0,所以我们可以通过用系数矩阵的逆矩阵乘以常数向量的方式求解。

A1 = [[1,1,1],[1,-1,-1],[5,-2,2]]
A = tf.constant(A1, tf.float32)
b = tf.constant([[1],[2],[3]],dtype=tf.float32)
print(b)
print(sess.run(b))

print(sess.run(tf.matmul(tf.matrix_inverse(A),b)))

Tensor("Const_5:0", shape=(3, 1), dtype=float32)

[[1.]
[2.]
[3.]]

[[ 1.5000001]
[ 0.875 ]
[-1.3750001]]

最后求得,x=1.5, y=0.875, z = -1.375.

上一篇下一篇

猜你喜欢

热点阅读