Python_ML-Day04: 深度学习、Tensorflow
1.Tensorflow特点
- 真正的可移植性
引入各种计算设备的支持包括CPU/GPU/TPU,以及能够很好地运行在移动端,
如安卓设备、ios、树莓派等等
- 多语言支持
Tensorflow 有一个合理的c++使用界面,也有一个易用的python使用界面来构建和
执行你的graphs,你可以直接写python/c++程序。
- 高度的灵活性与效率
TensorFlow是一个采用数据流图(data flow graphs),用于数值计算的开源软件库
能够灵活进行组装图,执行图。随着开发的进展,Tensorflow的效率不算在提高
- 支持TensorFlow
由谷歌提供支持,谷歌投入了大量精力开发 TensorFlow,它希望
TensorFlow 成为机器学习研究人员和开发人员的通用语言
2.安装
pip3 install tensorflow
pip3 install tensorflow==1.14
3.数据流图
- Tensor: 张量,数据
- operation: op算子,专门运算的操作节点.所有操作都是一个op
- graph: 图, 这个程序的结构 - 由Tensor 和 op 组成的图
- session: 会话, 运算图
4.图 Graph: 图包含了一组op, tensor 和 一个会话session
- 创建图:tf.Graph()
- 使用图:
# 创建一张图
g = tf.Graph()
# 使用图
with g.as_default():
a = tf.constant(5.0)
b = tf.constant(6.0)
sum1 = tf.add(a, b)
with tf.Session() as sess:
print(sess.run(sum1))
5.op 与 tensor 的区别
op: 只要使用tensorflow 的 api 定义的函数或者类,都是op. 即 tf. 点出来的都是算子
tensor: 张量 指代的数据。仅仅是数据。 可以是 op 里面的数据。即 op 里面是可以有tensor的。算子可以包括运算和数据
6.会话Session
- 运行TensorFlow操作图的类,使用默认注册的图,也可以指定
- tf.Session()
- 会话资源
会话可能拥有很多资源,如 tf.Variable,tf.QueueBase
和tf.ReaderBase,会话结束后需要进行资源释放
- sess = tf.Session() sess.run(...) sess.close()
- 使用上下文管理器,自动关闭session
with tf.Session() as sess:
sess.run(...)
- 可以给会话添加配置项: 比如打印log: config=tf.ConfigProto(log_device_placement=True)
- 交互式:tf.InteractiveSession() - 命令行使用
- 会话的run(fetches, feed_dict=None,graph=None):
0. fetches: 要运行的ops
1. 不是op 不能运行
2. 但有重载机制: + - * / 可以重载 比如: run(2 + 3)错 run(op + 2)可以
3. placeholder 可以实时的提供训练的数据
- placeholder(占位符) + feed_dict
- plt = tf.placeholder(tf.float32, [2,3]) -- 表示一个类型是float32的2行3列的数据占位,但是没有实际的数据
- plt = tf.placeholder(tf.float32, [None,3]) -- 表示一个类型是float32的 不定行 3列 的数据占位,但是没有实际的数据
- sess.run(plt, feed_dict={plt:[[1,2,3],[3,4,5]]})
- feed_dict: 是一个字典 允许调用者覆盖图中指定张量的值,提供给placeholder使用
4. 返回值异常
RuntimeError:如果它Session处于无效状态(例如已关闭)。
TypeError:如果fetches或feed_dict键是不合适的类型。
ValueError:如果fetches或feed_dict键无效或引用 Tensor不存在。
7.张量
- tensorflow基本的数据类型
- 一个类型化的N纬度数组 tf.tensor
- 三部分组成: 数据类型,形状[非常重要],名字
- 形状: 0阶/1阶/2阶/n阶
- 类型: tf.float32/float64/int32/int64/uint8/
- 属性:
1. graph 张量所在的图
2. op 张量的操作名
3. name 张量的字符串描述
4. shape 张量形状
- 0维 = ()
- 1维 = (?)
- 2维 = (?,?)
- 动态形状和静态形状: 在张量的变化中,有没有生成一个新的张量数据
1.静态形状
- 创建一个张量之后,默认的形状。初始状态的形状
- tf.Tensor.get_shape 获取静态形状
- tf.Tensor.set_shape 更新对象的静态形状。通常用于在不能直接推断的情况下
2.动态形状
- 一种动态变化,一种描述原始张量在执行过程中的一种形状
- tf.reshape: 创建一个具有不同动态形状的新张量
3.注意
- 转换静态形状的时候,1D-1D,2D-2D,但是不能跨阶 2D-3D
- 对于已经固定或者set静态形状的张量,不能再次设置静态形状
- tf.reshape 创建动态形状,元素个数要保持一致
8.张量的操作
- 创建固定值张量
tf.zeros()
tf.ones()
tf.constant()
- 创建随机张量
1. 通过正态分布去创建[正态分布-平均值和标准差]
tf.random_normal()
- 代码
# 全是0 的张量
zero = tf.zeros(shape=[3, 4], dtype=tf.float32)
# 全是1 的张量
print(zero.eval())
zero = tf.ones(shape=[3, 4], dtype=tf.float32)
print(zero.eval())
# 指定张量
cons = tf.constant(value=[5, 1], shape=[3, 3], dtype=tf.float32)
print(cons.eval())
# 创建随机张量
random = tf.random_normal(shape=[3, 3], mean=6, stddev=1.0, dtype=tf.float32)
print(random.eval())
- 改变张量类型
tf.string_to_number(string_tensor, out_type, name)
tf.cast(tensor, dtype, name)
- 切片与拓展
tf.concat()
9.变量
- 变量也是一种op. 是一种特殊的张量。能够进行持久化存储。它的值就是张量,默认被训练
- 创建一个带值initial_value的新变量: tf.Variable(initial_value=None,name=None)
0.initial_value:需要持久化的张量或者op
1.assign(value):为变量分配一个新值,返回新值
2.eval(session=None):计算并返回此变量的值
3.name属性表示变量名字
- 定义一个变量op的时候,一定要在会话当中运行初始化
def variable():
"""
变量
:return:
"""
# 初始化一个变量
random = tf.random_normal([2, 3], mean=0, stddev=1.0)
v1 = tf.Variable(random)
print(v1)
# 变量不能直接计算,必须先做显示的初始化操作
init_op = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init_op)
print(sess.run(v1))
10. 可视化学习Tensorboard
- 步骤
1. 将你的程序图结构序列化成事件文件events
2. 使用Tensorboard,读取事件文件,显示图形
- summary: 摘要
1. tf.summary.FileWriter('/tmp/tensorflow/summary/test/', graph=default_graph)
- 返回filewriter,写入事件文件到指定目录(最好用绝对路径),以提供给tensorboard使用
- graph = sess.graph
2.开启
- tensorboard --logdir="/tmp/tensorflow/summary/test/"
- 一般浏览器打开为127.0.0.1:6006
- 注:修改程序后,再保存一遍会有新的事件文件,打开默认为最新
11.自定义一个线性回归案例
- 步骤分析
1. 准备好数据
- 比如 1个特征值和1个目标值,总计100个样本
2. 建立模型
- 随机初始化准备一组权重w, 一个偏置 b
- y = wx + b
- 模型的参数,必须用变量初始化。因为要迭代
3. 求损失函数,均方误差
- (y1-y1`)^2 + (y2-y2`)^2 + ... + (y1-y100`)^2 / 100
4. 指定学习率,使用梯度下降去求解最优解
- 工具分析
1. 矩阵相乘
tf.matmul(x,w)
[m,n] * [n,1] = [m,1]
2. 平方
tf.square(error)
3. 均值
tf.reduce_mean(error)
4. 梯度下降优化器
- tf.train.GradientDescentOptimizer(learning_rate)
- learning_rate:学习率
- return:梯度下降op
- 梯度爆炸/梯度消失
1. 在极端的情况下,权重的值变得非常大,以至于溢出,导致Nan
2. 如何解决梯度爆炸?
- 重新设计网络
- 调整学习率
- 使用梯度截断: 在训练过程中检查和限制梯度的大小
- 使用激活函数
12.作用域
- with tf.variable_scope("a"):
- 作用
1. 让模型代码更加清晰,作用分明
13.增加变量显示
- 观察模型的参数、损失值等变量的变化
- 步骤
1. 收集变量:添加权重参数,损失值等需要检测变化的变量,到tensorboard
- tf.summary.scalar(name=’’,tensor) 收集对于损失函数和准确率
等单值变量,name为变量的名字,tensor为值
- tf.summary.histogram(name=‘’,tensor) 收集高维度的变量参数
- tf.summary.image(name=‘’,tensor) 收集输入的图片张量能显示图片
2. 合并变量并写入事件文件
- merged = tf.summary.merge_all()
- 运行合并:summary = sess.run(merged),每次迭代都需运行
- 添加:FileWriter.add_summary(summary,i),i表示第几次的值
14.模型的保存与加载
- tf.train.Saver(var_list=None,max_to_keep=5)
1. var_list:指定将要保存和还原的变量。它可以作为一个dict或一个列表传递.
2. max_to_keep:指示要保留的最近检查点文件的最大数量。
创建新文件时,会删除较旧的文件。如果无或0,则保留所有
检查点文件。默认为5(即保留最新的5个检查点文件。)
- 保存:saver.save(sess, '/tmp/ckpt/test/model')
- 加载:saver.restore(sess, '/tmp/ckpt/test/model')
- 保存文件格式:checkpoint文件
15.自定义命令行参数
- 步骤
1. 首先定义有哪些参数需要在运行时指定
- tf.app.flags.DEFINE_integer("flagname","default_value,"DESC")
- tf.app.flags.DEFINE_integer("max_step",100,"模型训练的步数")
2. 程序当中获取传入的参数
- FLAGS = tf.app.flags.FLAGS
- FLAGS.max_step
16.源码
import tensorflow as tf
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
# # 创建一张图
# g = tf.Graph()
# # 使用图
# with g.as_default():
# a = tf.constant(5.0)
# b = tf.constant(6.0)
# sum1 = tf.add(a, b)
# with tf.Session() as sess:
# print(sess.run(sum1))
def tensor():
"""
张量
:return:
"""
# 占位符
plt = tf.placeholder(tf.float32, [None, 2])
print(plt)
# 使用set_shape 确定形状为[3,2]
plt.set_shape([3, 2])
print(plt)
# 静态形状张量一旦固定,则不能再次设置了,而且元素的个数和纬度要一致
# plt.set_shape([4, 2])
# print(plt)
# 如果想再次设置形状,可以考虑使用动态张量。生成一个新的张量
# 但是要注意: [2,3] 可以变成[3,2],[6,1,1] 但是不能[3,3] 因为特征值数量一共6个,没办法变成9个
plt_reshape = tf.reshape(plt, [6, 1, 1])
print(plt_reshape)
def tensor_op():
"""
张量的操作
:return:
"""
# 全是0 的张量
zero = tf.zeros(shape=[3, 4], dtype=tf.float32)
# 全是1 的张量
print(zero.eval())
zero = tf.ones(shape=[3, 4], dtype=tf.float32)
print(zero.eval())
# 指定张量
cons = tf.constant(value=[5, 1], shape=[3, 3], dtype=tf.float32)
print(cons.eval())
# 创建随机张量
random = tf.random_normal(shape=[3, 3], mean=6, stddev=1.0, dtype=tf.float32)
print(random.eval())
# 张量的类型转换
c = tf.cast(random, tf.float32)
print(c.eval())
# 张量的合并。 列拼装
cc = tf.concat([cons, c], axis=1)
print(cc.eval())
def variable():
"""
变量
:return:
"""
# 初始化一个变量
random = tf.random_normal([2, 3], mean=0, stddev=1.0)
v1 = tf.Variable(random)
print(v1)
# 变量不能直接计算,必须先做显示的初始化操作
init_op = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init_op)
# 把程序的图,写入到事件文件
filewriter = tf.summary.FileWriter("./test", graph=sess.graph)
print(sess.run(v1))
def liner():
"""
手动实现线性回归
:return:
"""
with tf.variable_scope("a"):
# 准备数据 x 100 个样本 1 个特征 假设 目标值 y = 0.7x + 0.8
x = tf.random_normal([100, 1], mean=1.75, stddev=0.5)
# 建立线性回归模型 1特征1权重1偏置 y = wx + b
y_true = tf.matmul(x, [[0.7]]) + 0.8
# 随机初始化权重weight 和偏置bias
weight = tf.Variable(tf.random_normal([1, 1], mean=0, stddev=1), name='w')
b = tf.Variable(0.0, name='b')
with tf.variable_scope("b"):
# 求预测predict
y_pre = tf.matmul(x, weight) + b
# 计算损失loss
loss = tf.reduce_mean(tf.square(y_true - y_pre))
# 梯度下降优化损失 learn_rate: 0-1. 返回一个op
train_op = tf.train.GradientDescentOptimizer(0.2).minimize(loss)
# 通过会话,循环训练 运行程序[变量初始化global]
init_op = tf.global_variables_initializer()
# 收集tensor
tf.summary.scalar("losses", loss)
tf.summary.histogram("weight", weight)
# 合并
merged_op = tf.summary.merge_all()
# 定义一个保存模型的实例
saver = tf.train.Saver(var_list=None, max_to_keep=5)
with tf.Session() as sess:
sess.run(init_op)
print("初始w 和 b:", weight.eval(), b.eval())
filewriter = tf.summary.FileWriter('./test/', sess.graph)
# 加载模型,覆盖模型当中随机定义的参数,从检查点开始运行
if os.path.exists("./ckpt/checkpoint"):
saver.restore(sess, "./ckpt/model")
for i in range(200):
sess.run(train_op)
# 运行合并的merge_op
summary = sess.run(merged_op)
filewriter.add_summary(summary, i)
print("第{}次训练完之后的w 和 b: ".format(i), weight.eval(), b.eval())
saver.save(sess, "./ckpt/model")
if __name__ == '__main__':
liner()
Python_ML-Day04: 深度学习、Tensorflow
1.Tensorflow特