2.2矩阵计算回顾
有很多的标准的数学运算在机器学习程序里反复使用。我们只介绍一些最为基础的运算。矩阵转置是在矩阵对解线上翻转矩阵的最方便的操作。假如A是矩阵,则转置矩阵AT 的定义为 AijT = Aji。例如,旋转矩阵Rα的转置为
矩阵加只针对有相同形状的矩阵且只是简单的进行元素级的运算。例如:
相似的,矩阵可以被标量乘。这种情况,矩阵里的每一个元素被标量乘。
有时候,可以直接进行两个矩阵的乘。矩阵乘可能是矩阵相关的概念里最重要的一个。特别要注意矩阵乘不是矩阵元素级的乘!相反,假如我们有形状为 (m, n)的矩阵,有 m行和n列。则A可以在右边被形状为 (n, k)矩阵B乘 (其中 k是正整数)从而得到形状为(m, k)的矩阵 AB。对于实际的数学描述,AB的定义为
我们简单的展示一下前面的矩阵乘。因为我们有了正式的定义,现在扩展一下这个例子:
它的基础就是一个矩阵的行与另一个矩阵的列相乘。这个定义隐藏了很多细节。首先要注意矩阵乘是不可交换的。即, 通常AB ≠ BA 。实际上, AB可能存在而 BA没有意义。例如,假如 A 是形状 (2, 3)的矩阵且 B是形状 (3, 4)的矩阵。则AB 是形状 (2, 4)矩阵。但是,BA没有定义,因为相关的维(4和2)并不匹配。另一个细节,形状(m, n)的矩阵可以在右边被形状为(n, 1)的矩阵乘。但是形状为(n, 1)的矩阵只是列向量。所以,矩阵被向量乘是有意义的。矩阵-向量乘是常见机器学习系统的基础构件。标准乘的最佳特征是线性操作。具体的,如果f(x + y)= f x + f y 且 f(cx) = c f x,其中c是标量,则称f是线性的。
要证明标量乘是线性的,假如 a,b, c, d 为实数。我们有
我们应用乘法的交换律和分配律。现在假如 A, C, D为矩阵,其中C, D有相同的size,在A 的右边乘C 或D是有意义的 (b 仍是个实数)。则矩阵乘是线性运算:
换句话,矩阵与标量乘是可交换和可分配的。
事实上,可以证明,向量的任何线性变换都可以用矩阵乘来表示。
2.3TensorFlow基础计算
我们在前面定义了不同的张量。如果我们不能对Tensors进行运算,那么它们就不会很有用。TensorFlow支持大量的tensor运算。现在讲一下如何用TensorFlow创建并操作张量。我们在这里只提一些最常用的运算作为示例。最常用的运算可以分为两类:单目和双目运算。单目运算以一个tensor作为输入并返回新的tensor,而双目运算取两个tensor作为输入并返回新的tensor。
我推荐你使用IPython。直接实验后,许多的TensorFlow概念都极为容易理解。
2.3.1安装TensorFlow并开始
在继续本节之前,你需要在你的机器里安装TensorFlow。安装的过程参见https://www.docin.com/p-4295595957.html。尽管TensorFlow的前端有多种编程语言,这里我们仅限于TensorFlow Python API。 我推荐你安装Anaconda Python, 它包含许多数学库。
Example 2-1. Initialize an interactive TensorFlow session
>>> import tensorflow as tf
2.3.2初始化常数张量
创建Scalar (rank-0 tensor)
Scalar是一个tensor,它的shape是一个空的数组([])。它没有轴(axes)而且只含一个值。你可以用tf.convert_to_tensor()函数创建一个新的Scalar。
import tensorflow as tf
m0 = 2
t0 = tf.convert_to_tensor(m0, dtype=tf.float32)
t0
<tf.Tensor: shape=(), dtype=float32, numpy=2.0>
创建1d tensor (rank-1 tensor)
1D tensor有时也称为rank-1 tensor或vector。1D tensor有一个轴,它的shape是长度为1的数组。下面的代码创建一个vector:
import tensorflow as tf
m1 = [1.0, 2.0,7.0,5.0]
t1 = tf.convert_to_tensor(m1, dtype=tf.float32)
t1
<tf.Tensor: shape=(4,), dtype=float32, numpy=array([1., 2., 7., 5.], dtype=float32)>
这个1D tensor有4个元素可以称为4-dimensional vector。不要将4D vector 与 4D tensor相混淆了!4D vector 是1D tensor,它有一个轴,含4个元素;而4D tensor有4个轴(在每一个轴上可以有许多的维dimensions)。Dimensionality可以指沿特定轴的元素的个数或者指一个tensor的轴的数量(例如,一个4D tensor),这经常被混淆。从技术角度讲,使用rank-4 tensor更准确更清楚,但是4D tensor这种含糊的写法通常是不计较的。大部分情况下,这不是问题,因为可以根据上下文来确定。
创建2d tensor (rank-2 tensor)
2D tensor有两个轴。有时候2D tensor也指matrix,且它的两个轴可以分别被解释为矩阵的行索引和列索引。你可以可视化的将矩阵解释为方形的元素网格。
import tensorflow as tf
m2 = [[1.0, 2.0],
[3.0, 4.0]]
t2 = tf.convert_to_tensor(m2, dtype=tf.float32)
t2
<tf.Tensor: shape=(2, 2), dtype=float32, numpy=
array([[1., 2.],
[3., 4.]], dtype=float32)>
第一轴的输入称为行,第二轴的输入称为列。上面的例子中,有1行,20列。
创建Rank-3和更高维的 tensors
如果你将多个2D tensors放在数组里,你就会得到一个3D tensor,你可以把它想像为元素组成的立方体。
import tensorflow as tf
m3 =[[[1.0, 2.0],[3.0, 4.0]], [[2.0, 3.0], [4.0, 5.0]], [[3.0, 4.0], [5.0, 6.0]]]
t3 = tf.convert_to_tensor(m3, dtype=tf.float32)
t3
<tf.Tensor: shape=(3, 2, 2), dtype=float32, numpy=
array([[[1., 2.],[3., 4.]],[[2., 3.], [4., 5.]], [[3., 4.], [5., 6.]]], dtype=float32)>
m4 =[[ [[1.0, 2.0],[3.0, 4.0]], [[2.0, 3.0], [4.0, 5.0]], [[3.0, 4.0], [5.0, 6.0]]],
[ [[1.0, 2.0],[3.0, 4.0]], [[2.0, 3.0], [4.0, 5.0]], [[3.0, 4.0], [5.0, 6.0]]]]
t4 = tf.convert_to_tensor(m4, dtype=tf.float32)
t4
<tf.Tensor: shape=(2, 3, 2, 2), dtype=float32, numpy=
array([[[[1., 2.],[3., 4.]], [[2., 3.], [4., 5.]], [[3., 4.], [5., 6.]]], [[[1., 2.], [3., 4.]],
[[2., 3.],[4., 5.]],[[3., 4.],[5., 6.]]]], dtype=float32)>
创建全0和全1tensors
到现在我们将张量作为抽像的数学实体计论。但是 TensorFlow必须运行于真实的计算机里,所以任保张量必须在计算机的内存里以便给计算机的程序员使用。TensorFlow了很多的函数以实例化内存里的张量。最简单的是tf.zeros()和tf.ones()函数。
通常希望创建一定形状的全0的tensor。你可以用tf.zeros()函数来实现。要调用这个函数,提供希望的shape作为输入参数。
tf.zeros() 取张量的形状作为参数并返回这个形状的张量,用零填充。我们在shell里调用这个命令 (Example 2-2).
Example 2-2. Create a zeros tensor
>>> tf.zeros(2)
<tf.Tensor: shape=(2,), dtype=float32, numpy=array([0., 0.], dtype=float32)>
我们可以调用l tf.zeros()和 tf.ones() 以创建和显示不同尺寸sizes的张量。(Example 2-3).
Example 2-3. Evaluate and display tensors
>>> a = tf.zeros((2, 3))
>>> a
<tf.Tensor: shape=(2, 3), dtype=float32, numpy=
array([[0., 0., 0.],
[0., 0., 0.]], dtype=float32)>
>>>my_tensor = tf.zeros([2, 3, 3])
>>>tf.print(my_tensor)
[[[0 0 0] [0 0 0] [0 0 0]]
[[0 0 0] [0 0 0] [0 0 0]]]
这个tensor有黙认的dtype (float32)。要创建其它dtypes的全0 tensor,指明dtype作为tf.zeros()的第二个参数。
一个相关的函数是tf.zeros_like(), 它可以创建与已有的tensor相同形状的全0 tensor 。例如,
y = tf.zerosLike(my_tensor)
这等同于
y = tf.zeros(my_tensor.shape,my_tensor.dtype)
但是更简洁。
类似的方法允许你创建全1 tensor: tf.ones() 和tf.ones_like()。
>>> b = tf.ones((2,2,2))
>>> b
<tf.Tensor: shape=(2, 2, 2), dtype=float32, numpy=
array([[[1., 1.], [1., 1.]], [[1., 1.], [1., 1.]]], dtype=float32)>
用常数填充张量
如果我们想用别的值填充张量,该如何呢? 可以用 tf.fill()完成 (Example 2-4).
Example 2-4. Filling tensors with arbitrary values
>>> b = tf.fill((2, 2), value=5.)
>>> b
<tf.Tensor: shape=(2, 2), dtype=float32, numpy=
array([[5., 5.],
[5., 5.]], dtype=float32)>
>>>tffill=tf.fill([2,3], -1)
>>>Tffill
<tf.Tensor: shape=(2, 3), dtype=int32, numpy=
array([[-1, -1, -1],
[-1, -1, -1]])>
tf.constant是另一个函数,与 tf.fill相似, 可以用以构建在程序执行过程中不能改变的张量 (Example 2-5)。什么是tf.constant?一个constant有如下参数,可以按要求调整以得到需要的功能。Constant的值是不能被修改的。
value:输出类型为dtype的constant的值(或列表)
? dtype: 所得的张量的元的类型,可选
? shape: 所得张量的维,可选
? name: 所得张量的名字,可选
Example 2-5. Creating constant tensors
>>> a = tf.constant(3)
>>> a
<tf.Tensor: shape=(), dtype=int32, numpy=3>
>>>tf.constant([8, 6, 7, 5, 3, 0, 9])
<tf.Tensor: shape=(7,), dtype=int32, numpy=array([8, 6, 7, 5, 3, 0, 9])>
>>>a = tf.constant(1)
>>>b = tf.constant(5)
>>>c= a*b
>>>print(c)
tf.Tensor(5, shape=(), dtype=int32)
# Create a constant initiaized with a fixed value.
>>>a_constant_tensor = tf.constant(123.100)
>>>print(a_constant_tensor)
>>>tf.print(a_constant_tensor)
tf.Tensor(123.1, shape=(), dtype=float32)
123.1
#CONSTANT
>>>import tensorflow as tf
>>>tens1 = tf.constant([[[1,2],[2,3]],[[3,4],[5,6]]])
>>>print(tens1[1,1,0])
tf.Tensor(5, shape=(), dtype=int32)
尽管我们可以用选定的任意方法组合并再组合这些张量 ,我们并不能改变这些张量值(只能用新的值创建新的张量)。这种编程风格是函数式的而不是有状态的。
基于序列和范围创建Tensors
你也可以用TensorFlow的序列生成函数创建tensors。TensorFlow 函数linspace()
和range()
与
python/numpy的相应函数非常相似。
>>>a=tf.linspace(start=0.0, stop=1.0, num=3)
>>>a
<tf.Tensor: shape=(3,), dtype=float32, numpy=array([0. , 0.5, 1. ], dtype=float32)>
>>>b=tf.range(start=6, limit=15, delta=3)
>>>b
<tf.Tensor: shape=(3,), dtype=int32, numpy=array([ 6, 9, 12])>
2.3.3创建随机值的tensors
尽管常数张量对于测试很方便,更常见的是用随机数初始化张量。创建随机值的tensors在许多情况下是有用的。许多机器学习算法通过更新存贮权重的张量来学习。如果张量初始化为常数值则不能很好的学习,因此需要用随机数张量。例如初始化权重。最常见的方法是从随机分布中取机张量的实体。最常用的函数是tf.random.normal() 和 tf.random.uniform()。两个函数的符号相似但是元素值的分布不同。正如它的名字所示,tf.random.normal()返回的tensors的元素服从正态分布。tf.random.normal 从指定均值和标准差的正态分布中取值。 (Example 2-6).
Example 2-6 Sampling a tensor with random Normal entries
>>> a = tf.random.normal((2, 2), mean=0, stddev=1)
>>> a.eval()
<tf.Tensor: shape=(2, 2), dtype=float32, numpy=
array([[ 0.93582726, 2.0912473 ],
[-0.838633 , 0.42628655]], dtype=float32)>
如果你只提供shape参数调用函数,你得到的tensor的所有元素服从标准正态分布:均值为0标准差为1的正态分布。例如,
>>>row_dim = 2
>>>col_dim = 3
>>>rnorm_var = tf.random.normal([row_dim, col_dim])
>>>print(rnorm_var)
tf.Tensor([[-0.57468396 0.14487568 -0.6770046 ]
[-1.673455 -0.8273121 1.6534648 ]], shape=(2, 3), dtype=float32)
如果你想要正态分布有非黙认的均值和标准差,你要提供它们作为第二个和第三个输入参数。例如,下面的代码创建元素服从均值为20标准差为0.6的正态分布的tensor。
>>>rnorm_var = tf.random.normal([row_dim, col_dim],-20, 0.6)
>>>print(rnorm_var)
tf.Tensor(
[[-19.392843 -20.463398 -20.568737]
[-20.180227 -19.270271 -19.49574 ]], shape=(2, 3), dtype=float32)
注意机器学习系统通常使用非常大的张量,通常有上百万个参数。当我们从正态分布中取上百万个随机数时,某些值可能离平均值很远。这会导致数值不稳定,所以需要使用 tf.truncated.normal()而不是tf.random.normal()。这个函数的行为与tf.random.normal()相似,但是去掉了离均值2个标准差的数并重取样。
tf.random.uniform() 的行为与tf.random.normal()相似,只是随机值在指定范围内服从均匀分布 (Example 2-7)。tf.random.uniform()允许你创建随机tensors它的元素服从均匀分布。黙认的,均匀分布是单位一,即下限为0上限为1:
Example 2-7. Sampling a tensor with uniformly random entries
>>>runif_var = tf.random.uniform([row_dim, col_dim])
>>>print(runif_var)
tf.Tensor(
[[0.5040356 0.99528396 0.69372094]
[0.6397085 0.57031155 0.48447895]], shape=(2, 3), dtype=float32)
如果你要让元素的值服从非单位均匀分布,你可以指明上限和下限作为tf.random.uniform()第二和第三个参数。例如,
>>>runif_var = tf.random.uniform([row_dim, col_dim], minval=-10, maxval=10)
>>>print(runif_var)
创建的tensor的元素值在区间[-10, 10)均匀分布:
tf.Tensor(
[[-6.0767674 -2.4103093 0.2182846]
[ 6.3281536 9.959738 4.9375677]], shape=(2, 3), dtype=float32)
tf.random.uniform()可以创建int32类型的随机值的tensors。当你要创建随机标签时这个函数很有用。例如,正面的代码创建长度为10的向量,值从0-100的整数随机抽取:
>>>x = tf.random.uniform([10], 0, 100, tf.int32)
>>>print(x)
tf.Tensor([18 37 89 16 94 76 38 10 40 88], shape=(10,), dtype=int32)
注意 tf.int32是本例的重点,没有它,你得到的tensor包含float32值而不是 int32值。
2.3.4TensorFlow 变量(Variables)
前面的所有例子都使用常数张量。虽然函数计算很有用,机器学习通常依赖于状态计算。学习算法是更新存贮的张量以解释提供的数据的关键规则。如果不能更新这些存贮的张量,就很难学习。TensorFlow的算法需要知道哪些对象是variables哪些对象是constants。TensorFlow的variable是呈现你的程序所操作的共享的,持久的状态的最好的方法。
Variables由tf.Variable类操作。tf.Variable() 类提供了对张量的包装,允许有状态的计算。 variable对象作为张量的容器。内在地,一个tf.Variable存贮持久的张量。具体的操作允许你读取和修改这个张量的值。我们可以用函数tf.Variable()
创建
variables。创建变量很容易 (Example 2-8).
Example 2-8. Creating a TensorFlow variable
>>> a = tf.Variable(tf.ones((2, 2)))
>>> a
<tf.Variable 'Variable:0' shape=(2, 2) dtype=float32, numpy=
array([[1., 1.],
[1., 1.]], dtype=float32)>
variables需要显式的初始化。变量的形状在初始化时固定,必须在更新时保留。我们通过指定行和列的大小来创建指定形状的variables。
import tensorflow as tf
import numpy as np
from tensorflow.python.framework import ops
ops.reset_default_graph()
row_dim = 2
col_dim = 3
zero_var = tf.Variable(tf.zeros([row_dim, col_dim]))
ones_var = tf.Variable(tf.ones([row_dim, col_dim]))
zero_var
ones_var
my_var = tf.Variable(tf.zeros([1,20]))
my_var
<tf.Variable 'Variable:0' shape=(1, 20) dtype=float32, numpy=
array([[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0.]], dtype=float32)>
我们可以从常数数组或列表创建variable
# Create a variable from a constant
const_var = tf.Variable(tf.constant([8, 6, 7, 5, 3, 0, 9]))
# This can also be used to fill an array:
const_fill_var = tf.Variable(tf.constant(-1, shape=[row_dim, col_dim]))
print(const_var)
print(const_fill_var)
<tf.Variable 'Variable:0' shape=(7,) dtype=int32, numpy=array([8, 6, 7, 5, 3, 0, 9])>
<tf.Variable 'Variable:0' shape=(2, 3) dtype=int32, numpy=
array([[-1, -1, -1],
[-1, -1, -1]])>
x = tf.Variable(3, name="x")
y = tf.Variable(4, name="y")
f = x*x*y
a = tf.zeros((2,2));
b = tf.ones((2,2))
a.get_shape()
tf.reshape(a,(1,4))
当你声明了一个variable, 你可以在以后通过tf.assign()方法(可以用一个值或操作完成初始化)改变它的值。
import tensorflow as tf
import numpy as np
from tensorflow.python.framework import ops
ops.reset_default_graph()
my_var = tf.Variable(tf.zeros([2,3]))
my_var.assign([[2,3,1],[2,3,1]])
<tf.Variable 'UnreadVariable' shape=(2, 3) dtype=float32, numpy=
array([[2., 3., 1.],
[2., 3., 1.]], dtype=float32)>