tensorflow(1)

张量

张量可以说时Tensorflow的标志。因为整个框架的名称Tensorflow就是张量流的意思。

在tensorflow中把数据称为张量(tensor)。每个tensor包含了类型(type)、阶(rank)和形状(shape)。

tensor类型

下面把tensor类型和python的类型放在一起比较。

tensor阶

张量的阶:相当于数组的维度。 但张量的阶和矩阵的阶并不是同一个概念,主要是看有几层中括号。例如:对于一个传统的三阶矩阵a=[[1,2,3],[4,5,6],[7,8,9]]。在张量中的阶数表示为2阶(因为它有两层中括号)

tensor形状

shape用于描述张量内部的组织关系。“形状”可以通过Python中的整数列表或元祖来表示,也可以Tensorflow中的相关形状函数来表示。

举例:一个二阶张量a=[[1,2,3],[4,5,6]]形状是两行三列,描述为(2,3)。

tensorflow中张量形状分为动态形状和静态形状,其在于有没有生成一个新的张量数据。静态形状的修改不能跨维度修改

相关操作

张量的相关操作包括类型转换、数值操作、形状变换、数据操作。

类型转换

数值操作

tf.ones_like和tf.zeros_like的描述错了,应该分别生成1和0

形状变换

数据操作

算术运算函数

矩阵相关函数

规约计算

规约计算的操作都会有降维的功能,在所有reduce_xxx系列操作函数中,都是以xxx的手段降维,每个函数都有axis这个参数,即沿某个方向,使用xxx方法对输入的Tensor进行降维。

axis的默认值是None,即把input_tensor降到0维。即一个数。对于二维input_tensor而言,axis=0,则按列计算。axis=1,则按行计算。

tf.reduce_mean()

函数用于计算张量tensor沿着指定的数轴(tensor的某一维度)上的的平均值,主要用作降维或者计算tensor(图像)的平均值。

如果想设置为原来向量的维度,keep_dims=True。

分割

分割操作是tensorflow不常用的操作,在复杂的网络模型里偶尔才会用到。

整个程序的结构称为图(graph),可以把图看作一个计算任务。

一个Tensorflow程序默认是建立一个图的,除了系统自动建图外,还可以自主建图。

建立图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import tensorflow as tf
import numpy as np
c=tf.constant(0.0)
g=tf.Graph()
with g.as_default():
c1=tf.constant(0.0)
print(c1.graph)
print(g)
print(c.graph)

g2=tf.get_default_graph()
print(g2)

tf.reset_default_graph()
g3=tf.get_default_graph()
print(g3)

运行上面代码,得出结果如下:

c是刚开始的默认图中建立的,所以图的打印值就是原始的默认图的打印值。然后使用tf.Graph函数建立了一个图g,并且在新建的图里添加变量,可以通过变量的“.graph”获得所在的图。在新图g的作用域外,使用tf.get_default_graph又获得了原始的默认图,接着又使用tf.reset_default_graph函数,相当于重新建立一张图来代替原来的默认图。

注意:在使用tf.reset_default_graph函数时必须保证当前图的资源已经全部释放,否则会报错。

获取张量

在图里可以通过名字得到其对应的元素,例如get_tensor_by_name可以获得图里面的张量。在上面的代码的基础上加上下面这段代码:

1
2
3
4
5
6
7
8
print(c1.name)
t=g.get_tensor_by_name(name="Const":0)
print(t)


#运行结果
#Const:0
#Tensor("Const:0",shape=(),dtype=float32)

常量c1是在一个子图g中建立的。with tf.Graph()、as_default()代码表示使用tf.Graph函数来创建一个图,并在其上面定义op。

获取节点操作

获取节点操作op的方法是get_operation_by_name。

1
2
3
4
5
6
7
8
9
10
11
12
import tensorflow as tf
a=tf.constant([[1.0,2.0]])
b=tf.constant([[1.0],[3.0]])
tensor1=tf.matmul(a,b,name="exampleop")
print(tensor1.name,tensor1)
g3=tf.get_default_graph()
test=g3.get_tensor_by_name("exampleop:0")
print("test",test)

print(tensor1.op.name)
testop=g3.get_operation_by_name("exampleop")
print("testop",testop)

打印了一堆信息,看不懂。。。

获取元素列表

如果想看图中的全部元素,可以使用get_operations函数来实现。

1
2
tt2=g.get_operations()
print("所有的元素",tt2)

有多少个常量,就打印多少条信息。

获取对象

前面是根据名字来获取信息,还可以根据对象来获取对象。使用tf.Graph.as_graph_element(obj,allow_tensor=True,allow_operation=True)函数,即传入的是一个对象,返回一个张量或是一个op。

1
2
3
4
5
tt3=g.as_graph_element(c1)
print(tt3)

#输出内容
#Tensor("Const:0", shape=(), dtype=float32)

看上述代码对tt3的打印来看,变量tt3所指的张量名字为Const0。而在获取张量那小节可以看到量名c1所指向的真实张量名字也为Const0。这表明:函数as_graph_element获得了c1的真实张量对象,并赋给了变量tt3。

动态图(Eager)

动态图是相对于静态图而言的。所谓的动态图是指在Python中代码被调用后,其操作立即被执行的计算。其与静态图最大的区别是不需要使用session来建立会话了。即:在静态图中,需要在会话中调用run方法才可以获得某个张量的具体值,而在动态图中,直接运行就可以得到具体值。

动态图是在Tensorflow1.3版本之后出现的。启动动态图只需要在程序的最开始处加上两行代码

1
2
import tensorflow.contrib.eager as tfe
tfe.enable_eager_execution()

上面这两行代码的作用就是开启动态图计算功能。例如:调用tf.matmul时,将会立即计算两个数相乘的值,而不是op。

在创建动态图的过程中, 默认也建立了一个session。 所有的代码都在该session中进行, 而且该session具有进程相同的生命周期。 这表明一旦使用动态图就无法实现静态图中关闭session的功能。 这便是动态图的不足之处: 无法实现多
session操作。 如果当前代码只需要一个session来完成的话, 建议优先选择动态图Eager来实现

会话

运算程序的图称为会话(Session)。一次只能运行一个图

会话的作用:1、运行图的结构 2、分配资源运算 3、掌握资源

会话需要进行资源释放,需要run后进行close。否则可以使用with作为上下文管理器

可以在会话当中指定图去运行

sess.run(fetches,feed_dict=None,graph=None)启动整个图。

用来运行op和计算tensor

feed_dict常与placeholder(占位符)一起使用

变量:tensorflow中的变量也是一种op,是一种特殊的张量能够进行存储持久化,它的值就是张量,默认被训练。其中有个trainable参数默认为True,如果改为False,变量将不再变化。

图的可视化(tensorboard)

tensorflow提供了一个可视化工具TensorBoard,它可以把训练过程中的各种绘制数据展示出来,包括标量(Scalers)、图片(Images)、音频(Audio)、计算图(Graph)、数据分布、直方图(Histograms)和嵌入式向量。可以通过网页来观察模型的结构和训练过程中各个参数的变化。

当然,TensorBoard不会自动把代码展示出来,其实它是一个日志展示系统,需要在session中运算图时,将各种类型的数据汇总并输出到日志文件中。然后启动TensorBoard服务,TensorBoard读取这些日志文件,并开启6006端口提供web服务,让用户可以在浏览器中查看数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt

plotdata = { "batchsize":[], "loss":[] }
def moving_average(a, w=10):
if len(a) < w:
return a[:]
return [val if idx < w else sum(a[(idx-w):idx])/w for idx, val in enumerate(a)]

#生成模拟数据
train_X = np.linspace(-1, 1, 100)
train_Y = 2 * train_X + np.random.randn(*train_X.shape) * 0.3 # y=2x,但是加入了噪声
#图形显示
plt.plot(train_X, train_Y, 'ro', label='Original data')
plt.legend()
plt.show()

tf.reset_default_graph()

# 创建模型
# 占位符
X = tf.placeholder("float")
Y = tf.placeholder("float")
# 模型参数
W = tf.Variable(tf.random_normal([1]), name="weight")
b = tf.Variable(tf.zeros([1]), name="bias")

# 前向结构
z = tf.multiply(X, W)+ b
tf.summary.histogram('z',z)#将预测值以直方图显示
#反向优化
cost =tf.reduce_mean( tf.square(Y - z))
tf.summary.scalar('loss_function', cost)#将损失以标量显示
learning_rate = 0.01
optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost) #Gradient descent

# 初始化变量
init = tf.global_variables_initializer()
#参数设置
training_epochs = 20
display_step = 2

# 启动session
with tf.Session() as sess:
sess.run(init)

merged_summary_op = tf.summary.merge_all()#合并所有summary
#创建summary_writer,用于写文件
summary_writer = tf.summary.FileWriter('log/mnist_with_summaries',sess.graph)

# Fit all training data
for epoch in range(training_epochs):
for (x, y) in zip(train_X, train_Y):
sess.run(optimizer, feed_dict={X: x, Y: y})

#生成summary
summary_str = sess.run(merged_summary_op,feed_dict={X: x, Y: y});
summary_writer.add_summary(summary_str, epoch);#将summary 写入文件

#显示训练中的详细信息
if epoch % display_step == 0:
loss = sess.run(cost, feed_dict={X: train_X, Y:train_Y})
print ("Epoch:", epoch+1, "cost=", loss,"W=", sess.run(W), "b=", sess.run(b))
if not (loss == "NA" ):
plotdata["batchsize"].append(epoch)
plotdata["loss"].append(loss)

print (" Finished!")
print ("cost=", sess.run(cost, feed_dict={X: train_X, Y: train_Y}), "W=", sess.run(W), "b=", sess.run(b))
#print ("cost:",cost.eval({X: train_X, Y: train_Y}))

#图形显示
plt.plot(train_X, train_Y, 'ro', label='Original data')
plt.plot(train_X, sess.run(W) * train_X + sess.run(b), label='Fitted line')
plt.legend()
plt.show()

plotdata["avgloss"] = moving_average(plotdata["loss"])
plt.figure(1)
plt.subplot(211)
plt.plot(plotdata["batchsize"], plotdata["avgloss"], 'b--')
plt.xlabel('Minibatch number')
plt.ylabel('Loss')
plt.title('Minibatch run vs. Training loss')
plt.show()
print ("x=0.2,z=", sess.run(z, feed_dict={X: 0.2}))

运行上面代码显示的内容和以前一样没什么变化,在代码的同级目录下多了一个文件夹,里面还有个文件夹。文件夹内有个文件。首先在命令行下pip安装tensorboard,接着在这个文件的上级路径下,输入下面命令

双引号中间填绝对路径,注意不要出现中文和空格。

打开浏览器,输入 http://127.0.0.6006。会跳到以下界面,点击SCALARS,会看到之前创建的loss\_function。这个loss\_function也是可以点开的,点击loss\_function可以看到损失值随迭代次数的变化情况。还可以调节平滑数来改变右边标量的曲线。类似的还可以点击GRAPHS看看神经网络的内部结构,点击HISTOGRAMS看另一个显示值z。

注意:1、浏览器最好使用谷歌。2、在命令行里启动TensorBoard时,一定要先进入到日志所在的上级目录下,否则打开的页面找不到创建好的信息。

深度学习中的线性回归:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
train_x=np.linspace(-1,1,100)
train_y=2*train_x+np.random.randn(*train_x.shape)*0.3
#plt.plot(train_x,train_y,label="original data")
#plt.legend()
#plt.show()
X=tf.placeholder("float")
Y=tf.placeholder("float")
W=tf.Variable(tf.random_normal([1]),name="weight")
b=tf.Variable(tf.zeros([1]),name="bias")
z=tf.multiply(X,W)+b
cost=tf.reduce_mean(tf.square(Y-z))
learn_rate=0.005
optimizer=tf.train.GradientDescentOptimizer(learn_rate).minimize(cost)
init=tf.global_variables_initializer()
training_epochs=20
display_step=2
with tf.Session() as sess:
sess.run(init)
plotdata={"batchsize":[],"loss":[]}
for epoch in range(training_epochs):
for (x,y) in zip(train_x,train_y):
sess.run(optimizer,feed_dict={X:x,Y:y})
if epoch%display_step==0:
loss=sess.run(cost,feed_dict={X:train_x,Y:train_y})
print("Epoch:",epoch+1,"cost",loss,"W=",sess.run(W),"b=",sess.run(b))
if not (loss=="NA"):
plotdata["batchsize"].append(epoch)
plotdata["loss"].append(loss)
print("finish")
print("cost",sess.run(cost,feed_dict={X:train_x,Y:train_y}),"W=",sess.run(W),"b=",sess.run(b))

如果后面的几个数据的迭代得出的结果是一样的,那么证明该模型已经梯度下降到最低点。此时应该把学习率调小。

保存和载入模型

保存模型

首先需要建立一个saver,然后再session中通过saver的save即可将模型保存起来。

1
2
3
4
5
6
7
#生成saver
saver=tf.train.Saver()
with tf.Session() as sess:
#对模型初始化
sess.run(tf.global_variables_initializer())
#训练完后,使用saver.save进行保存
saver.save(sess,"save_path/file_name")

运行以上代码后,在代码的同级目录下,生成几个文件。如图:

载入模型

1
2
3
4
5
6
saver=tf.train.Saver()
with tf.Session() as sess:
#参数可以进行初始化,也可以不进行初始化。即使初始化了,初始化的值也会被restore函数值覆盖。
sess.run(tf.global_variable_initializer())
#会将已经保存的变量值restore到变量中
saver.restore(sess,"save_path/file_name")

保存模型的其它方法

Saver还可以指定存储变量名字与变量的对应关系

1
saver=tf.train.Saver({"weight":W,"bias":b})

上面这种写法代表将W变量的值放到weight名字中,类似的写法还有以下两种:

1
2
3
4
#放到一个list里
saver=tf.train.Saver([W,b])
#将op的名字当作key
saver=tf.train.Saver({v.op.name:v for v in [W,b]})

模型内容

虽然模型已经保存了,但是仍然对我们不透明。下面代码将模型内容打印出来,看看保存了那些东西

1
2
from tensorflow.python.tools.inspect_checkpoint import print_tensors_in_checkpoint_file
print_tensors_in_checkpoint_file("./save_path/model")

添加保存检查点

保存模型并不限于在训练之后,在训练之中也需要保存,因为tensorflow训练模型时难免会出现中断的情况。我们希望能够将幸苦得到的中间参数保留下来,否则下次又要重新开始。这种,在训练中保存模型,习惯上称为保存检查点。

​ PS:我感觉预训练模型和这个一样

此时用到saver的另一个参数,max_to_keep。表明最多只保存检查点文件的个数。

saver=tf.train.Saver(max_to_keep=1),代表在迭代过程中只保存一个文件。这样,在循环训练模型中,新生成的模型就会覆盖以前的模型。

下面两种方法可以快速获取到检查点文件:

1
2
3
4
5
6
7
8
#第一种
ckpt=tf.train.get_checkpoint_state(ckpt_dir)
if ckpt and ckpt.model_checkpoint_path:
saver.restore(sess,ckpt.model_checkpoint_path)
#第二种
kpt=tf.train.latest_checkpoint(savedir)
if kpt!=None:
saver.restore(sess,kpt)

----本文结束,感谢您的阅读。如有错,请指正。----
大哥大嫂过年好!支持我一下呗
0%