深度学习发展成功与局限
最近几年深度学习的流行,大家一般认为是从2012年 AlexNet 在图像识别领域的成功作为一个里程碑。AlexNet 提升了整个业界对机器学习的接受程度:以前很多机器学习算法都处在“差不多能做 demo ”的程度,但是 AlexNet 的效果跨过了很多应用的门槛,造成了应用领域井喷式的兴趣。
推荐系统的应用需求
为什么我们会想到使用深度学习去处理推荐系统里面的事情呢,推荐系统从基于内容的推荐,到协同过滤的推荐,协同过滤的推荐在整个推荐算法领域里独领风烧了多年。或许深度学习在推荐系统里面没有像图像处理算法那样一枝独秀,但是深度学习对于推荐系统的帮助确实起到了,推波助澜的功效。
具体的基于深度的推荐模型后面讲TensorFlow详细介绍
特征提取方面
深度学习算法试图从数据中学习高级功能,这是深度学习的一个非常独特的部分。因此,减少了为每个问题开发新特征提取器的任务。适合用在难提取特征的图像、语音、自然语言领域
数据量
机器学习需要的执行时间远少于深度学习,深度学习参数往往很庞大,需要通过大量数据的多次优化来训练参数。
第一、它们需要大量的训练数据集
第二、是训练深度神经网络需要大量的算力
可能要花费数天、甚至数周的时间,才能使用数百万张图像的数据集训练出一个深度网络。所以以后
- 需要强大对的GPU服务器来进行计算
- 全面管理的分布式训练与预测服务——比如谷歌 TensorFlow 云机器学习平台——可能会解决这些问题,为大家提供成本合理的基于云的 CPU 和 GPU
算法代表
前几年一直关注AI框架,但是近年来框架的同质化说明了它不再是一个需要花大精力解决的问题,TensorFlow、Pytorch这样的框架在工业界的广泛应用,以及各种框架利用 Python 在建模领域的优秀表现,已经可以帮助我们解决很多以前需要自己编程实现的问题,如果作为 AI 工程师,我们应该跳出框架的桎梏,往更广泛的领域寻找价值。
tensorflow的github:
官网:https://www.tensorflow.org/
语言多样(Language Options)
使用分发策略进行分发训练
Tensorboard可视化
在任何平台上的生产中进行强大的模型部署
一旦您训练并保存了模型,就可以直接在应用程序中执行它,或者使用部署库为其提供服务:
安装 TensorFlow在64 位系统上测试这些系统支持 TensorFlow:
进入虚拟环境当中再安装。刚开始的环境比较简单,只要下载tensorflow即可
安装较慢,指定镜像源,请在带有numpy等库的虚拟环境中安装
pip install tensorflow==1.13 -i https://mirrors.aliyun.com/pypi/simple
pip install tensorflow==1.13 -i https://mirrors.aliyun.com/pypi/simple
注:如果需要下载GPU版本的(TensorFlow只提供windows和linux版本的,没有Macos版本的)参考官网https://www.tensorflow.org/install/gpu?hl=zh-cn,
1、虚拟机下linux也是用不了GPU版本TensorFlow
2、本机单独的windows和本机单独的unbuntu可以使用GPU版本TensorFlow,需要安装相关驱动
def tensorflow_demo():
"""
通过简单案例来了解tensorflow的基础结构
:return: None
"""
# 一、原生python实现加法运算
a = 10
b = 20
c = a + b
print("原生Python实现加法运算方法1:\n", c)
def add(a, b):
return a + b
sum = add(a, b)
print("原生python实现加法运算方法2:\n", sum)
# 二、tensorflow实现加法运算
a_t = tf.constant(10)
b_t = tf.constant(20)
# 不提倡直接运用这种符号运算符进行计算
# 更常用tensorflow提供的函数进行计算
# c_t = a_t + b_t
c_t = tf.add(a_t, b_t)
print("tensorflow实现加法运算:\n", c_t)
# 如何让计算结果出现?
# 开启会话
with tf.Session() as sess:
sum_t = sess.run(c_t)
print("在sess当中的sum_t:\n", sum_t)
return None
注意问题:警告指出你的CPU支持AVX运算加速了线性代数计算,即点积,矩阵乘法,卷积等。可以从源代码安装TensorFlow来编译,当然也可以选择关闭
import os os.environ['TF_CPP_MIN_LOG_LEVEL']='2'
TensorFlow 程序通常被组织成一个构建图阶段和一个执行图阶段。
在构建阶段,数据与操作的执行步骤被描述成一个图。
在执行阶段,使用会话执行构建好的图中的操作。
TensorFlow是一个采用数据流图(data flow graphs),用于数值计算的开源框架。
节点(Operation)在图中表示数学操作,线(edges)则表示在节点间相互联系的多维数据数组,即张量(tensor)。
图包含了一组tf.Operation代表的计算单元对象和tf.Tensor代表的计算单元之间流动的数据。
通常TensorFlow会默认帮我们创建一张图。
查看默认图的两种方法:
def graph_demo():
# 图的演示
a_t = tf.constant(10)
b_t = tf.constant(20)
# 不提倡直接运用这种符号运算符进行计算
# 更常用tensorflow提供的函数进行计算
# c_t = a_t + b_t
c_t = tf.add(a_t, b_t)
print("tensorflow实现加法运算:\n", c_t)
# 获取默认图
default_g = tf.get_default_graph()
print("获取默认图:\n", default_g)
# 数据的图属性
print("a_t的graph:\n", a_t.graph)
print("b_t的graph:\n", b_t.graph)
# 操作的图属性
print("c_t的graph:\n", c_t.graph)
# 开启会话
with tf.Session() as sess:
sum_t = sess.run(c_t)
print("在sess当中的sum_t:\n", sum_t)
# 会话的图属性
print("会话的图属性:\n", sess.graph)
return None
def graph_demo():
# 图的演示
a_t = tf.constant(10)
b_t = tf.constant(20)
# 不提倡直接运用这种符号运算符进行计算
# 更常用tensorflow提供的函数进行计算
# c_t = a_t + b_t
c_t = tf.add(a_t, b_t)
print("tensorflow实现加法运算:\n", c_t)
# 获取默认图
default_g = tf.get_default_graph()
print("获取默认图:\n", default_g)
# 数据的图属性
print("a_t的graph:\n", a_t.graph)
print("b_t的graph:\n", b_t.graph)
# 操作的图属性
print("c_t的graph:\n", c_t.graph)
# 自定义图
new_g = tf.Graph()
print("自定义图:\n", new_g)
# 在自定义图中去定义数据和操作
with new_g.as_default():
new_a = tf.constant(30)
new_b = tf.constant(40)
new_c = tf.add(new_a, new_b)
# 数据的图属性
print("new_a的graph:\n", new_a.graph)
print("new_b的graph:\n", new_b.graph)
# 操作的图属性
print("new_c的graph:\n", new_c.graph)
# 开启会话
with tf.Session() as sess:
sum_t = sess.run(c_t)
print("在sess当中的sum_t:\n", sum_t)
# 会话的图属性
print("会话的图属性:\n", sess.graph)
# 不同的图之间不能互相访问
# sum_new = sess.run(new_c)
# print("在sess当中的sum_new:\n", sum_new)
with tf.Session(graph=new_g) as sess2:
sum_new = sess2.run(new_c)
print("在sess2当中的sum_new:\n", sum_new)
print("会话的图属性:\n", sess2.graph)
# 很少会同时开启不同的图,一般用默认的图就够了
return None
TensorFlow有一个亮点就是,我们能看到自己写的程序的可视化效果,这个功能就是Tensorboard。在这里我们先简单介绍一下其基本功能。
TensorFlow 可用于训练大规模深度神经网络所需的计算,使用该工具涉及的计算往往复杂而深奥。为了更方便 TensorFlow 程序的理解、调试与优化,TensorFlow提供了TensorBoard 可视化工具。
实现程序可视化过程:
TensorBoard 通过读取 TensorFlow 的事件文件来运行,需要将数据生成一个序列化的 Summary protobuf 对象。
# 返回filewriter,写入事件文件到指定目录(最好用绝对路径),以提供给tensorboard使用
tf.summary.FileWriter('./tmp/summary/test/', graph=sess.graph)
这将在指定目录中生成一个 event 文件,其名称格式如下:
events.out.tfevents.{timestamp}.{hostname}
tensorboard --logdir="./tmp/tensorflow/summary/test/"
在浏览器中打开 TensorBoard 的图页面 127.0.0.1:6006 ,会看到与以下图形类似的图,在GRAPHS模块我们可以看到以下图结构
哪些是OP?
类型 | 实例 |
---|---|
标量运算 | add, sub, mul, div, exp, log, greater, less, equal |
向量运算 | concat, slice, splot, constant, rank, shape, shuffle |
矩阵运算 | matmul, matrixinverse, matrixdateminant |
带状态的运算 | Variable, assgin, assginadd |
神经网络组件 | softmax, sigmoid, relu,convolution,max_pool |
存储, 恢复 | Save, Restroe |
队列及同步运算 | Enqueue, Dequeue, MutexAcquire, MutexRelease |
控制流 | Merge, Switch, Enter, Leave, NextIteration |
一个操作对象(Operation)是TensorFlow图中的一个节点, 可以接收0个或者多个输入Tensor, 并且可以输出0个或者多个Tensor,Operation对象是通过op构造函数(如tf.matmul())创建的。
例如: c = tf.matmul(a, b) 创建了一个Operation对象,类型为 MatMul类型, 它将张量a, b作为输入,c作为输出,,并且输出数据,打印的时候也是打印的数据。其中tf.matmul()是函数,在执行matmul函数的过程中会通过MatMul类创建一个与之对应的对象
# 实现一个加法运算
con_a = tf.constant(3.0)
con_b = tf.constant(4.0)
sum_c = tf.add(con_a, con_b)
print("打印con_a:\n", con_a)
print("打印con_b:\n", con_b)
print("打印sum_c:\n", sum_c)
打印语句会生成:
打印con_a:
Tensor("Const:0", shape=(), dtype=float32)
打印con_b:
Tensor("Const_1:0", shape=(), dtype=float32)
打印sum_c:
Tensor("Add:0", shape=(), dtype=float32)
注意,打印出来的是张量值,可以理解成OP当中包含了这个值。并且每一个OP指令都对应一个唯一的名称,如上面的Const:0,这个在TensorBoard上面也可以显示
请注意,tf.Tensor 对象以输出该张量的 tf.Operation 明确命名。张量名称的形式为 “
tf.Graph对象为其包含的 tf.Operation对象定义的一个命名空间。TensorFlow 会自动为图中的每个指令选择一个唯一名称,用户也可以指定描述性名称,使程序阅读起来更轻松。我们可以以以下方式改写指令名称
例如,tf.constant(42.0, name=“answer”) 创建了一个名为 “answer” 的新 tf.Operation 并返回一个名为 “answer:0” 的 tf.Tensor。如果默认图已包含名为 “answer” 的指令,则 TensorFlow 会在名称上附加 “1”、“2” 等字符,以便让名称具有唯一性。
a = tf.constant(3.0, name="a")
b = tf.constant(4.0, name="b" )
一个运行TensorFlow operation的类。会话包含以下两种开启方式
1 TensorFlow 使用 tf.Session 类来表示客户端程序(通常为 Python 程序,但也提供了使用其他语言的类似接口)与 C++ 运行时之间的连接
2 tf.Session 对象使用分布式 TensorFlow 运行时提供对本地计算机中的设备和远程设备的访问权限。
会话可能拥有的资源,如 tf.Variable,tf.QueueBase和tf.ReaderBase。当这些资源不再需要时,释放这些资源非常重要。因此,需要调用tf.Session.close会话中的方法,或将会话用作上下文管理器。以下两个例子作用是一样的:
def session_demo():
"""
会话演示
:return:
"""
a_t = tf.constant(10)
b_t = tf.constant(20)
# 不提倡直接运用这种符号运算符进行计算
# 更常用tensorflow提供的函数进行计算
# c_t = a_t + b_t
c_t = tf.add(a_t, b_t)
print("tensorflow实现加法运算:\n", c_t)
# 开启会话
# 传统的会话定义
# sess = tf.Session()
# sum_t = sess.run(c_t)
# print("sum_t:\n", sum_t)
# sess.close()
# 开启会话
with tf.Session() as sess:
# sum_t = sess.run(c_t)
# 想同时执行多个tensor
print(sess.run([a_t, b_t, c_t]))
# 方便获取张量值的方法
# print("在sess当中的sum_t:\n", c_t.eval())
# 会话的图属性
print("会话的图属性:\n", sess.graph)
return None
# 运行会话并打印设备信息
sess = tf.Session(config=tf.ConfigProto(allow_soft_placement=True,
log_device_placement=True))
会话可以分配不同的资源在不同的设备上运行。
/job:worker/replica:0/task:0/device:CPU:0
device_type:类型设备(例如CPU,GPU,TPU)
使用tf.operation.eval()也可运行operation,但需要在会话中运行
# 创建图
a = tf.constant(5.0)
b = tf.constant(6.0)
c = a * b
# 创建会话
sess = tf.Session()
# 计算C的值
print(sess.run(c))
print(c.eval(session=sess))
def session_run_demo():
"""
会话的run方法
:return:
"""
# 定义占位符
a = tf.placeholder(tf.float32)
b = tf.placeholder(tf.float32)
sum_ab = tf.add(a, b)
print("sum_ab:\n", sum_ab)
# 开启会话
with tf.Session() as sess:
print("占位符的结果:\n", sess.run(sum_ab, feed_dict={a: 3.0, b: 4.0}))
return None
请注意运行时候报的错误error:
RuntimeError:如果这Session是无效状态(例如已关闭)。 TypeError:如果fetches或者feed_dict键的类型不合适。 ValueError:如果fetches或feed_dict键无效或引用 Tensor不存在的键。
在编写 TensorFlow 程序时,程序传递和运算的主要目标是tf.Tensor
TensorFlow 的张量就是一个 n 维数组, 类型为tf.Tensor。Tensor具有以下两个重要的属性
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5l9M4fqE-1650942232063)(images/%E7%B1%BB%E5%9E%8B.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Seo5A0jf-1650942232064)(images/%E9%98%B6.png)]
形状有0阶、1阶、2阶….
tensor1 = tf.constant(4.0)
tensor2 = tf.constant([1, 2, 3, 4])
linear_squares = tf.constant([[4], [9], [16], [25]], dtype=tf.int32)
print(tensor1.shape)
# 0维:() 1维:(10, ) 2维:(3, 4) 3维:(3, 4, 5)
TensorFlow的张量具有两种形状变换,动态形状和静态形状
关于动态形状和静态形状必须符合以下规则
def tensor_demo():
"""
张量的介绍
:return:
"""
a = tf.constant(value=30.0, dtype=tf.float32, name="a")
b = tf.constant([[1, 2], [3, 4]], dtype=tf.int32, name="b")
a2 = tf.constant(value=30.0, dtype=tf.float32, name="a2")
c = tf.placeholder(dtype=tf.float32, shape=[2, 3, 4], name="c")
sum = tf.add(a, a2, name="my_add")
print(a, a2, b, c)
print(sum)
# 获取张量属性
print("a的图属性:\n", a.graph)
print("b的名字:\n", b.name)
print("a2的形状:\n", a2.shape)
print("c的数据类型:\n", c.dtype)
print("sum的op:\n", sum.op)
# 获取静态形状
print("b的静态形状:\n", b.get_shape())
# 定义占位符
a_p = tf.placeholder(dtype=tf.float32, shape=[None, None])
b_p = tf.placeholder(dtype=tf.float32, shape=[None, 10])
c_p = tf.placeholder(dtype=tf.float32, shape=[3, 2])
# 获取静态形状
print("a_p的静态形状为:\n", a_p.get_shape())
print("b_p的静态形状为:\n", b_p.get_shape())
print("c_p的静态形状为:\n", c_p.get_shape())
# 形状更新
# a_p.set_shape([2, 3])
# 静态形状已经固定部分就不能修改了
# b_p.set_shape([10, 3])
# c_p.set_shape([2, 3])
# 静态形状已经固定的部分包括它的阶数,如果阶数固定了,就不能跨阶更新形状
# 如果想要跨阶改变形状,就要用动态形状
# a_p.set_shape([1, 2, 3])
# 获取静态形状
print("a_p的静态形状为:\n", a_p.get_shape())
print("b_p的静态形状为:\n", b_p.get_shape())
print("c_p的静态形状为:\n", c_p.get_shape())
# 动态形状
# c_p_r = tf.reshape(c_p, [1, 2, 3])
c_p_r = tf.reshape(c_p, [2, 3])
# 动态形状,改变的时候,不能改变元素的总个数
# c_p_r2 = tf.reshape(c_p, [3, 1])
print("动态形状的结果:\n", c_p_r)
# print("动态形状的结果2:\n", c_p_r2)
return None
详细请参考: https://www.tensorflow.org/versions/r1.8/api_guides/python/math_ops
这些API使用,我们在使用的时候介绍,具体参考文档
TensorFlow变量是表示程序处理的共享持久状态的最佳方法。变量通过 tf.Variable OP类进行操作。变量的特点:
tf.Variable(
initial_value=None,trainable=True,collections=None
,name=None)
变量需要显式初始化,才能运行值
def variable_demo():
"""
变量的演示
:return:
"""
# 定义变量
a = tf.Variable(initial_value=30)
b = tf.Variable(initial_value=40)
sum = tf.add(a, b)
# 初始化变量
init = tf.global_variables_initializer()
# 开启会话
with tf.Session() as sess:
# 变量初始化
sess.run(init)
print("sum:\n", sess.run(sum))
return None
会在OP的名字前面增加命名空间的指定名字
with tf.variable_scope("name"):
var = tf.Variable(name='var', initial_value=[4], dtype=tf.float32)
var_double = tf.Variable(name='var', initial_value=[4], dtype=tf.float32)
<tf.Variable 'name/var:0' shape=() dtype=float32_ref>
<tf.Variable 'name/var_1:0' shape=() dtype=float32_ref>
根据数据建立回归模型,w1x1+w2x2+……+b = y,通过真实值与预测值之间建立误差,使用梯度下降优化得到损失最小对应的权重和偏置。最终确定模型的权重和偏置参数。最后可以用这些参数进行预测。
这里将数据分布的规律确定,是为了使我们训练出的参数跟真实的参数(即0.8和0.7)比较是否训练准确
运算
梯度下降优化
import tensorflow as tf
import os
def linear_regression():
"""
自实现线性回归
:return: None
"""
# 1)准备好数据集:y = 0.8x + 0.7 100个样本
# 特征值X, 目标值y_true
X = tf.random_normal(shape=(100, 1), mean=2, stddev=2)
# y_true [100, 1]
# 矩阵运算 X(100, 1)* (1, 1)= y_true(100, 1)
y_true = tf.matmul(X, [[0.8]]) + 0.7
# 2)建立线性模型:
# y = W·X + b,目标:求出权重W和偏置b
# 3)随机初始化W1和b1
weights = tf.Variable(initial_value=tf.random_normal(shape=(1, 1)))
bias = tf.Variable(initial_value=tf.random_normal(shape=(1, 1)))
y_predict = tf.matmul(X, weights) + bias
# 4)确定损失函数(预测值与真实值之间的误差)-均方误差
error = tf.reduce_mean(tf.square(y_predict - y_true))
# 5)梯度下降优化损失:需要指定学习率(超参数)
# W2 = W1 - 学习率*(方向)
# b2 = b1 - 学习率*(方向)
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01).minimize(error)
# 初始化变量
init = tf.global_variables_initializer()
# 开启会话进行训练
with tf.Session() as sess:
# 运行初始化变量Op
sess.run(init)
print("随机初始化的权重为%f, 偏置为%f" % (weights.eval(), bias.eval()))
# 训练模型
for i in range(100):
sess.run(optimizer)
print("第%d步的误差为%f,权重为%f, 偏置为%f" % (i, error.eval(), weights.eval(), bias.eval()))
return None
trainable的参数作用,指定是否训练
weight = tf.Variable(tf.random_normal([1, 1], mean=0.0, stddev=1.0), name="weights", trainable=False)
是代码结构更加清晰,Tensorboard图结构清楚
with tf.variable_scope("lr_model"):
def linear_regression():
# 1)准备好数据集:y = 0.8x + 0.7 100个样本
# 特征值X, 目标值y_true
with tf.variable_scope("original_data"):
X = tf.random_normal(shape=(100, 1), mean=2, stddev=2, name="original_data_x")
# y_true [100, 1]
# 矩阵运算 X(100, 1)* (1, 1)= y_true(100, 1)
y_true = tf.matmul(X, [[0.8]], name="original_matmul") + 0.7
# 2)建立线性模型:
# y = W·X + b,目标:求出权重W和偏置b
# 3)随机初始化W1和b1
with tf.variable_scope("linear_model"):
weights = tf.Variable(initial_value=tf.random_normal(shape=(1, 1)), name="weights")
bias = tf.Variable(initial_value=tf.random_normal(shape=(1, 1)), name="bias")
y_predict = tf.matmul(X, weights, name="model_matmul") + bias
# 4)确定损失函数(预测值与真实值之间的误差)-均方误差
with tf.variable_scope("loss"):
error = tf.reduce_mean(tf.square(y_predict - y_true), name="error_op")
# 5)梯度下降优化损失:需要指定学习率(超参数)
# W2 = W1 - 学习率*(方向)
# b2 = b1 - 学习率*(方向)
with tf.variable_scope("gd_optimizer"):
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01, name="optimizer").minimize(error)
# 2)收集变量
tf.summary.scalar("error", error)
tf.summary.histogram("weights", weights)
tf.summary.histogram("bias", bias)
# 3)合并变量
merge = tf.summary.merge_all()
# 初始化变量
init = tf.global_variables_initializer()
# 开启会话进行训练
with tf.Session() as sess:
# 运行初始化变量Op
sess.run(init)
print("随机初始化的权重为%f, 偏置为%f" % (weights.eval(), bias.eval()))
# 1)创建事件文件
file_writer = tf.summary.FileWriter(logdir="./summary", graph=sess.graph)
# 训练模型
for i in range(100):
sess.run(optimizer)
print("第%d步的误差为%f,权重为%f, 偏置为%f" % (i, error.eval(), weights.eval(), bias.eval()))
# 4)运行合并变量op
summary = sess.run(merge)
file_writer.add_summary(summary, i)
return None
使用
例如:
指定目录+模型名字
saver.save(sess, '/tmp/ckpt/test/myregression.ckpt')
saver.restore(sess, '/tmp/ckpt/test/myregression.ckpt')
如要判断模型是否存在,直接指定目录
checkpoint = tf.train.latest_checkpoint("./tmp/model/")
saver.restore(sess, checkpoint)
前面具体定义的flag_name
# 定义一些常用的命令行参数
# 训练步数
tf.app.flags.DEFINE_integer("max_step", 0, "训练模型的步数")
# 定义模型的路径
tf.app.flags.DEFINE_string("model_dir", " ", "模型保存的路径+模型名字")
# 定义获取命令行参数
FLAGS = tf.app.flags.FLAGS
# 开启训练
# 训练的步数(依据模型大小而定)
for i in range(FLAGS.max_step):
sess.run(train_op)
import tensorflow as tf
import os
tf.app.flags.DEFINE_string("model_path", "./linear_regression/", "模型保存的路径和文件名")
FLAGS = tf.app.flags.FLAGS
def linear_regression():
# 1)准备好数据集:y = 0.8x + 0.7 100个样本
# 特征值X, 目标值y_true
with tf.variable_scope("original_data"):
X = tf.random_normal(shape=(100, 1), mean=2, stddev=2, name="original_data_x")
# y_true [100, 1]
# 矩阵运算 X(100, 1)* (1, 1)= y_true(100, 1)
y_true = tf.matmul(X, [[0.8]], name="original_matmul") + 0.7
# 2)建立线性模型:
# y = W·X + b,目标:求出权重W和偏置b
# 3)随机初始化W1和b1
with tf.variable_scope("linear_model"):
weights = tf.Variable(initial_value=tf.random_normal(shape=(1, 1)), name="weights")
bias = tf.Variable(initial_value=tf.random_normal(shape=(1, 1)), name="bias")
y_predict = tf.matmul(X, weights, name="model_matmul") + bias
# 4)确定损失函数(预测值与真实值之间的误差)-均方误差
with tf.variable_scope("loss"):
error = tf.reduce_mean(tf.square(y_predict - y_true), name="error_op")
# 5)梯度下降优化损失:需要指定学习率(超参数)
# W2 = W1 - 学习率*(方向)
# b2 = b1 - 学习率*(方向)
with tf.variable_scope("gd_optimizer"):
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01, name="optimizer").minimize(error)
# 2)收集变量
tf.summary.scalar("error", error)
tf.summary.histogram("weights", weights)
tf.summary.histogram("bias", bias)
# 3)合并变量
merge = tf.summary.merge_all()
# 初始化变量
init = tf.global_variables_initializer()
# 开启会话进行训练
with tf.Session() as sess:
# 运行初始化变量Op
sess.run(init)
# 未经训练的权重和偏置
print("随机初始化的权重为%f, 偏置为%f" % (weights.eval(), bias.eval()))
# 当存在checkpoint文件,就加载模型
# 1)创建事件文件
file_writer = tf.summary.FileWriter(logdir="./summary", graph=sess.graph)
# 训练模型
for i in range(100):
sess.run(optimizer)
print("第%d步的误差为%f,权重为%f, 偏置为%f" % (i, error.eval(), weights.eval(), bias.eval()))
# 4)运行合并变量op
summary = sess.run(merge)
file_writer.add_summary(summary, i)
return None
def main(argv):
print("这是main函数")
print(argv)
print(FLAGS.model_path)
linear_regression()
if __name__ == "__main__":
tf.app.run()
参考代码
# 用tensorflow自实现一个线性回归案例
# 定义一些常用的命令行参数
# 训练步数
tf.app.flags.DEFINE_integer("max_step", 0, "训练模型的步数")
# 定义模型的路径
tf.app.flags.DEFINE_string("model_dir", " ", "模型保存的路径+模型名字")
FLAGS = tf.app.flags.FLAGS
class MyLinearRegression(object):
"""
自实现线性回归
"""
def __init__(self):
pass
def inputs(self):
"""
获取特征值目标值数据数据
:return:
"""
x_data = tf.random_normal([100, 1], mean=1.0, stddev=1.0, name="x_data")
y_true = tf.matmul(x_data, [[0.7]]) + 0.8
return x_data, y_true
def inference(self, feature):
"""
根据输入数据建立模型
:param feature:
:param label:
:return:
"""
with tf.variable_scope("linea_model"):
# 2、建立回归模型,分析别人的数据的特征数量--->权重数量, 偏置b
# 由于有梯度下降算法优化,所以一开始给随机的参数,权重和偏置
# 被优化的参数,必须得使用变量op去定义
# 变量初始化权重和偏置
# weight 2维[1, 1] bias [1]
# 变量op当中会有trainable参数决定是否训练
self.weight = tf.Variable(tf.random_normal([1, 1], mean=0.0, stddev=1.0),
name="weights")
self.bias = tf.Variable(0.0, name='biases')
# 建立回归公式去得出预测结果
y_predict = tf.matmul(feature, self.weight) + self.bias
return y_predict
def loss(self, y_true, y_predict):
"""
目标值和真实值计算损失
:return: loss
"""
# 3、求出我们模型跟真实数据之间的损失
# 均方误差公式
loss = tf.reduce_mean(tf.square(y_true - y_predict))
return loss
def merge_summary(self, loss):
# 1、收集张量的值
tf.summary.scalar("losses", loss)
tf.summary.histogram("w", self.weight)
tf.summary.histogram('b', self.bias)
# 2、合并变量
merged = tf.summary.merge_all()
return merged
def sgd_op(self, loss):
"""
获取训练OP
:return:
"""
# 4、使用梯度下降优化器优化
# 填充学习率:0 ~ 1 学习率是非常小,
# 学习率大小决定你到达损失一个步数多少
# 最小化损失
train_op = tf.train.GradientDescentOptimizer(0.1).minimize(loss)
return train_op
def train(self):
"""
训练模型
:param loss:
:return:
"""
g = tf.get_default_graph()
with g.as_default():
x_data, y_true = self.inputs()
y_predict = self.inference(x_data)
loss = self.loss(y_true, y_predict)
train_op = self.sgd_op(loss)
# 收集观察的结果值
merged = self.merge_summary(loss)
saver = tf.train.Saver()
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
# 在没训练,模型的参数值
print("初始化的权重:%f, 偏置:%f" % (self.weight.eval(), self.bias.eval()))
# 开启训练
# 训练的步数(依据模型大小而定)
for i in range(FLAGS.max_step):
sess.run(train_op)
# 生成事件文件,观察图结构
file_writer = tf.summary.FileWriter("./tmp/summary/", graph=sess.graph)
print("训练第%d步之后的损失:%f, 权重:%f, 偏置:%f" % (
i,
loss.eval(),
self.weight.eval(),
self.bias.eval()))
# 运行收集变量的结果
summary = sess.run(merged)
# 添加到文件
file_writer.add_summary(summary, i)
if __name__ == '__main__':
lr = MyLinearRegression()
lr.train()
TensorFlow 2.0 将专注于 简单性 和 易用性,具有以下更新:
**1、使用tf.data加载数据。**使用输入管道读取训练数据,输入管道使用tf.data创建。利用tf.feature_column描述特征,如分段和特征交叉。
2、使用tf.keras构建、训练并验证模型,或者使用Premade Estimators。
**3、使用分布式策略进行分布式训练。**对于大型机器学习训练任务,分布式策略API可以轻松地在不同硬件配置上分配和训练模型,无需更改模型的定义。由于TensorFlow支持各种硬件加速器,如CPU,GPU和TPU,因此用户可以将训练负载分配到单节点/多加速器以及多节点/多加速器配置上(包括TPU Pod)。
4、导出到Saved Model。 TensorFlow将对Saved Model进行标准化,作为TensorFlow服务的一部分,他将成为TensorFlow Lite、TensorFlow.js、TensorFlow Hub等格式的可互换格式。
工作流程
TFRecords其实是一种二进制文件,虽然它不如其他格式好理解,但是它能更好的利用内存,更方便复制和移动,并且不需要单独的标签文件。
TFRecords文件包含了tf.train.Example
协议内存块(protocol buffer)(协议内存块包含了字段 Features
)。可以获取你的数据, 将数据填入到Example
协议内存块(protocol buffer),将协议内存块序列化为一个字符串, 并且通过tf.python_io.TFRecordWriter
写入到TFRecords文件。
tf.train.Example
协议内存块(protocol buffer)(协议内存块包含了字段 Features
),Features
包含了一个Feature
字段,Features
中包含要写入的数据、并指明数据类型。这是一个样本的结构,批数据需要循环存入这样的结构
example = tf.train.Example(features=tf.train.Features(feature={
"features": tf.train.Feature(bytes_list=tf.train.BytesList(value=[features])),
"label": tf.train.Feature(int64_list=tf.train.Int64List(value=[label])),
}))
tf.train.Example(
features
=None)
tf.train.
Features
(
feature
=None)
tf.train.
Feature
(options)
这种结构是不是很好的解决了数据和标签(训练的类别标签)或者其他属性数据存储在同一个文件中
Example
协议内存块(protocol buffer)对于每一个点击事件样本数据,都需要写入到example当中,所以这里需要取出每一样本进行构造存入
# 保存到TFRecords文件中
df = train_res.select(['user_id', 'article_id', 'clicked', 'features'])
df_array = df.collect()
import pandas as pd
df = pd.DataFrame(df_array)
存储
import tensorflow as tf
def write_to_tfrecords(click_batch, feature_batch):
"""
将数据存进tfrecords,方便管理每个样本的属性
:param image_batch: 特征值
:param label_batch: 目标值
:return: None
"""
# 1、构造tfrecords的存储实例
writer = tf.python_io.TFRecordWriter("./train_ctr_201905.tfrecords")
# 2、循环将每个样本写入到文件当中
for i in range(len(click_batch)):
click = click_batch[i]
feature = feature_batch[i].tostring()
# 绑定每个样本的属性
example = tf.train.Example(features=tf.train.Features(feature={
"label": tf.train.Feature(int64_list=tf.train.Int64List(value=[click])),
"feature": tf.train.Feature(bytes_list=tf.train.BytesList(value=[feature])),
}))
writer.write(example.SerializeToString())
# 文件需要关闭
writer.close()
return None
# 开启会话打印内容
with tf.Session() as sess:
# 创建线程协调器
coord = tf.train.Coordinator()
# 开启子线程去读取数据
# 返回子线程实例
threads = tf.train.start_queue_runners(sess=sess, coord=coord)
# 存入数据
write_to_tfrecords(df.iloc[:, 2], df.iloc[:, 3])
# 关闭子线程,回收
coord.request_stop()
coord.join(threads)
取出每一样本进行构造存入
```python
# 保存到TFRecords文件中
df = train_res.select(['user_id', 'article_id', 'clicked', 'features'])
df_array = df.collect()
import pandas as pd
df = pd.DataFrame(df_array)
存储
import tensorflow as tf
def write_to_tfrecords(click_batch, feature_batch):
"""
将数据存进tfrecords,方便管理每个样本的属性
:param image_batch: 特征值
:param label_batch: 目标值
:return: None
"""
# 1、构造tfrecords的存储实例
writer = tf.python_io.TFRecordWriter("./train_ctr_201905.tfrecords")
# 2、循环将每个样本写入到文件当中
for i in range(len(click_batch)):
click = click_batch[i]
feature = feature_batch[i].tostring()
# 绑定每个样本的属性
example = tf.train.Example(features=tf.train.Features(feature={
"label": tf.train.Feature(int64_list=tf.train.Int64List(value=[click])),
"feature": tf.train.Feature(bytes_list=tf.train.BytesList(value=[feature])),
}))
writer.write(example.SerializeToString())
# 文件需要关闭
writer.close()
return None
# 开启会话打印内容
with tf.Session() as sess:
# 创建线程协调器
coord = tf.train.Coordinator()
# 开启子线程去读取数据
# 返回子线程实例
threads = tf.train.start_queue_runners(sess=sess, coord=coord)
# 存入数据
write_to_tfrecords(df.iloc[:, 2], df.iloc[:, 3])
# 关闭子线程,回收
coord.request_stop()
coord.join(threads)