机器学习与数据挖掘人工智能/模式识别/机器学习精华专题大数据

TensorFlow深度学习-第四章

2019-11-30  本文已影响0人  皮皮大

本章中的内容包含:

TensorFlow是一个面向深度学习算法的科学计算库,内部数据保存在张量Tensor对象中,所有的运算操作都是基于张量进行的

image

数据类型

数值类型

数值类型的张量是TF的主要数据载体,包含:

  1. 标量Scalar,单个的实数,维度是0,形状shape[]
  2. 向量Vectorn个实数的有序集合,通过中括号包裹,例如[1,2,4,5,3],维数是1,长度不定,shape为n
  3. 矩阵Matrix,m行n列实数的有序集合,shape为[m,n]
  4. 张量是所有维度数(dim>2)的数组的统称,每个维度也称之为轴Axis。通常将标量、向量、矩阵也统称为张量;张量的维度和形状自行判断
标量

创建标量的关键字是constant,必须通过TF规定的方式去创建张量

import tensorflow as tf

a = 2  # python形式
b = tf.constant(2.0)  # 这才是TF形式
c = tf.constant([1,2.0,3.7])

tf.is_true(b)  # True

返回值中几个具体信息:

向量

向量的定义必须通过List类型转递给tf.constant函数

a = tf.constant([1.0])  # 即使是一个元素也是如此
b = tf.constant([1.0, 2.4, 4.5]) 
矩阵
a = tf.constant([[1,2],
                 [3,4]])  # 2维

b = tf.constant([[[1,2], [3,4]],
                 [[5,6], [7,8]]])  # 3维

字符串类型

字符串类型Strings类型的数据

a = tf.constant("hello tensorflow")

tf.strings模块中提供了常见的工具函数:

布尔类型

TF中支持布尔类型的张量

a = tf.constant([True, False])

# tf中布尔类型和Python的中布尔类型是不等同的
b =  tf.constant(True)
b == True     # 结果是False

数值精度

精度设置和获取

TF支持不同类型的精度,Bit位数越长,精度越高,同时占用的内存空间越大。

需要注意的点:

  1. 高精度转低精度可能会报错
  2. 对于浮点数,高精度的张量可以表示更精准的数据
  3. 实际中,一般使用tf.int32tf.float32
import numpy as np
import tensorflow as tf

# 创建张量的时候指定精度
tf.constant(12345678, dtype=tf.int32)
tf.constant(np.pi, dtype=tf.float64)

通过张量的dtype属性可以获取张量的精度

类型转换

通过tf.cast函数进行转换,需要注意的地方:

a = tf.constant([True, False])
tf.cast(a, tf.bool)  # 1,0

待优化张量

有些张量是需要计算梯度,因此产生了需要计算待优化的张量,专门用来支持梯度信息的记录,使用的函数是tf.Variable

tf.Variable类型在普通的张量类型基础上添加了nametrainable等属性来支持计算的构建。

梯度的计算会消耗大量的资源,且会自动更新相关参数。

创建张量

从Numpy、List对象创建

numpy中的array数组和Python中的list都可以直接用来创建张量,通过tf.convert_to_tensor

import tensorflow as tf
import numpy as np

tf.convert_to_tensor([1,2,3])
tf.convert_to_tensor(np.array([[1,2,3],[4,5,6]])

numpy中默认使用的是64-bit精度,转到TF中使用的是tf.float64

创建全0、全1张量

几个函数记住即可,like只是创建形状相同的张量:

tf.ones([2,3])

a = tf.zeros([2,4])
b = tf.ones_like(a)  # 形状相同

自定义数值张量

在创建张量的时候,可以指定初始值:tf.fill(shape, vlaue)

tf.fill([2,3], -1)  # 形状为2*3,值全部是-1

创建已知分布的张量

正态分布和均匀分布是最常见的。

注意:如果均匀分布中采样的是整数类型,必须指定maxval和数据类型

创建序列

创建序列类型的张量是通过函数tf.range(),标准的格式为:

tf.range(start,end,delta=1)  # 含头不含尾,delta为步长

张量的应用

标量

标量的应用主要是误差值的表示、各种测量指标的表示,入精确度、精度、召回率等

image
out = tf.random.uniform(4,10)  # 随机模拟网络输出
y = tf.constant([2,3,4,5]) # 随机构造样本真实输出标签
y = tf.one_hot(y, depth=10)  # 转成热编码
loss = tf.keras.losses.mse(y, out)  # 计算MSE
loss = tf.reduce_mean(loss)  # 平均MSE
print(mse)

向量

在全连接层和卷积神经网络中,偏置b就是向量b=[b_!,b_2]^T

image

通过高层结口Dense()方式创建地网络层,张量W和b存储在类的内部,由类自动创建。

fc = layers.Dense(3)  # 创建一层Wx+b,输出节点为3
fc.build(input_shape=(2,4))
fc.bias  # 查看偏置

矩阵

矩阵也是非常常见的张量类型,比如全连接层的批量输入X=[b,d_{in}],其中b表示的是输入样本的个数,即batch sized_{in}表示的是输入特征的长度。

w = tf.constant([3,4])  # 定义两个张量
b = tf.constant([3])  
o = x@w + b  # 执行X@W+b
fc = layers.Dense(3)  # 定义全连接层的输出节点为3
fc.build(input_shape=(2,4))  # 定义全连接层的输入节点为4
fc.kernel # 查看权重矩阵

3维张量

三维的张量一个典型应用是表示序列信号,它的格式是𝑋 = [𝑏, 𝑠𝑒𝑞𝑢𝑒𝑛𝑐𝑒 𝑙𝑒𝑛, 𝑓𝑒𝑎𝑡𝑢𝑟𝑒 𝑙𝑒𝑛]

4维张量

4维张量在卷积神经网络中应用的非常广泛,它用于保存特征图Feature maps数据, 格式一般定义为[b,h,w,c]

对于含有 RGB 3 个通道的彩色图片,每张图片包含了 h 行 w 列像素点,每个点需要 3 个数 值表示 RGB 通道的颜色强度,因此一张图片可以表示为[h, w, 3]

# 创建32x32的彩色图片输入,个数为4
x = tf.random.normal([4,32,32,3]) # 创建卷积神经网络
layer = layers.Conv2D(16,kernel_size=3) out = layer(x) # 前向计算
out.shape # 输出大小

# 卷积核张量也是4维张量,通过kernel属性来查看
layer.kernel.shape

索引和切片

索引

  1. 从0开始
  2. 两种方式
    1. [i][j][k]...
    2. [i,j,k,…]
x = tf.random.normal([4, 32, 32, 3])
x[0]
x[0][1][2]

切片

通过𝑠𝑡𝑎𝑟𝑡: 𝑒𝑛𝑑: 𝑠𝑡𝑒𝑝切片方式提取数据

关于冒号和三个点的使用:都是表示某个维度上的所有数据

x = tf.random.normal([4, 32, 32, 3])
x[1:3]
x[0,::]
x[0, 0:28, 2:28:2, :]
x[::-2]
x[0:2,...,1:]

维度变换

线性层的批量形式
Y=X@W+b
假设:

那么不同shape的张量之间如何进行相加?此时,维度变换可以解决


image

改变视图reshape

张量存储
  1. 张量的存储体现张量在内存上保存为一块连续的存储区域
  2. 张量的存储需要人为跟踪
  3. shape中相对靠左的维度称之为大维度;相对靠右的维度称之为小维度
张量视图

语法格式为tf.reshape(x, new_shape)

x = tf.random.normal([4, 32, 32, 3])
tf.reshape(x, [2,-1])
tf.reshape(x,[2,4,12])
tf.reshape(x,[2,-1,3])

增删维度

增加维度
x = tf.random.uniform([28,28],maxval=10,dtype=tf.int32)
x = tf.expand_dims(x,axis=2)
删除维度
x = tf.random.uniform([1,28,28,1],maxval=10,dtype=tf.int32)
x = tf.squeeze(x, axis=2)
tf.squeeze(x)

维度交换

x = tf.random.normal([2,32,32,3])
tf.transpose(x,perm=[0,3,1,2])

数据复制

通过函数tf.tile(x, multiples)来实现,关于参数multiples

  1. 1表示不复制
  2. 2表示长度为2倍,即复制1份
  3. 3表示长度为3倍,即复制2份;类推

复制操作会创建一个新的张量来保存复制后的张量,涉及到大量的IO操作,运算代价大

b = tf.constant([1,2])
b = tf.expand_dims(b, axis=0)  # 插入新维度
b = tf.tile(b, multiples=[2,1])  # axis=0上复制1份

x = tf.range(4)
x = tf.reshape(x, [2,2])
x = tf.tile(x, multiples=[1,2])  # 列上复制
x = tf.tile(x,multiples=[2,1])  # 行上复制

广播机制Broadcasting

通过函数tf.broadcast_to(x, new_shape)实现

特点
x = tf.random.normal([2,4])
w = tf.random.normal([4,3])
b = tf.random.normal([3])
y = x@w+b   # 等价于y = x@w + tf.broadcast_to(b,[2,3])  实现自动广播
核心思想

广播机制的核心思想是普适性,同一份数据能够适合于不同的位置

image

有些运算可以在处理不同 shape 的张量时,会隐式地调用广播机制

image

数学运算

方法 作用
// 整除
% 余除
tf.power(x,a),x**a 乘方
tf.square(x) 平方
tf.sqrt(x) 平方根
tf.power(a,x),a**x 指数运算
tf.exp(x) 自然指数
tf.math.log(x) 自然对数
log_ax=\frac{log_ex}{log_ea} 其他底数的对数

矩阵相乘

两种方式实现:

  1. @
  2. tf.matmul(a,b)函数

实战-前向传播

采用的手写数字图片集数据:

o𝑢𝑡 = 𝑟𝑒𝑙𝑢\{𝑟𝑒𝑙𝑢\{𝑟𝑒𝑙𝑢[𝑋@𝑊 + 𝑏 ]@𝑊 + 𝑏 \}@𝑊 + 𝑏 \}

#  计算每个线性函数的张量参数
w1 = tf.Variable(tf.random.truncated_normal([784, 256], stddev=0.1))
b1 = tf.Variable(tf.zeros([256]))
w2 = tf.Variable(tf.random.truncated_normal([256, 128], stddev=0.1))
b2 = tf.Variable(tf.zeros([128]))
w3 = tf.Variable(tf.random.truncated_normal([128, 10], stddev=0.1))
b3 = tf.Variable(tf.zeros([10]))

# 将输入数据进行维度变化
# [b, 28, 28] => [b, 28*28]
x = tf.reshape(x, [-1, 28*28])
 
# 非线性函数的计算
h1 = x@w1 + tf.broadcast_to(b1, [x.shape[0], 256])
h1 = tf.nn.relu(h1)  # 得到输出函数

# 完成剩下两个非线性函数
# [b, 256] => [b, 128]
h2 = h1@w2 + b2
h2 = tf.nn.relu(h2)
# [b, 128] => [b, 10]
out = h2@w3 + b3

# 计算均方差MSE
# mse = mean(sum(y-out)^2)
# [b, 10]
loss = tf.square(y_onehot - out)
# mean: scalar
loss = tf.reduce_mean(loss)

# 计算梯度
grads = tape.gradient(loss, [w1, b1, w2, b2, w3, b3]
                      
# w1 = w1 - lr * w1_grad
w1.assign_sub(lr * grads[0])
b1.assign_sub(lr * grads[1])
w2.assign_sub(lr * grads[2])
b2.assign_sub(lr * grads[3])
w3.assign_sub(lr * grads[4])
b3.assign_sub(lr * grads[5])
上一篇下一篇

猜你喜欢

热点阅读