MyException - 我的异常网
当前位置:我的异常网» Go » Tensorflow 实战 Google 深度学习框架 | 学习笔记(

Tensorflow 实战 Google 深度学习框架 | 学习笔记(1)

www.MyException.Cn  网友分享于:2018-03-30  浏览:1次
Tensorflow 实战 Google 深度学习框架 | 学习笔记(一)

本文转载自:http://www.javaxxz.com/thread-359454-1-1.html


  Shoot on the moon and if you miss you will still be among the stars.

Caicloud Github :tensorflow-tutorialhttps://github.com/caicloud/tensorflow-tutorial
原本 tutorial 使用的 Tensorflow 最新版本是 1.4.0 ,本人使用的 1.5.0 版本,所以部分代码会略有不同,该笔记仅为个人学习,理解使用。如有错误,还望批评指教。—-ZJ
3.1 计算图的使用

  1. [code]import tensorflow as tf
  2. tf.__version__
复制代码

[/code]

  1. [code]"1.5.0"
复制代码

[/code]

  1. [code]"""
  2. 3.12 计算图的使用
  3. """
  4. import tensorflow as tf
  5. a = tf.constant([1.0, 2.0], name="a")
  6. b = tf.constant([2.0, 3.0], name="b")
  7. result = a + b
  8. print(result)
复制代码

[/code]

  1. [code]Tensor("add:0", shape=(2,), dtype=float32)
复制代码

[/code]

  1. [code]print(a.graph is tf.get_default_graph())
复制代码

[/code]

  1. [code]True
复制代码

[/code]

  定义两个不同的图

除了默认的计算图,Tensorflow 支持通过 tf.Graph() 函数来生成新的计算图。

  1. [code]import tensorflow as tf
  2. g1 = tf.Graph()
  3. with g1.as_default():
  4.     # 在计算图 g1 中定义变量“v”,并设置初始值为 0
  5.     v = tf.get_variable("v", shape=[1], initializer=tf.zeros_initializer)
  6. g2 = tf.Graph()
  7. with g2.as_default():
  8.     # 在计算图 g2 中定义变量“v”设置初始值为 1
  9.     v = tf.get_variable("v", shape=[1], initializer=tf.ones_initializer)
  10. # 在计算图 g1 中,读取变量‘v’的值
  11. with tf.Session(graph=g1) as sess:
  12.     tf.global_variables_initializer().run()
  13.     with tf.variable_scope("", reuse=True):
  14.         # 在计算图 g1 中,变量 ‘v’的值取值应该为 0,所以下面这行会输出[0.]
  15.         print(sess.run(tf.get_variable("v")))
  16. # 在计算图 g2 中,读取变量‘v’的值
  17. with tf.Session(graph=g2) as sess:
  18.     tf.global_variables_initializer().run()
  19.     with tf.variable_scope("",reuse=True):
  20.         # 在计算图 g2 中,变量 ‘v’的值取值应该为 1,所以下面这行会输出[1.]
  21.         print(sess.run(tf.get_variable("v")))
复制代码

[/code]

  1. [code][0.]
  2. [1.]
复制代码

[/code]

  1. [code]import tensorflow as tf
  2. a = tf.constant([1.0, 2.0], name="a")
  3. b = tf.constant([2.0, 3.0], name="b")
  4. g  = tf.Graph()
  5. with g.device("/gpu:0"):
  6.     result = a + b
  7. print(result)
复制代码

[/code]

  1. [code]Tensor("add_1:0", shape=(2,), dtype=float32)
复制代码

[/code]
3.2 Tensorflow 数据模型—— 张量
第 n 阶张量,理解为 n 维数组。
与 numpy 不同,Tensorflow 计算的结果不是一个具体的数,而是一个张量的结构,主要保存三个属性:名字(name),维度(shape)和类型(type).
注意:类型要匹配

  1. [code]import tensorflow as tf
  2. a = tf.constant([1.0, 2.0], name="a")
  3. b = tf.constant([2.0, 3.4], name="b")
  4. c = tf.constant([4, 5], name="c")
  5. d = tf.constant([4, 5], name="d", dtype=tf.float32)
  6. result = a + b
  7. # 类型不匹配 会报错
  8. # result1 = a + c
  9. # 指定类型 dtype=tf.float32 正常运行
  10. result2 = a + d
  11. print (result)
  12. print (result2)
  13. sess = tf.InteractiveSession()
  14. print(result.eval())
  15. print(result2.eval())
  16. sess.close()
复制代码

[/code]

  1. [code]Tensor("add_2:0", shape=(2,), dtype=float32)
  2. Tensor("add_3:0", shape=(2,), dtype=float32)
  3. [3.  5.4]
  4. [5. 7.]
复制代码

[/code]
add_2:0 :说明 result 这个张量是输出节点‘add’输出的第 3 个结果,编号从 0 开始
3.3 Tensorflow 运行模型——会话
使用 Session 来执行定义好的运算,Session 拥有并管理 Tensorflow 程序运行时的所有资源,当所有计算完成之后需要关闭会话来帮助系统回收资源,否则就可能出现资源泄露的问题。
3.3.1 创建和关闭会话

  1. [code]# 创建一个会话。
  2. sess = tf.Session()
  3. # 使用会话得到之前计算的结果。
  4. print(sess.run(result))
  5. # 关闭会话使得本次运行中使用到的资源可以被释放。
  6. sess.close()
复制代码

[/code]

  1. [code][3.  5.4]
复制代码

[/code]
上面这种模式是,在所有计算完成之后,明确调用 Session.close() 函数来关闭会话,但是,若程序因异常而退出,Session.close() 函数可能就不会被执行到,从而导致资源泄露。
解决这个问题:则通过 Python 的上下文管理器 with 来使用 Session
3.3.2 使用 with statement 来创建会话

  1. [code]# 创建一个 Session ,并通过 Python 的上下文管理器 with 来管理 Session
  2. with tf.Session() as sess:
  3.     print(sess.run(result))
  4. # 不需要调用 sess.close() 函数,当上下文退出时,会话关闭和资源释放将会自用完成。
复制代码

[/code]

  1. [code][3.  5.4]
复制代码

[/code]
3.3.3 指定默认会话

  Tensorflow 会自动生成一个默认的计算图 (Graph),如果没有特殊指定,运算会加到这个默认的计算图中。
  Session 有类似的机制,但是 Tensorflow 不会自动生成默认的 Session ,需要 手动指定。
  tf.Tensor.eval() 可以用来计算一个张量的取值。

  1. [code]print(result)
  2. sess = tf.Session()3.3 指定默认会话
  3. with sess.as_default():
  4.     print(result)
  5.     print(result.eval())
复制代码

[/code]

  1. [code]Tensor("add_2:0", shape=(2,), dtype=float32)
  2. Tensor("add_2:0", shape=(2,), dtype=float32)
  3. [3.  5.4]
复制代码

[/code]

  1. [code]sess = tf.Session()
  2. # 下面的两个命令有相同的功能。
  3. print(sess.run(result))
  4. print(result.eval(session=sess))
  5. sess.close()
复制代码

[/code]

  1. [code][3.  5.4]
  2. [3.  5.4]
复制代码

[/code]
3.3.4 使用 tf.InteractiveSession 构建会话
在交互式环境下,(Python 脚本 或 jupyter notebook),通过设置默认的会话方式,可以更方便的获取张量的取值。

  1. [code]sess = tf.InteractiveSession()
  2. print(result.eval)
  3. print(result.eval())
  4. sess.close()
复制代码

[/code]

  1. [code]<bound method Tensor.eval of <tf.Tensor "add_2:0" shape=(2,) dtype=float32>>
  2. [3.  5.4]
复制代码

[/code]
3.3.5 通过 ConfigProto 配置会话 Session
之前都是使用的默认的 session 的配置,我们也可以通过 ConfigProto 对 session 进行特殊的配置,来实现不同的需求。

  1. [code]config = tf.ConfigProto(allow_soft_placement=True, log_device_placement=True)
  2. sess1 = tf.InteractiveSession(config=config)
  3. sess2 = tf.Session(config=config)
  4. sess1.close()
  5. sess2.close()
复制代码

[/code]

  通过 ConfigProto 可以配置并行的线程数,GPU 分配策略,运算超时时间等参数。
  allow_soft_placement=True 时(默认为False),以下三个条件成立时,GPU 运算可以放到 CPU 上运行。 

   
    运算无法在 GPU 执行 
    没有指定的 GPU 资源,1. 没有 GPU 2.指定第二个,实际上只有 1个
    运算输入包含对 CPU 计算结果的引用
   
  log_device_placement=True 时(默认为 False 减少日志量),为 True时,日志中会记录每个节点被安排在哪个设备上以方便调试。



3.4 Tensorflow 实现神经网络
3.4.1 Tensorflow 游乐场及神经原理简介
Tinker With a Neural Network in Your Browser.:http://playground.tensorflow.org
通过 Browser 可以训练简单的神经网络,并实现了可视化训练过程。
中间省略看原书。
使用神经网络解决分类问题主要步骤:

  提取问题中实体的特征向量作为神经网络的输入。
  定义神经网络的结构,并定义如何从神经网络的输入得到输出,也就是前向传播算法。
  通过训练数据来调整神经网络中参数的取值,也就是训练神经网络的过程。
  使用训练好的神经网络来预测未知的数据。

3.4.2 前向传播算法(Forward propogation)
介绍最简单的全连接网络结构的前向传播算法。略
3.4.3 三层简单神经网络

 


  1. [code]import tensorflow as tf
  2. # 1. 定义 w1, w2 两个变量,seed=1 设定随机种子
  3. # tf.random_normal 随机生成 2*3 大小的矩阵,服从正太分布 均值 mean,标准差 stddev = 1
  4. # 一定要注意矩阵的大小
  5. w1 = tf.Variable(tf.random_normal([2,3], stddev=1, seed=1))
  6. w2 = tf.Variable(tf.random_normal([3,1], stddev=1, seed=1))
  7. # 2. 将输入的特征向量定义为一个常量,x 维度(1,2)
  8. x = tf.constant([[0.7, 0.9]])
  9. # 3.定义前向传播算法的神经网络
  10. a = tf.matmul(x, w1)
  11. y = tf.matmul(a, w2)
  12. # 分别初始化 w1,w2 两个变量
  13. # 4.调用会话输出结果
  14. with tf.Session() as sess:
  15.     sess.run((w1.initializer, w2.initializer))
  16.     print(sess.run(y))
  17. # sess = tf.Session()
  18. # sess.run(w1.initializer)
  19. # sess.run(w2.initializer)
  20. # print(sess.run(y))
  21. # sess.close()
复制代码

[/code]

  1. [code]E:\ProgramData\Anaconda3\lib\site-packages\h5py\__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
  2.   from ._conv import register_converters as _register_converters
  3. [[3.957578]]
复制代码

[/code]
注意:
运行上面代码时,出现下面的错误:
InternalError: Blas GEMM launch failed : a.shape=(1, 2), b.shape=(2, 3), m=1, n=3, k=2 [[Node: MatMul = MatMul[T=DT_FLOAT, transpose_a=false, transpose_b=false, _device=”/job:localhost/replica:0/task:0/device:GPU:0”](Const, Variable/read)]]
解决方法:
最后发现是运行着多个 jupyter notebook ,在学习练习的过程中,没有及时关闭 session 导致,看到系统资源占用比高达 75%,然后 将没用的都关闭后,就降到了 23%。
多半是 session 用毕没有及时 close, 导致系统和 GPU 的很大部分被占用过却没有归还, 当前资源便不够了; 或是多个 session 争用 GPU.




  tf.random_normal 随机生成 2*3 大小的矩阵,服从正太分布 均值 mean,标准差 stddev 
  上面给 w1,w2 赋值时,使用的是 initializer ,当变量多的时候这样就会很麻烦,所以 以后可以使用 tf.global_variables_initializer() 函数来完成初始化所有变量的过程。 

  1. [code]w1 = tf.Variable(tf.random_normal([2,3], stddev=1, seed=1))
  2. w2 = tf.Variable(tf.random_normal([3,1], stddev=1, seed=1))
  3. top = tf.global_variables_initializer()
  4. with tf.Session() as sess:
  5.     sess.run(top)
  6.     print("w1:\n",w1.eval(),"\nw2:\n",w2.eval())
复制代码

[/code]

  1. [code]w1:
  2. [[-0.8113182   1.4845988   0.06532937]
  3. [-2.4427042   0.0992484   0.5912243 ]]
  4. w2:
  5. [[-0.8113182 ]
  6. [ 1.4845988 ]
  7. [ 0.06532937]]
复制代码

[/code]
3.4.4 通过 Tensorflow 训练神经网络模型

 


使用 placeholder:
首先,每生成一个常量,计算图就会增加一个节点,一般来说,一个神经网络训练过程会经过几百万轮甚至几亿轮的迭代。若都是常量的话,则计算图会非常的大,且利用率低。
所以使用 placeholder ,相当于定义一个位置,这个位置中的数据,在运行程序时再指定。其类型不可变,维度可变。

  1. feed_dict={x:[[0.7,0.9]]}
复制代码

feed_dict 喂给的输入数据,字典类型,再去指定 x 键,对应的值

  1. [code]# 定义 placeholder 作为存放输入数据的地方,必须指定类型,
  2. # 维度不一定要指定,但是,如果确定维度,可以避免出 bug
  3. x = tf.placeholder(tf.float32, shape=(1,2), name="input")
  4. a = tf.matmul(x, w1)
  5. y = tf.matmul(a, w2)
  6. with tf.Session() as sess:
  7.     sess.run(tf.global_variables_initializer())
  8.     # feed_dict 喂给的 输入数据
  9.     print(sess.run(y, feed_dict={x:[[0.7,0.9]]}))
复制代码

[/code]

  1. [code][[3.957578]]
复制代码

[/code]

  1. [code]"""
  2. 增加多个输入
  3. """
  4. x = tf.placeholder(tf.float32, shape=(3,2), name="input")
  5. a = tf.matmul(x, w1)
  6. y = tf.matmul(a, w2)
  7. with tf.Session() as sess:
  8.     sess.run(tf.global_variables_initializer())
  9.     print(sess.run(y, feed_dict={x:[[0.7,0.9],[0.1,0.4],[0.5,0.8]]}))
复制代码

[/code]

  1. [code][[3.957578 ]
  2. [1.1537654]
  3. [3.1674924]]
复制代码

[/code]
3.4.5 完整神经网络样例程序
在一个模拟数据集上训练神经网络,下面是一个完整的程序来训练神经网络解决二分类问题。

  1. [code]import tensorflow as tf
  2. # numpy 是一个科学计算的工具包,这里通过 numpy 工具包生成模拟数据集
  3. from numpy.random import RandomState
  4. # 定义训练数据 batch 的大小
  5. batch_size = 8
  6. # 定义神经网络的参数
  7. w1 = tf.Variable(tf.random_normal([2, 3], stddev=1, seed=1))
  8. w2 = tf.Variable(tf.random_normal([3, 1], stddev=1, seed=1))
  9. # 在 shape 的维度上使用 None 可以方便使用不大的 batch 的大小,在训练时把数据分成比较小的 batch
  10. # 将大量数据放进一个 batch 会导致内存溢出
  11. x = tf.placeholder(tf.float32, shape=(None, 2), name="x-input")
  12. y_ = tf.placeholder(tf.float32, shape=(None, 1), name="y-input")
  13. # 定义神经网络的前向传播过程
  14. a = tf.matmul(x, w1)
  15. y = tf.matmul(a, w2)
  16. y = tf.sigmoid(y)
  17. # 定义损失函数和反向传播算法
  18. cross_entropy = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y, 1e-10, 1.0))
  19.                                 + (1 - y_) * tf.log(tf.clip_by_value(1-y, 1e-10, 1.0)))
  20. train_step = tf.train.AdamOptimizer(0.001).minimize(cross_entropy)
  21. # 通过随机数生成一个模拟数据集
  22. rdm = RandomState(1)
  23. data_size = 128
  24. X = rdm.rand(data_size, 2)
  25. # 定义规则来给出样本的标签,x1 + x2 < 1 .为正样本 (1),其他为 负样本(0)
  26. Y = [[int(x1+x2 < 1)]  for (x1, x2) in X ]
  27. # 创建 Session 来运行 tf 程序
  28. with tf.Session() as sess:
  29.     # 初始化变量
  30.     sess.run(tf.global_variables_initializer())
  31.     # 输出目前(未经训练)的参数取值。
  32.     print(sess.run(w1))
  33.     print(sess.run(w2))
  34.     print("\n")
  35.     # 设定训练的 轮数
  36.     STEPS = 5000
  37.     for i in range(STEPS):
  38.         # 每次选取 batch_size 个样本进行训练
  39.         start = (i*batch_size) % data_size
  40.         end = (i*batch_size) % data_size + batch_size
  41.         # 通过选取的样本 训练神经网络,并更新参数
  42.         sess.run([train_step, y, y_], feed_dict={x:X[start:end], y_:Y[start:end]})
  43.         # 每隔一段时间,计算在所有数据上的交叉熵并输出
  44.         if i % 1000 ==0:
  45.             """
  46. 随着训练的进行,交叉熵是逐渐变小的,越小则越说明,
  47. 预测值与真实值之间的差距越小
  48. """
  49.             total_cross_entropy = sess.run(cross_entropy, feed_dict={x:X, y_:Y})
  50.             print("After %d training step(s), cross entropy on all data is %g" % (i, total_cross_entropy))
  51.     """
  52. 训练完后,神经网络参数的值,w1 ,w2 的值已经发生了变化,也就是训练的结果。
  53. 它使得这个神经网络可以更好的拟合提供的训练数据。具有更好的泛化能力。
  54. """
  55.     print("\n")
  56.     print(sess.run(w1))
  57.     print(sess.run(w2))   
复制代码

[/code]

  1. [code][[-0.8113182   1.4845988   0.06532937]
  2. [-2.4427042   0.0992484   0.5912243 ]]
  3. [[-0.8113182 ]
  4. [ 1.4845988 ]
  5. [ 0.06532937]]
  6. After 0 training step(s), cross entropy on all data is 1.89805
  7. After 1000 training step(s), cross entropy on all data is 0.655075
  8. After 2000 training step(s), cross entropy on all data is 0.626172
  9. After 3000 training step(s), cross entropy on all data is 0.615096
  10. After 4000 training step(s), cross entropy on all data is 0.610309
  11. [[ 0.02476974  0.56948686  1.6921943 ]
  12. [-2.1977353  -0.23668927  1.1143897 ]]
  13. [[-0.45544702]
  14. [ 0.49110925]
  15. [-0.98110336]]
复制代码

[/code]
总结:
训练神经网络的过程主要可以分成 三步:

  定义神经网络的结构和前向传播的输出结果
  定义损失函数以及选择反向传播优化的算法(常用优化算法如下)
   
    tf.train.GradientDescentOptimizer
    tf.train.AdamOptimizer
    tf.train.MomentumOptimizer
   
  定义 Session 并在训练数据上反复运行反向传播优化的算法。



补充知识点:

  batchsize:批大小。在深度学习中,一般采用 SGD 训练,即每次训练在训练集中取batchsize个样本训练;
  iteration:迭代,1 个 iteration 等于使用 batchsize 个样本训练一次;
  一个迭代 = 一个正向通过 + 一个反向通过
  epoch:迭代次数,1 个 epoch 等于使用训练集中的全部样本训练一次;
  一个epoch = 所有训练样本的一个正向传递和一个反向传递

举个例子,训练集有 1000 个样本,batchsize = 10,那么:
训练完整个样本集需要:
100次 iteration,1次 epoch。 

文章评论

程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
那些争议最大的编程观点
那些争议最大的编程观点
 程序员的样子
程序员的样子
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
老程序员的下场
老程序员的下场
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
“懒”出效率是程序员的美德
“懒”出效率是程序员的美德
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
程序员应该关注的一些事儿
程序员应该关注的一些事儿
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
我是如何打败拖延症的
我是如何打败拖延症的
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
漫画:程序员的工作
漫画:程序员的工作
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
Java程序员必看电影
Java程序员必看电影
总结2014中国互联网十大段子
总结2014中国互联网十大段子
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
要嫁就嫁程序猿—钱多话少死的早
要嫁就嫁程序猿—钱多话少死的早
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
10个调试和排错的小建议
10个调试和排错的小建议
为什么程序员都是夜猫子
为什么程序员都是夜猫子
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
中美印日四国程序员比较
中美印日四国程序员比较
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
一个程序员的时间管理
一个程序员的时间管理
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
每天工作4小时的程序员
每天工作4小时的程序员
代码女神横空出世
代码女神横空出世
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
2013年美国开发者薪资调查报告
2013年美国开发者薪资调查报告
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
如何成为一名黑客
如何成为一名黑客
那些性感的让人尖叫的程序员
那些性感的让人尖叫的程序员
Web开发者需具备的8个好习惯
Web开发者需具备的8个好习惯
程序员必看的十大电影
程序员必看的十大电影
程序员和编码员之间的区别
程序员和编码员之间的区别
Google伦敦新总部 犹如星级庄园
Google伦敦新总部 犹如星级庄园
编程语言是女人
编程语言是女人
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
程序员都该阅读的书
程序员都该阅读的书
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有