https://www.wandouip.com/t5i183316/

引言

原来引用过一个段子,这里还要再引用一次。是关于苹果的。大意是,苹果发布了新的开发语言Swift,有非常多优秀的特征,于是很多时髦的程序员入坑学习。不料,经过一段头脑体操一般的勤学苦练,发现使用Swift做开发,不仅要学习Swift,还要学习Swift2、Swift3、Swift4...
后来我发现,这个段子很有普遍性,并非仅仅苹果如此,今天的TensorFlow 2.0也有点这样的趋势。以至于我不得不专门写一个课程的续集,来面对使用新版本软件开始机器学习的读者。
事实上大多具有革命性的公司都是这样,一方面带来令人兴奋的新特征,另一方面则是高企不落的学习成本。

《从锅炉工到AI专家》一文中,已经对机器学习的基本概念做了很详细的介绍。所以在这里我们就省掉闲言絮语,直接从TensorFlow2.0讲起。
当然即便没有看过这个系列,假设你对TensorFlow 1.x很熟悉,也可以直接通过阅读本文,了解从TensorFlow 1.x迁移至2.x的知识。
如果你不了解机器学习的概念,试图通过直接学习TensorFlow 2.0开始AI开发,那可能比较困难。TensorFlow只是工具。没有技能,只凭工具,你恐怕无法踏上旅程。

安装

截至本文写作的时候,TensorFlow 2.0尚未正式的发布。pip仓库中仍然是1.13稳定版。所以如果想开始TensorFlow 2.0的学习,需要指定版本号来安装。此外由于Python2系列将于2020年元月停止官方维护,本文的示例使用Python3的代码来演示:

$ pip3 install tensorflow==2.0.0-alpha0

(注: 上面$是Mac/Linux的提示符,假如用Windows,你看到的提示符应当类似C:\Users\Administrator>这样子。)

如果希望使用GPU计算,安装的预先准备会麻烦一些,请参考这篇文档:https://www.tensorflow.org/install/gpu。主要是安装CUDA/cuDNN等计算平台的工具包。其中CUDA可以使用安装程序直接安装。cuDNN是压缩包,如果不打算自己编译TensorFlow的话,放置到CUDA相同目录会比较省事。
这里提醒一下,除非自己编译TensorFlow,否则一定使用CUDA 10.0的版本,低了、高了都不成,因为官方的2.0.0-alpha0使用了CUDA 10.0的版本编译。
此外TensorFlow的安装请使用如下命令:

$ pip3 install tensorflow-gpu==2.0.0-alpha0

安装完成后,可以在Python的交互模式,来确认TensorFlow正常工作:

$ python3
Python 3.7.2 (default, Feb 13 2019, 13:59:29)
[Clang 10.0.0 (clang-1000.11.45.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import tensorflow as tf
>>> tf.__version__
'2.0.0-alpha0'
>>>

本文中还会用到几个第三方的python扩展库,也是在机器学习中非常常用的,建议一起安装:

$ pip3 install numpy matplotlib pillow pandas seaborn sklearn

第一个例子:房价预测

本示例中的源码来自于《从锅炉工到AI专家》系列2,使用了最简单的线性函数来做房价预测。原始TensorFlow 1.x/ Python 2.x代码如下:

#!/usr/bin/env python
# -*- coding=UTF-8 -*- #本代码在mac电脑,python2.7环境测试通过
#第一行是mac/Linux系统脚本程序的标志,表示从环境参量中寻找python程序解释器来执行本脚本
#省去了每次在命令行使用 python <脚本名> 这样的执行方式
#第二行表示本脚本文本文件存盘使用的代码是utf-8,并且字符串使用的编码也是utf-8,
#在本源码中,这一点其实没有什么区别,但如果需要中文输出的时候,这一行就必须要加了。 #引入TensorFlow库
import tensorflow as tf
#引入数值计算库
import numpy as np #使用 NumPy 生成假数据集x,代表房间的平米数,这里的取值范围是0-1的浮点数,
#原因请看正文中的说明,属于是“规范化”之后的数据
# 生成的数据共100个,式样是100行,每行1个数据
x = np.float32(np.random.rand(100,1))
#我们假设每平米0.5万元,基础费用0.7万,这个数值也是规范化之后的,仅供示例
#最终运行的结果,应当求出来0.5/0.7这两个值代表计算成功
#计算最终房价y,x和y一同当做我们的样本数据
# np.dot的意思就是向量x * 0.5
y = np.dot(x,0.5) + 0.7
#---------------------------------数据集准备完成
#以下使用TensorFlow构建数学模型,在这个过程中,
#直到调用.run之前,实际上都是构造模型,而没有真正的运行。
#这跟上面的numpy库每一次都是真正执行是截然不同的区别
# 请参考正文,我们假定房价的公式为:y=a*x+b #tf.Variable是在TensorFlow中定义一个变量的意思
#我们这里简单起见,人为给a/b两个初始值,都是0.3,注意这也是相当于规范化之后的数值
b = tf.Variable(np.float32(0.3))
a = tf.Variable(np.float32(0.3)) #这是定义主要的数学模型,模型来自于上面的公式
#注意这里必须使用tf的公式,这样的公式才是模型
#上面使用np的是直接计算,而不是定义模型
# TensorFlow的函数名基本就是完整英文,你应当能读懂
y_value = tf.multiply(x,a) + b # 这里是代价函数,同我们文中所讲的唯一区别是用平方来取代求绝对值,
#目标都是为了得到一个正数值,功能完全相同,
#平方计算起来会更快更容易,这种方式也称为“方差“
loss = tf.reduce_mean(tf.square(y_value - y))
# TensorFlow内置的梯度下降算法,每步长0.5
optimizer = tf.train.GradientDescentOptimizer(0.5)
# 代价函数值最小化的时候,代表求得解
train = optimizer.minimize(loss) # 初始化所有变量,也就是上面定义的a/b两个变量
init = tf.global_variables_initializer() #启动图
sess = tf.Session()
#真正的执行初始化变量,还是老话,上面只是定义模型,并没有真正开始执行
sess.run(init) #重复梯度下降200次,每隔5次打印一次结果
for step in xrange(0, 200):
sess.run(train)
if step % 5 == 0:
print step, sess.run(loss),sess.run(a), sess.run(b)

代码保留了原始的注释,希望如果概念已经没有问题的话,可以让你不用跑回原文去看详细讲解。
程序使用numpy生成了一组样本集,样本集是使用线性函数生成的。随后使用TensorFlow学习这些样本,从而得到线性函数中未知的权重(Weight)和偏移(Bias)值。
原文中已经说了,这个例子并没有什么实用价值,只是为了从基础开始讲解“机器学习”的基本原理。

使用2.0中的v1兼容包来沿用1.x代码

TensorFlow 2.0中提供了tensorflow.compat.v1代码包来兼容原有1.x的代码,可以做到几乎不加修改的运行。社区的contrib库因为涉及大量直接的TensorFlow引用代码或者自己写的Python扩展包,所以无法使用这种模式。TensorFlow 2.0中也已经移除了contrib库,这让人很有点小遗憾的。
使用这种方式升级原有代码,只需要把原有程序开始的TensorFlow引用:

import tensorflow as tf

替换为以下两行就可以正常的继续使用:

import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()

其它代码无需修改。个人觉得,如果是稳定使用中、并且没有重构意愿的代码,这种方式算的上首选。

使用迁移工具来自动迁移1.x代码到2.0

TensorFlow 2.0中提供了命令行迁移工具,来自动的把1.x的代码转换为2.0的代码。工具使用方法如下(假设我们的程序文件名称为first-tf.py):

tf_upgrade_v2 --infile first-tf.py --outfile first-tf-v2.py

迁移工具还可以对整个文件夹的程序做升级,请参考工具自身的帮助文档。
使用迁移工具升级的代码,实质上也是使用了tensorflow.compat.v1兼容包来提供在TensorFlow 2.0环境中执行1.x的代码。这里贴出自动转换后的新代码供你对比参考:

#引入TensorFlow库
import tensorflow as tf
#import tensorflow.compat.v1 as tf
tf.compat.v1.disable_v2_behavior() #引入数值计算库
import numpy as np #使用 NumPy 生成假数据集x,代表房间的平米数,这里的取值范围是0-1的浮点数,
#原因请看正文中的说明,属于是“规范化”之后的数据
# 生成的数据共100个,式样是100行,每行1个数据
x = np.float32(np.random.rand(100,1))
#我们假设每平米0.5万元,基础费用0.7万,这个数值也是规范化之后的,仅供示例
#最终运行的结果,应当求出来0.5/0.7这两个值代表计算成功
#计算最终房价y,x和y一同当做我们的样本数据
# np.dot的意思就是向量x * 0.5
y = np.dot(x,0.5) + 0.7
#---------------------------------数据集准备完成
#以下使用TensorFlow构建数学模型,在这个过程中,
#直到调用.run之前,实际上都是构造模型,而没有真正的运行。
#这跟上面的numpy库每一次都是真正执行是截然不同的区别
# 请参考正文,我们假定房价的公式为:y=a*x+b #tf.Variable是在TensorFlow中定义一个变量的意思
#我们这里简单起见,人为给a/b两个初始值,都是0.3,注意这也是相当于规范化之后的数值
b = tf.Variable(np.float32(0.3))
a = tf.Variable(np.float32(0.3)) #这是定义主要的数学模型,模型来自于上面的公式
#注意这里必须使用tf的公式,这样的公式才是模型
#上面使用np的是直接计算,而不是定义模型
# TensorFlow的函数名基本就是完整英文,你应当能读懂
y_value = tf.multiply(x,a) + b # 这里是代价函数,同我们文中所讲的唯一区别是用平方来取代求绝对值,
#目标都是为了得到一个正数值,功能完全相同,
#平方计算起来会更快更容易,这种方式也称为“方差“
loss = tf.reduce_mean(input_tensor=tf.square(y_value - y))
# TensorFlow内置的梯度下降算法,每步长0.5
optimizer = tf.compat.v1.train.GradientDescentOptimizer(0.5)
# 代价函数值最小化的时候,代表求得解
train = optimizer.minimize(loss) # 初始化所有变量,也就是上面定义的a/b两个变量
init = tf.compat.v1.global_variables_initializer() #启动图
sess = tf.compat.v1.Session()
#真正的执行初始化变量,还是老话,上面只是定义模型,并没有真正开始执行
sess.run(init) #重复梯度下降200次,每隔5次打印一次结果
for step in range(0, 200):
sess.run(train)
if step % 5 == 0:
print(step, sess.run(loss),sess.run(a), sess.run(b))

转换之后,代码中的注释部分会完美的保留,喜欢用代码来代替文档的程序员可以放心。所有2.0中变更了的类或者方法,转换工具将使用tensorflow.compat.v1中的对应类或方法来替代,比如:

optimizer = tf.compat.v1.train.GradientDescentOptimizer(0.5)
train = optimizer.minimize(loss)
init = tf.compat.v1.global_variables_initializer()

所以从本质上,这种方式跟第一种方法,采用tensorflow.compat.v1包作为tensorflow替代包的方式是完全相同的。

编写原生的TensorFlow 2.0程序

推荐的演进方式,当然还是学习TensorFlow 2.0的相关特征,重构原有代码为新版本代码才是正路。平心而论,毕竟绝大多数系统的升级都是为了提供更多功能和降低使用门槛。TensorFlow 2.0也是大幅的降低了使用门槛的。大多数的工作比起1.x版本来,都能使用更少的代码量来完成。
首先了解一下TensorFlow 2.0同1.x之间的重要区别:

  • 在API层面的类、方法有了较大的变化,这个需要在使用中慢慢熟悉
  • 取消了Session机制,每一条命令直接执行,而不需要等到Session.run
  • 因为取消了Session机制,原有的数学模型定义,改为使用Python函数编写。原来的feed_dict和tf.placeholder,成为了函数的输入部分;原来的fetches,则成为了函数的返回值。
  • 使用keras的模型体系对原有的TensorFlow API进行高度的抽象,使用更容易
  • 使用tf.keras.Model.fit来替代原有的训练循环。

正常情况下,最后一项tf.keras.Model.fit能够大大的降低训练循环的代码量。但在本例中,我们模拟了一个现实中并不适用的例子,keras中并未对这种情形进行优化。所以在本例中反而无法使用tf.keras.Model.fit(实际上一定要使用也是可以的,不过要自定义模型,工作量更不划算)。因此本例中仍然要自己编写训练循环。并且因为2.0中API的变化,代码更复杂了。不过相信我,等到比较正式应用中,使用神经网络、卷积等常用算法,代码就极大的简化了。
使用TensorFlow 2.0原生代码的程序代码如下:

#!/usr/bin/env python3
#上面一行改为使用python3解释本代码 #引入python新版本的语言特征
from __future__ import absolute_import, division, print_function #引入TensorFlow库,版本2.0
import tensorflow as tf #引入数值计算库
import numpy as np #使用 NumPy 生成假数据集x,代表房间的平米数,这里的取值范围是0-1的浮点数,
#原因请看正文中的说明,属于是“规范化”之后的数据
# 生成的数据共100个,式样是100行,每行1个数据
x = np.float32(np.random.rand(100,1))
#我们假设每平米0.5万元,基础费用0.7万,这个数值也是规范化之后的,仅供示例
#最终运行的结果,应当求出来0.5/0.7这两个值代表计算成功
#计算最终房价y,x和y一同当做我们的样本数据
y = np.dot(x,0.5) + 0.7
#---------------------------------数据集准备完成
# 请参考正文,我们假定房价的公式为:y=a*x+b
#定义tensorflow变量,a是权重,b是偏移
b = tf.Variable(np.float32(0.3))
a = tf.Variable(np.float32(0.3)) #以上代码基本同tensorflow1.x版本一致
#以下有了区别
#使用python语言定义数学模型,模型来自于上面的公式
#上面使用np的是直接计算得到训练样本,而不是定义模型
#模型中并非必须使用tensorflow的计算函数来代替python的乘法运算
@tf.function
def model(x):
return a*x+b #定义代价函数,也是python函数
def loss(predicted_y, desired_y):
return tf.reduce_sum(tf.square(predicted_y - desired_y)) # TensorFlow内置Adam算法,每步长0.1
optimizer = tf.optimizers.Adam(0.1)
# 还可以选用TensorFlow内置SGD(随机最速下降)算法,每步长0.001
#不同算法要使用适当的步长,步长过大会导致模型无法收敛
#optimizer = tf.optimizers.SGD(0.001) #重复梯度下降200次,每隔5次打印一次结果
for step in range(0, 200):
with tf.GradientTape() as t:
outputs = model(x) #进行一次计算
current_loss = loss(outputs, y) #得到当前损失值
grads = t.gradient(current_loss, [a, b]) #调整模型中的权重、偏移值
optimizer.apply_gradients(zip(grads,[a, b])) #调整之后的值代回到模型
if step % 5 == 0: #每5次迭代显示一次结果
print( "Step:%d loss:%%%2.5f weight:%2.7f bias:%2.7f " %
(step,current_loss.numpy(), a.numpy(), b.numpy()))

程序在升级中所做的修改和特殊的处理,都使用注释保留在了源码中。我觉得这种方式比打散摘出来讲解的能更透彻。
最后看一下新版程序的执行结果:

Step:0 loss:%25.78244 weight:0.4000000 bias:0.4000000
Step:5 loss:%2.71975 weight:0.7611420 bias:0.7740188
Step:10 loss:%3.09600 weight:0.6725605 bias:0.7224629
Step:15 loss:%0.87834 weight:0.4931822 bias:0.5800986
Step:20 loss:%1.24737 weight:0.4960071 bias:0.6186275
Step:25 loss:%0.22444 weight:0.5730734 bias:0.7264798
Step:30 loss:%0.47145 weight:0.5464076 bias:0.7252067
Step:35 loss:%0.09156 weight:0.4736322 bias:0.6712209
Step:40 loss:%0.14845 weight:0.4771673 bias:0.6866464
Step:45 loss:%0.06199 weight:0.5101752 bias:0.7255269
Step:50 loss:%0.03108 weight:0.4946054 bias:0.7112849
Step:55 loss:%0.04115 weight:0.4770990 bias:0.6918764
Step:60 loss:%0.00145 weight:0.4950625 bias:0.7060429
Step:65 loss:%0.01781 weight:0.5029647 bias:0.7096580
Step:70 loss:%0.00211 weight:0.4934593 bias:0.6963260
Step:75 loss:%0.00298 weight:0.4983235 bias:0.6982682
Step:80 loss:%0.00345 weight:0.5049748 bias:0.7031375
Step:85 loss:%0.00004 weight:0.5001755 bias:0.6976562
Step:90 loss:%0.00102 weight:0.5002422 bias:0.6978318
Step:95 loss:%0.00065 weight:0.5029225 bias:0.7010939
Step:100 loss:%0.00001 weight:0.5000774 bias:0.6990223
Step:105 loss:%0.00021 weight:0.4996552 bias:0.6993059
Step:110 loss:%0.00015 weight:0.5007215 bias:0.7008768
Step:115 loss:%0.00000 weight:0.4993480 bias:0.6997767
Step:120 loss:%0.00003 weight:0.4995552 bias:0.7000407
Step:125 loss:%0.00004 weight:0.5001000 bias:0.7004969
Step:130 loss:%0.00001 weight:0.4995880 bias:0.6998325
Step:135 loss:%0.00000 weight:0.4999941 bias:0.7000810
Step:140 loss:%0.00001 weight:0.5001197 bias:0.7000892
Step:145 loss:%0.00000 weight:0.4999250 bias:0.6998329
Step:150 loss:%0.00000 weight:0.5001498 bias:0.7000451
Step:155 loss:%0.00000 weight:0.5000388 bias:0.6999565
Step:160 loss:%0.00000 weight:0.4999948 bias:0.6999494
Step:165 loss:%0.00000 weight:0.5000526 bias:0.7000424
Step:170 loss:%0.00000 weight:0.4999576 bias:0.6999717
Step:175 loss:%0.00000 weight:0.4999971 bias:0.7000214
Step:180 loss:%0.00000 weight:0.4999900 bias:0.7000131
Step:185 loss:%0.00000 weight:0.4999775 bias:0.6999928
Step:190 loss:%0.00000 weight:0.5000094 bias:0.7000152
Step:195 loss:%0.00000 weight:0.4999923 bias:0.6999906

模型通过学习后,得到的结果是很接近我们的预设值的。
程序中还可以考虑使用随机快速下降算法(SGD),你可以把当前的Adam算法使用注释符屏蔽上,打开SGD算法的注释屏蔽来尝试一下。对于本例中的数据集来讲,SGD的下降步长需要的更小,同样循环次数下,求解的精度会低一些。可以看出对于本例,Adam算法显然是更有效率的。而在TensorFlow的支持下,对于同样的数据集和数学模型,变更学习算法会很容易。

(待续...)

相关文章

tensorflow兼容处理 tensorflow.compat.v1的更多相关文章

  1. ImportError: No module named tensorflow.compat.v1 忽略已经安装的某个包版本 忽略已安装版本

    ImportError: No module named tensorflow.compat.v1 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声 ...

  2. 移动端目标识别(3)——使用TensorFlow Lite将tensorflow模型部署到移动端(ssd)之Running on mobile with TensorFlow Lite (写的很乱,回头更新一个简洁的版本)

    承接移动端目标识别(2) 使用TensorFlow Lite在移动设备上运行         在本节中,我们将向您展示如何使用TensorFlow Lite获得更小的模型,并允许您利用针对移动设备优化 ...

  3. [Tensorflow] Practice - The Tensorflow Way

    该系列主要是<Tensorflow 实战Google深度学习框架 >阅读笔记:有了Cookbook的热身后,以这本书作为基础形成个人知识体系. Ref: [Tensorflow] Cook ...

  4. 移动端目标识别(1)——使用TensorFlow Lite将tensorflow模型部署到移动端(ssd)之TensorFlow Lite简介

    平时工作就是做深度学习,但是深度学习没有落地就是比较虚,目前在移动端或嵌入式端应用的比较实际,也了解到目前主要有 caffe2,腾讯ncnn,tensorflow,因为工作用tensorflow比较多 ...

  5. 移动端目标识别(2)——使用TENSORFLOW LITE将TENSORFLOW模型部署到移动端(SSD)之TF Lite Developer Guide

    TF Lite开发人员指南 目录: 1 选择一个模型 使用一个预训练模型 使用自己的数据集重新训练inception-V3,MovileNet 训练自己的模型 2 转换模型格式 转换tf.GraphD ...

  6. TensorFlow+Keras 03 TensorFlow 与 Keras 介绍

    1 TensorFlow 架构图 1.1 处理器 TensorFlow 可以在CPU.GPU.TPU中执行 1.2 平台 TensorFlow 具备跨平台能力,Windows .Linux.Andro ...

  7. [Tensorflow] **Android Meets TensorFlow

    TensorFlow Dev Summit 2017 From: Android Meets TensorFlow: How to Accelerate Your App with AI (Googl ...

  8. 使用TensorFlow Serving优化TensorFlow模型

    使用TensorFlow Serving优化TensorFlow模型 https://www.tensorflowers.cn/t/7464 https://mp.weixin.qq.com/s/qO ...

  9. TensorFlow应用实战 | TensorFlow基础知识

    挺长的~超出估计值了~预计阅读时间20分钟. 从helloworld开始 mkdir 1.helloworld cd 1.helloworldvim helloworld.py 代码: # -*- c ...

随机推荐

  1. c++新特性实验(2)类型特性

    1. 基本类型 1.1 增加 long long long long int signed long long signed long long int unsigned long long unsi ...

  2. Lvs 环境搭建 vbox搭建centos6.9 vbox设置 centos上安装nginx

    1.现在vbox上虚拟出3个虚拟机,分别为负载均衡器(Load Balance).实际服务器1(Real server1).实际服务器2(Real Server2) 要点: :vbox系统网络连接方式 ...

  3. img标签中的onerror事件

    img标签中有一个onerror事件.是当我引用的src属性获取不到图片或者网络错误导致无法正常显示我src属性的图片时,显示的提示错误图片或者是可以代替的万能图片. 用法: <img src= ...

  4. Eclipse 出现select type (? = any character,*= any String,Tz=TimeZone)

    在eclipse中想运行project的时候,往往是右键项目名称---->run As --->Java Application 但是会弹出窗口显示select type (? = any ...

  5. jnhs[未解决]无法使用选定的hibernate配置文件建立数据库连接.请验证hibernate.cfg.xml中的数据库连接详情信息

    工程可以正常的使用读写数据库,当然model和model.hbm.xml文件是自己写的. 解决中

  6. 避免SQL注入三慷慨法

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/wangyy130/article/details/26154837       要说SQL注入还要从 ...

  7. 2019.8.10 NOIP模拟测试16 反思总结【基本更新完毕忽视咕咕咕】

    一如既往先放代码,我还没开始改… 改完T1滚过来了,先把T1T2的题解写了[颓博客啊] 今天下午就要走了,没想到还有送行的饯别礼,真是欣喜万分[并没有] 早上刚码完前面的总结,带着不怎么有希望的心情开 ...

  8. 二维vector基本使用

    变量声明 vector<vector<int> > 变量名: 添加行 vector<vector<int> > v2d; for(int i=0;i&l ...

  9. WCF 服务

    1.代码 using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Seriali ...

  10. 完整版unity安卓发布流程(包括SDK有原生系统依赖关系的工程)

    要3个东西!NDS,SDK,JDK, NDK官网下载:https://developer.android.google.cn/ndk/downloads/index.html(注意系统是不是64位) ...