深度学习之Tensorflow
概要
Tensorflow是由谷歌公司Google Brain研发的深度学习框架,用于机器学习和深度神经网络方面的研究,后被广泛应用于其他计算领域。
2015年11月在GitHub上开源;2016年4月发布分布式版本;2017年发布1.0版本,趋于稳定。
Tensorflow相关链接
Tensorflow官网:
www.tensorflow.org
GitHub链接:
github.com/tensorflow/tensorflow
Tensorflow核心概念
Tensorflow是一个采用数据流图(data flow graphs),用于数值计算的开源软件。
数据流图用节点(nodes)和线(edges)的有向图来描述数学计算
- ‘节点’ 一般用来表示施加的数学计算,但也可以表示输入和输出。
- ‘线’ 表示 ‘节点’ 之间的输入输出关系。这些数据 ‘线’ 可以运输 ‘siz可动态调整’ 的多维数组,即‘张量’(tensor)
Tensorflow主要是由计算图、张量及模型会话三部分组成。
计算图
Tensorflow是通过计算图的形式来表述计算的编程系统,计算图也成为数据流图,在Tensorflow中需要构建一个计算图,按照计算图启动一个会话,在会话中完成变量赋值,计算得到最终结果。
计算图描述了数据计算流程,也负责维护和更新状态
![](https://img.haomeiwen.com/i15546936/47623fb8de3d1c02.png)
代码流程:
Import tensorflow as tf
b = tf.Variable(tf.zeros([100]))
W = tf.Variable(tf.random_uniform([784,100], -1, 1))
x = tf.placeholder(name=“x”)
relu = tf.nn.relu(tf.matmul(W, x) + b)
Cost = […]
Sess = tf.Session()
for step in range(0, 10):
input = …construct 100-D input array…
result = sess.run(cost, feed_dict={x: input})
print(step, result)
Tensorflow中的数据类型
1.张量
张量是Tensorflow的核心组件,所有运算和优化都是基于张量进行的。张量是基于向量和矩阵的推广,可以将标量看为零阶张量,矢量看做一阶张量,矩阵看做二阶张量。
注意:
1.张量三属性:名字,维度,类型
2.运算时维度和类型要保持一致
3.名字给出了张量的唯一标识符,同时给出变量是如何计算的
4.张量的计算和普通的计算是不同的,保存的不是数值而是计算过程
张量的作用:
1.对中间计算结果的引用,增加代码的可读性
2.计算图构造完成后,用来获得计算结果
demo:
import tensorflow as tf
#tf.constant():常量
a=tf.constant([1.0,2.0],name='a')
b=tf.constant([2.0,3.0],name='b')
#不管张量是直接加还是用tf.add方法都是一样的
result1=a+b
result2=tf.add(a,b,name='add')
print(result1)
print(result2)
2.tf.Variable()
简单的说在建立神经网络模型的时候,使用变量tf.Variable()类型,用来保存和更新神经网络中的参数
常用的常数生成函数
tf.oens()
tf.zeros()
tf.fill()
常用的随机数生成函数:
1. tf.random_normal() 正态分布随机函数
参数:
shape: 一维的张量,也是输出的张量
mean: 正态分布的均值
stddev: 正态分布的标准差
dtype: 输出的类型
seed: 一个整数,当设置之后,每次生成的随机数都一样
name: 操作的名字
2.tf.truncated_normal()截断正态分布随机函数
3.tf.random_uniform()均匀分布随机函数
demo:
import tensorflow as tf
a = tf.Variable(tf.random_normal([2,2],seed=1))
b = tf.Variable(tf.truncated_normal([2,2],seed=2))
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
print(sess.run(a))
print(sess.run(b))
输出:
[[-0.8113182 1.4845988 ]
[ 0.06532937 -2.4427042 ]]
[[-0.85811085 -0.19662298]
[ 0.13895045 -1.2212768 ]]
3.tf.placeholder()
在前面定义张量时,我们使用的是tf.constant().我们都知道神经网络的训练需要上千上万,甚至几百万的循环迭代,而每次循环迭代,每次生成一个常量,TensorFlow就会在计算图中增加一个节点,最后就会使得,图异常复杂.所以TensorFlow引入tf.placeholder机制.
tf.placeholder相当于提前为变量,定义,开拓了占位符,这个位置的数据在程序运行时被指定.也就是在计算图中,我们只有一个位置,这个位置的值会不断改变,这样就避免了重复生成.
定义placeholder需要三个参数
- dtype:类型,常用的是tf.float32,tf.float64等数值类型
- shape:形状,默认是None,就是一维值,也可以是多维,比如[2,3], [None, 3]表示列是3,行不定
- name:名字
demo:
import tensorflow as tf
import numpy as np
x = tf.placeholder(tf.float32, shape=(768, 768), name='x')
y = tf.matmul(x, x)
with tf.Session() as sess:
# print(sess.run(y)) # ERROR: 此处x还没有赋值.
rand_array = np.random.rand(768,768)
# feed_dict是一个字典,在字典中需要给出每一个用到的占位符的取值
print(sess.run(y, feed_dict={x: rand_array}))
会话(Session)
在TensorFlow中,使用会话(Session)来执行定义好的计算.会话拥有并管理TensorFlow中的所有资源,运行结束后,需要及时回收资源
方法一:
调用会话生成函数,然后关闭会话函数.
import tensorflow as tf
#tensorflow.Variable生成的变量,每次都会迭代更新
#这个也是我们要计算的结果,所以说你要计算什么是不是就把什么定义成变量
'''
tensorflow 可以通过tf.device函数来制定运行每一个操作的运行设备
这个设备可以是本地的CPU或者GPU,也可以是远程服务器
tensorflow会给每一个可用的设备一个名称,tf.device可以根据设备的名称来指定执行运算的设备
比如,CPU在tensorflow中的名称是/cpu:0
在默认情况下 即使机器有多个cpu,tensorflow也不会区分他们,所有的cup都会使用/cpu:0
而一台机器上不同的GPU名称是不同的,第N个GPU在tensorflow中的名称为/GPU:n
比如第一个GPU的名称为/gpu:0 第二个GPU的名称为/GPU:1
tensorflow提供了一个快捷方式,来查询每一个运行运算的设备
在生成回话的时候,可以通过设置log_device_placement参数来打印运行每一个运算的设备
除了可以看到最后的运算结果之外,还可以看到类似add:/job:localhost/replica:0/task:0/cpu:0 这样的输出
这些输出显示了执行每一个运算的设备比如加法操作是通过cpu运算的,因为他的设备中包含了/cpu:0
在配置好gpu环境的tensorflow中,如果操作没有明确的指定运行设备,那么tensorflow就会优先选择GPU
'''
with tf.device('/cpu:0'):
x=tf.Variable(3,name='x')
y=tf.Variable(4,name='y')
f=x*x*y+y+2
#创建一个计算图的上下文环境
session=tf.Session(config=tf.ConfigProto(log_device_placement=True))
#碰到session.run就会立刻去调用计算机
session.run(x.initializer)
session.run(y.initializer)
result=session.run(f)
print(result)
session.close()
方法二:
利用上下文管理器,来使用会话,自动释放资源.
import tensorflow as tf
x = tf.Variable(3, name='X')
y = tf.Variable(4, name='y')
f = x * x * y + y + 2
# 可以不分别对每个变量进行初始化
# 并不立即进行初始化,在run运行的时候进行初始化
init = tf.global_variables_initializer()
with tf.Session() as sess:
init.run()
result = f.eval()
print(result)
方法三:
交互式会话模式,尤其是在Ipython(Jupyter Notebook),这种交互式的环境中,使用非常方便.
import tensorflow as tf
x = tf.Variable(3, name='x')
y = tf.Variable(4, name='y')
f = x*x*y + y + 2
init = tf.global_variables_initializer()
# InteractiveSession和常规的Session不同在于,自动默认设置它自己为默认的session
# 即无需放在with块中了,但是这样需要自己来close session
sess = tf.InteractiveSession()
init.run()
result = f.eval()
print(result)
sess.close()
# TensorFlow程序会典型的分为两部分,第一部分是创建计算图,叫做构建阶段,
# 这一阶段通常建立表示机器学习模型的的计算图,和需要去训练模型的计算图,
# 第二部分是执行阶段,执行阶段通常运行Loop循环重复训练步骤,每一步训练小批量数据,
# 逐渐的改进模型参数
TensorFlow实现神经网络
demo:
import tensorflow as tf
my_mnist=input_data.read_data_sets("Mnist_data_bak/", one_hot=True)
print(my_mnist.train.images.shape,my_mnist.train.labels.shape)
print(my_mnist.test.images.shape,my_mnist.test.labels.shape)
print(my_mnist.validation.images.shape,my_mnist.validation.labels.shape)
# 输入的是一堆图片,None表示不限输入条数,784表示每张图片都是一个784个像素值的一维向量, 所以输入的矩阵是None乘以784二维矩阵
x = tf.placeholder(dtype=tf.float32, shape=(None, 784))
# 初始化都是0,二维矩阵784乘以10个W值
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))
print(b.shape)
print(W.shape)
y_pred = tf.nn.softmax(tf.matmul(x, tf.cast(W,tf.float32)) + tf.cast(b,tf.float32))
# 训练
# labels是每张图片都对应一个one-hot的10个值的向量
y = tf.placeholder(dtype=tf.float32, shape=(None, 10))
# 对于多分类问题,通常使用交叉熵损失函数
# reduction_indices等价于axis,指明按照每行加,还是按照每列加
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y * tf.log(y_pred), reduction_indices=[1]))
#GradientDescentOptimizer随机梯度下降法
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
#评估
# tf.argmax()是一个从tensor中寻找最大值的序号,tf.argmax 就是求各个预测的数字中概率最大的那一个值的下标
# axis = 0的时候返回每一列最大值的位置索引
# axis = 1的时候返回每一行最大值的位置索引
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_pred, 1))
# 用tf.cast将之前correct_prediction输出的bool值转换为float32,再求平均
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
#创建save节点
saver = tf.train.Saver()
n_epoch = 1000#迭代次数
sess = tf.InteractiveSession()
tf.global_variables_initializer().run()
for epoch in range(n_epoch):
if epoch % 100 == 0:
save_path = saver.save(sess, "./ckpt/my_model.ckpt", global_step=epoch)
batch_xs, batch_ys = my_mnist.train.next_batch(100)
sess.run(train_step, feed_dict={x: batch_xs, y: batch_ys})
print("TrainSet batch acc : %s " % accuracy.eval({x: batch_xs, y: batch_ys}))
print("ValidSet acc : %s" % accuracy.eval({x: my_mnist.validation.images, y: my_mnist.validation.labels}))
print("TrainSet batch loss : %s " % cross_entropy.eval({x: batch_xs, y: batch_ys}))
# best_theta = W.eval()
save_path = saver.save(sess, "./ckpt/my_model_final.ckpt")