Tensorflow实战Google深度学习框架 第1-3章总结

Tensorflow实战Google深度学习框架

第1章 深度学习简介

  • 深度学习在NLP上的应用:
    1.语言模型 2.机器翻译 3.词性标注 4.实体识别 5.情感分析 6.广告推荐 7.搜索排序

  • 语料库:
    WordNet, ConceptNet, FrameNet
    概念:将我们平时说的句子,一些文学作品的语句段落,报刊杂志上出现过的语句段落等在现实生活中真实出现过的语言材料整理在一起,形成一个语料库,以便在做研究时可以从中取材获得到数据佐证。
    特点:语料库中存放的是在语言的实际使用中真实出现过的语言材料;语料库是以电子计算机为载体承载语言知识的基础资源;真实语料需要经过加工(分析和处理),才能成为有用的资源。

第2章 Tensorflow环境搭建

  • Tensorflow主要依赖包:
    Protocol Buffer, Bazel

  • Protocol Buffer
    处理结构化数据的工具
    结构化数据:拥有多种属性的数据
    ‘name’ : ‘Tom’,
    ‘id’ : 1234
    ‘email’ : ‘1234@qq.com’
    上面的用户信息就是一个结构化数据。要将结构化持久化或者进行网络传输时,需要将它们先序列化。序列化是将结构化的数据变成数据流的格式,简单地说就是变成一个字符串。将结构化的数据序列化,并从序列化之后的数据流中还原出原来的结构化数据,通称为处理结构化数据。这就是Protocol Buffer解决的主要问题。
    除Protocol Buffer外,XML, JSON是两种比较常用的结构化数据处理工具,比如上面的用户信息使用XML格式表达,那么数据的格式为:
    XML格式:
    <user>
    ‘name’ : ‘Tom’,
    ‘id’ : 1234
    ‘email’ : ‘1234@qq.com’
    </user>
    JSON格式:
    {
    ‘name’ : ‘Tom’,
    ‘id’ : 1234
    ‘email’ : ‘1234@qq.com’
    }
    Protocol Buffer格式的数据和XML或者JSON格式的数据有比较大的差别。首先,Protocol Buffer序列化之后得到的数据不是可读的字符串,而是二进制流。其次,XML或者JSON格式的数据信息都包含在了序列化之后的数据中,不需要任何其他信息就能还原序列化之后的数据。但使用Protocol Buffer时需要先定义数据的格式。还原一个序列化之后的数据将需要使用到这个定义好的数据格式。以下代码是上面用户信息样例的数据格式定义文件。因为这样的差别,Protocol Buffer序列化出来的数据要比XML或者JSON格式的数据小3到10倍,解析时间要快到20-100倍
    message user{
    optional string name = 1;
    required int32 id = 2;
    repeated string email = 3;
    }
    Protocol Buffer定义的数据格式的文件一般保存在.proto文件中。每一个message代表了一类结构化的数据。message中定义了每一个属性的类型和名字。在message中,Protocol Buffer定义了一个属性是必需的(required)还是可选的(optional)或者是可重复的(repeated)。

  • Bazel
    Bazel是从Google开源的自动化构建工具,谷歌内部绝大部分的应用都是通过它来编译的。
    项目空间是Bazel的一个基本概念。一个项目框架可以简单的理解为一个文件夹,在这个文件夹中包含了编译一个软件所需要的源代码以及输出编译结果的软连接地址。一个项目空间可以包含一个或多个应用。一个项目空间所对应的文件夹是这个项目的根目录,在这个根目录中需要有一个WORKSPACE文件,此文件定义了对外部资源的依赖关系。
    在一个项目空间内,Bazel通过BUILD文件来找到需要编译的目标。Bazel的编译方式是事先定义好的。Bazel对Python支持的编译方式只有三种:py_binary, py_library, py_test. 其中py_binary将Python程序编译为可执行文件,py_test编译Python测试程序,py_library将Python程序编译成库函数供其他py_binary或py_test调用。
    BUILD文件是由一系列编译目标组成的。定义编译目标的先后顺序不会影响编译结果。

第3章 Tensorflow入门

核心概念

  • Tensorflow中的计算可以表示为一个有向图,其中每一个运算操作将作为一个节点,节点与节点之间的连接称为边。这个计算图描述了数据的计算流程,它也负责维护和更新状态,用户可以对计算图的分支进行条件控制或循环操作。计算图中每一个节点可以有任意多个输入和任意多个输出,每一个节点描述了一种运算操作,节点可以算是运算操作的实例化。在计算图的边中流动的数据被称为张量(tensor),而tensor的数据类型,可以是事先定义的,也可以根据计算图的结构推断得到的。有一类特殊的边中没有数据流动,这种边是依赖控制,作用是让他的起始节点执行完之后再执行目标节点,用户可以使用这样的边进行灵活的条件控制,比如限制内存使用的最高峰值。

  • Tensorflow程序一般分为两个阶段。第一个阶段需要定义计算图中所有的计算;第二阶段为执行阶段。

# 定义阶段,这个过程中,TensorFlow会自动将定义的计算转化为计算图上的节点
import tensorflow as tf
a = tf.constant([1, 2], name = 'a')
b = tf.constant([3, 4], name = 'b')
result = a + b
# 执行阶段
with tf.Session() as sess:
    print(sess.run(result))
  • 在Tensorflow中,系统会维护一个默认的计算图,通过tf.get_default_graph函数可以获取当前默认的计算图
# 通过a.graph可以查看张量所属的计算图,如果没有特定指定,张量的计算图属于默认的计算图
print(a.graph is tf.get_default_graph())   # True
  • 除了使用默认的计算图,TensorFlow支持通过tf.Graph()函数来生成新的计算图,不同计算图上的张量和运算都不会共享。
import tensorflow as tf

g1 = tf.Graph()   # 定义g1计算图
with g1.as_default():
    # 在计算图g1中定义变量'v',并设置初始值0
    v = tf.get_variable('v', shape=[1], initializer=tf.zeros_initializer())

g2 = tf.Graph()    # 定义g2计算图
with g2.as_default():
    # 在计算图g1中定义变量'v',并设置初始值1
    v = tf.get_variable('v', shape=[1], initializer=tf.ones_initializer())


# 在计算图g1中读取变量'v'的值
with tf.Session(graph=g1) as sess:
    tf.global_variables_initializer().run()
    with tf.variable_scope('', reuse=True):
        print(sess.run(tf.get_variable('v')))   # 输出[0.]

# 在计算图g2中读取变量'v'的值        
with tf.Session(graph=g2) as sess:
    tf.global_variables_initializer().run()
    with tf.variable_scope('', reuse=True):
        print(sess.run(tf.get_variable('v')))   # 输出[1.]

with tf.Session(graph=g1) as sess:
    tf.global_variables_initializer().run()
    with tf.variable_scope('zyy'):
        v = tf.get_variable('v', [1])
    with tf.variable_scope('zyy', reuse=True):
        vv = tf.get_variable('v', [1])
    print(v == vv)   # 输出True
    with tf.variable_scope('zyy', reuse=True, initializer=tf.zeros_initializer()):
        vvv = tf.get_variable('v', [1])
    print(vv == vvv)   # 输出True

    with tf.variable_scope('zyy'):
        v = tf.get_variable('k', [2, 3], initializer=tf.random_normal_initializer(mean=0, stddev=1))

TensorFlow计算模型——张量

张量的概念
  • 所有数据都通过张量的形式来表示。从功能的角度上看,张量可以被简单理解为多维数组。其中零阶张量表示标量,也就是一个数;一阶张量表示向量,也就是一个数组;n阶张量可以理解为一个n维数组。

  • 张量在TensorFlow中的实现并不是直接采用数组的形式,它只是TensorFlow中的运算结果的引用。在张量中并没有真正保存数字,它保存的是如何得到这些数字的计算过程。

import tensorflow as tf
a = tf.constant([1, 2], name = 'a')
b = tf.constant([3, 4], name = 'b')
result = a + b
print(result)
# 输出:Tensor('add:0', shape=(2,), dtype=int32
# 得到的是对结果的一个引用,是一个张量结构。主要保存了三个属性:名字、维度、类型
张量的使用
  1. 对中间计算结果的引用
  2. 当计算图构造完成之后,使用张量获得计算结果

TensorFlow运行模型——会话

  • 会话拥有并管理TensorFlow程序运行时的所有资源。所有计算完成之后需要关闭会话来帮助系统回收资源,否则就可能出现资源泄露的问题。
# 第一种
sess = tf.Session()
sess.run(...)
sess.close()
# 第二种
with tf.Session() as sess:
    sess.run(...)
  • TensorFlow不会自动生成默认的会话,而是需要手动指定。当默认的会话被指定之后可以通过tf.Tensor.eval函数来计算一个张量的取值
sess = tf.Session()
with sess.as_default():
    print(result.eval())
# 以下代码与上面代码有同样功能
with tf.Session() as sess:
    print(sess.run(result))
    # print(result.eval(session = sess))
  • 通过设置默认会话的方式来获取张量的取值更加方便。
sess = tf.InteractiveSession()
print(result.eval())
sess.close()

Tensorflow——变量

  • tf.Variable(tf.random_normal([2, 3], stddev=2))

  • TensorFlow支持随机数生成函数和常数生成函数

  • tf.global_variables_initializer().run() # 初始化所有变量

  • 在TensorFlow中,变量的声明函数tf.Variable是一个运算。这个运算的输出结果就是一个张量。

  • Tensorflow中集合(collection):所有的变量都会被自动地加入到GraphKeys.VARIABLES这个集合中。通过tf.global.variables()函数可以拿到当前计算图上所有变量。拿到计算图上所有的变量有助于持久化整个计算图的运行状态。当构建机器学习模型时,如神经网络,可以通过变量声明函数中的trainable参数来区分需要优化的参数和其他参数。如果声明变量是参数trainable为True,那么这个变量将会被加入到GraphKeys.TRAINABLE_VARIABLES集合。在Tensorflow中可以通过tf.trainable_variables函数得到所有需要优化的参数。

  • 一个变量在构建之后,他的类型不会改变,但是维度在程序运行过程中可以改变,通过设置参数validate_shape=False

w1 = tf.Variable(tf.random_normal((2, 3), stddev=1, seed=1))
w2 = tf.Variable(tf.random_normal((3, 1), stddev=1, seed=1))
tf.assign(w1, w2, validate=False)

Tensorflow——placeholder

  • Tensorflow提供了placeholder机制用于提供输入数据。placeholder相当于定义了一个位置,这个位置中的数据在程序运行时再指定。这样在程序中就不需要生成大量的常量来提供输入数据,而只需要将数据通过placeholder传入TensorFlow计算图。在placeholder定义时,这个位置上的数据类型是需要指定的,和其他张量一样,placeholder的类型也是不可以改变的。placeholder中数据维度信息可以根据提供的数据推导得出,所以不一定要给出。
w1 = tf.Variable(tf.random_normal((2, 3), stddev=1, seed=1))
w2 = tf.Variable(tf.random_normal((3, 1), stddev=1, seed=1))

x = tf.placeholder(tf.float32, shape=(None, 2), name='x_input')

a = tf.matmul(x, w1)
y = tf.matmul(a, w2)

sess = tf.Session()
tf.global_variable_initializer().run()
sess.run(y, feed_dict={x : [[0.7, 0.9]]})

在这段程序中替换了原来通过常量定义的输入x。需要提供一个feed_dict来指定x的取值,feed_dict是一个字典,在字典中需要给出每个用到的placeholder取值。

完整神经网络样例程序

'''
训练一个完整的神经网络
'''
from numpy.random import RandomState
import tensorflow as tf
batch_size = 8
learningRate = 0.001

w1 = tf.Variable(tf.random_normal((2, 3), stddev=1, seed=1))
w2 = tf.Variable(tf.random_normal((3, 1), stddev=1, seed=1))

x = tf.placeholder(tf.float32, shape=(None, 2), name='x_input')
y_ = tf.placeholder(tf.float32, shape=(None, 1), name='y_input')

a = tf.matmul(x, w1)
y = tf.matmul(a, w2)

y = tf.sigmoid(y)

cross_entropy = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y, 1e-10, 1.0)) + (1-y_) * tf.log(tf.clip_by_value(1-y, 1e-10, 1.0)))
train_step = tf.train.AdamOptimizer(learningRate).minimize(cross_entropy)

rdm = RandomState(1)
dataSize = 128
X = rdm.rand(dataSize, 2)
Y = [[int(x1+x2<1)] for (x1, x2) in X]

with tf.Session() as sess:
    init_op = tf.global_variables_initializer()
    sess.run(init_op)

    print(sess.run(w1))
    print(sess.run(w2))

    step = 5000
    for i in range(step):
        start = (i * batch_size) % dataSize
        end = min(start+batch_size, dataSize)

        sess.run(train_step, feed_dict={x:X[start:end], y_:Y[start:end]})

        if i % 1000 == 0:
            total_cross_entropy = sess.run(cross_entropy, feed_dict={x:X, y_:Y})
            print('After %d training step(s),cross entropy on all data is %g' % (i, total_cross_entropy))


    print(sess.run(w1))
    print(sess.run(w2))

训练神经网络的过程:
1. 定义神经网络的结构和前向传播的输出结果
2. 定义损失函数以及选择反向传播优化算法
3. 生成会话(tf.Session())并且在训练数据上反复运行反向传播优化算法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值