深入tensorflow1.x

夙愿已清 提交于 2020-02-07 00:22:35


目前所有的算法是基于1.12版本的tensorflow的实现,所以有必要学习一下1.x版本的tensorflow。

一、tensorflow 安装

基于tensorflow 1.4及以上
tensorflow的两个重要的依赖包:

  • protocol buffer:谷歌开发的结构化数据处理工具,例如json,xml等。
    • 主要的功能是把结构化的数据序列化进行网络传输或存储,然后把序列化的数据再反序列化为结构化数据。protocol buffer 需要定义数据的schema,利用schema来还原数据。使用 - protocol buffer序列化的数据比xml小3到10倍,反序列化时也快20到100倍。
    • tensorflow系统中的数据基本上都使用protocol buffer来组织的,分布式的tensorflow的通信协议也gRPC也是以protocol buffer为基础的。
  • bazel:谷歌开源的自动化构建工具,谷歌内部的绝大部分应用都是通过bazel构建的。功能类似于Maven等。

可以使用pip安装、docker安装及源码编译安装。

mac使用pip安装1.12.0版本的:
pip install --ignore-installed --upgrade https://storage.googleapis.com/tensorflow/mac/cpu/tensorflow-1.12.0-py3-none-any.whl

在这里插入图片描述

二、核心概念

  • 计算模型
  • 数据模型
  • 运行模型

2.1 计算图

Tensorflow计算的过程有两个阶段:首先是定义计算,定义的计算是作为计算图上的一个节点。在Tensorflow程序中,会维护自动维护一个计算图,可以通过tf.get_default_graph函数来获取默认的计算图。除了使用默认的计算图,Tensorflow还支持tf.Graph()来创建新的计算图。在不同的计算图中的张量和计算是不可以共享的。

# coding:utf-8
import tensorflow as tf

# 不同的计算图中的计算与张量是相互隔离的

# 创建一个计算图
g1 = tf.Graph()
# 在计算图中定义一个张量v
with g1.as_default():
    # 1.12版本把shape在initializer外边定义了
    v = tf.get_variable("v", initializer=tf.zeros_initializer(), shape=[1])

# 创建一个新的计算图
g2 = tf.Graph()
with g2.as_default():
    v1 = tf.get_variable("v", initializer=tf.ones_initializer(), shape=[1])

# 获取并输出g1中的张量v,结果是[0.]
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")))

# 获取并输出g2中的张量v,结果是[1.]
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")))

还可以指定计算图的设备,上一个计算两个常量的计算图:

with g.device("\gpu:0"):
	result = a + b

计算图另一个作用是管理Tensorflow中的资源,把资源放到collection中,可以使用tf.add_to_collection函数来把资源放到collection,tf.get_collection函数来获取collection中所有的资源。放入到collection中的可以是常量、变量或队列等资源。
为了管理方便,Tensorflow也自动维护了一些常用的集合。
在这里插入图片描述

2.2 Tensor

Tensorflow中的张量Tensor是数据管理的模型,有零阶张量(也就是标量),一阶张量可以理解为一维数组,n阶张量可以理解为n维数组。Tensorflow中的张量并不会保存数据,只保存计算过程,是计算结果的引用。有三个属性:name,shape和dtype。

  • name是node: src_output形式,node代表结点,src_output表示这个结点的第几个输出值。下面的例子result是来自add结点的第1个输出。
  • shape是张量的维度,是一个一维数组,这个数组的长度是2.
  • dtype是数据的type,浮点类型默认使用float32,整数默认是使用int32,使用默认类型容易出现类型不匹配的情况,所以一般会指定数据类型。
    在这里插入图片描述

张量的使用:

  • 是整个计算过程的引用,可以存储中间结果;
  • 可以用来计算真实的数值;

2.3 会话Session

Session拥有并且管理Tensorflow运行过程中的所有的资源。可以显示的打开Session,并关闭Session。另一种方法是使用上下文管理器with来管理。
当一个会话声明后,可以使用指定session的方法来计算一个Tensor

sess = tf.Session()
result.eval(session=sess)

2.4 两层神经网络

一个两层的神经网络:
在这里插入图片描述
这个一个由输入层,隐藏层、输出层组成的典型的两层神经网络。使用向量的形式:
在这里插入图片描述
参数W的维度是input×outputinput \times output。x的组织形式与Andrew ng的课中的组织形式是不同的,一行代表一个样本,一个样本有两个特征,所以x的维度是一行二列。

a = tf.matmul(x, W1)
y = tf.matmul(a, W2)
# 声明一个二行三列的变量,使用正态分布的对变量初始化
weight = tf.Variable(tf.random_normal([2,3], stddev=2))

在这里插入图片描述
在这里插入图片描述
两层神经网络的前向传播:

# coding=utf-8

import tensorflow as tf

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是一行两列的矩阵
x = tf.constant([[0.7, 0.9]])

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

with tf.Session() as sess:
    # 对变量执行初始化
    # sess.run(w1.initializer)
    # sess.run(w2.initializer)
    # 下面是对所有的变量进行初始化,而不是对每个变量单独执行
    tf.global_variables_initializer().run()
    print(sess.run(y))

可以通过tf.global_variables()来获取计算图上的所有变量,对持久化计算图的运行状态有帮助。

为什么要用placeholder?
训练一个神经网络需要进行很多轮的迭代,如果每次使用常量时,则会生成百万个的节点,占用很多的资源。而placeholder是占位的意思,先把计算图上位置占住,当用session计算的时候再把数据值传入。

# coding:utf-8
import warnings

warnings.filterwarnings('ignore')
import tensorflow as tf
import numpy as np
from numpy.random import RandomState

# 生成训练数据
datasize = 128
# 定义批大小
batch_size = 8

rdm = RandomState(1)
X = rdm.random([datasize, 2])
print(X.shape)
Y = np.array([[int(x1 + x2 > 1)] for (x1, x2) in X])
print(Y.shape)

# 定义placeholder
x = tf.placeholder(dtype=tf.float32, shape=(None, 2), name='x-input')
y_ = tf.placeholder(dtype=tf.float32, shape=(None, 1), name='y-input')
# 定义参数
w1 = tf.Variable(initial_value=tf.random_normal(shape=(2, 3), stddev=1, seed=1))
w2 = tf.Variable(initial_value=tf.random_normal(shape=(3, 1), stddev=1, seed=1))
# 定义模型
a = tf.matmul(x, w1)
y_pred = tf.sigmoid(tf.matmul(a, w2))

# 定义loss
cross_entropy = -tf.reduce_mean(
    y_ * tf.log(tf.clip_by_value(y_pred, 1e-10, 1.0)) + (1 - y_) * tf.log(tf.clip_by_value(1 - y_pred, 1e-10, 1.0)))

# 向后传播
learning_rate = 0.001
train_step = tf.train.GradientDescentOptimizer(learning_rate=learning_rate).minimize(cross_entropy)

# 开始迭代
STEMPS = 5000

with tf.Session() as sess:
    # 在迭代之前初始化所有的数据
    tf.global_variables_initializer().run()
    print('before loop w1:{}'.format(sess.run(w1)))
    print('before loop w2:{}'.format(sess.run(w2)))

    for i in range(STEMPS):
        start = i * batch_size % datasize
        # 当datasize无法整除batch_size时,end只能取到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:
            # 计算在全部训练数据上的cross entropy
            print(f'After loop {i}, cross entropy loss is:{sess.run(cross_entropy, feed_dict={x: X, y_: Y})}')
    print('after loop w1:{}'.format(sess.run(w1)))
    print('after loop w2:{}'.format(sess.run(w2)))

三、深层神经网络

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!