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.fill()完成 (Example 2-4).
*Example 2-4. Filling tensors with arbitrary values*
\>\>\> b = tf.fill((2, 2), value=5.)
\>\>\> b
\
```
>>>tffill=tf.fill([2,3], -1)
```
```
>>>Tffill
```
```
```
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.constant(\[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
```
```
\>\>\>b=tf.range(start=6, limit=15, delta=3)
\>\>\>b
```
```
```
```
**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()
\
如果你只提供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.4** **TensorFlow** **变量(** **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
\
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
```
```
我们可以从常数数组或列表创建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)
```
```
```
```
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\]\])
```
```