TensorFlow学习笔记(1)----基础概念和程序的形式

TensorFlow学习笔记(1)----基础概念和程序的形式

1.概念

graph:图,表示具体的计算任务

session:会话,图需要在会话中执行,一个会话可以包含很多图
  • graph只是定义了计算,他本身不计算任何东西,他不保存任何值,他只是定义了你用代码所规定的操作

  • session允许计算图或者图的一部分,他为这个分配资源并且保存中间结果的值和变量

tensor:张量,在此表示数据,类型是numpy::ndarray
variable:就是本意变量,图的重要组成部分
operation:简称op,是图中计算的节点,输入tensor计算后产生tensor
feed、fetch:意思是给图添加数据和获取图中的数据,因为训练过程中有些数据需要动态获得、临时给予数据

1、tensor之———变量(variable)、常量(constant)、占位符(Placeholder)

  1. x = tf.Variable(a)  
其中a是一个numpy中类型的ndarray(所有的tensor都是),这里的a相当于对x进行了初始化。

(2)constant就是常量

[plain]  view plain  copy
  1. a = tf.constant([3.0, 3.0])  

(3)Placeholder

这个最能体现TensorFlow的优势,TensorFlow首先都是搭建一个图然后描述一下操作,而占位符就是先占住一个位置因为我们不知道输入的数量等一些具体信息,所以可以先大致的描述一下这一信息。

[plain]  view plain  copy
  1. x = tf.placeholder(tf.float32, [None, 784])  
因为我们不知道x的具体数量,所以可以用None来代替【None, 784】就是我不知道数量但是我知道它的维度为784。“float”是x的精度。

2、Session的简介

前面已经说过了Session就是一个会话,是用来运行一个图用的,按照 官方API 中的说法:一个Session的目标简单说就是operation(op)的执行和tensor的计算。例如一种最简单的op(常量乘法)的执行如下:
  1. # Build a graph(图).  
  2. a = tf.constant(5.0)
  3. b = tf.constant(6.0)
  4. c = a * b   # Launch the graph in a session.sess = tf.Session()# Evaluate the tensor `c`.print sess.run(c)  
  5. 一个Session可以拥有很多资源(resources),还可以有变量、队列和reader,所以每次运行完一个Session都要用.cloce()关闭会话,这有两种方法:  
  6. # 方法一   
  7. sess = tf.Session()  
  8. sess.run(...)  
  9. sess.close()  
  10.     
  11. # 方法2 
  12. with tf.Session() as sess:  
  13.   sess.run(...)  
这里我们需要知道,一个计算其实可以有很多graph的,所以我们的Session需要加载一个graph,而通常我们只是加载的默认graph。

3、Session中run的使用以及fetch和feed

上面我们用了一个Session的方法run(),这里详细的介绍一下run的使用方法。其作用是Runs operations and evaluates(评估 )tensors in fetches, 意思是执行一次Session,其中待执行的内容放在fetches中, 这里的fetches是一个有用的概念,在其他地方也用得到。目前暂时看成是一些待计算的内容。我们看一下run需要的参数:
[plain]  view plain  copy
  1. run(fetches,feed_dict=None,options=None,run_metadata=None)  
fetches可以是一个图中的element(元素),或者一些list、tuple、namedtuple, dict, or OrderedDict containing graph elements at its leaves,总之就是一般结构都可以。而这个element可以是下面几种类型:
**Operation,这时返回值是None
**Tensor,则返回计算得到的Tensor中包含的值
**SparseTensor,和上面的一样
**string,这时string为Operation或Tensor的名字,返回内容和上面一致。
接着介绍feed_dict,feed_dict允许override(重写)图中tensor的值,顾名思义feed_dict是一个字典,键是tensor的名字,值是重写的tensor的内容。通常用在Placeholder的实现上。
#!/usr/bin/python
# -*- coding: UTF-8 -*-

import tensorflow as tf
input1 = tf.constant(3.0)
input2 = tf.constant(2.0)
input3 = tf.constant(5.0)
intermed = tf.add(input2, input3)
mul = tf.multiply(input1, intermed)

with tf.Session() as sess:
    result = sess.run((mul, intermed))
    print  (result) # 结果  (21.0, 7.0)
    result = sess.run([mul, intermed])
    print(result)  # 结果  [21.0, 7.0]
    result = sess.run([intermed])
    print (result)  #  [7.0]
    result = sess.run(intermed)
    print (result)  #  7.0

运行结果:

(21.0, 7.0)
[21.0, 7.0]
[7.0]

7.0

4、tf.assign的用法

tf.assign(A, new_number): 这个函数的功能主要是把 new_number的值 赋值给A

例如:

import tensorflow as tf;

A = tf.Variable(tf.constant(0.0), dtype=tf.float32)
with tf.Session() as sess:
	sess.run(tf.initialize_all_variables())
	print sess.run(A)
	sess.run(tf.assign(A, 10))
	print sess.run(A)
输出:

0.0
10.0

开始给A赋值为0,经过tf.assign函数后,把A的值变为10


#!/usr/bin/python
# -*- coding: UTF-8 -*-

import tensorflow as tf

state = tf.Variable(0.0,dtype=tf.float32)
one = tf.constant(1.0,dtype=tf.float32)
new_val = tf.add(state, one)
update = tf.assign(state, new_val) #返回tensor, 值为new_val
update2 = tf.assign(state, 10000)  #没有fetch,便没有执行
init = tf.initialize_all_variables()
with tf.Session() as sess:
    sess.run(init)
    for _ in range(3):
        print (sess.run(update))

结果:

1.0
2.0
3.0

输出是1.0 , 2.0, 3.0,可以看出,tensorflow并没有计算整个图,只是计算了与想要fetch 的值相关的部分

import tensorflow as tf

state = tf.Variable(0.0,dtype=tf.float32)
one = tf.constant(1.0,dtype=tf.float32)
new_val = tf.add(state, one)
update = tf.assign(state, new_val) #返回tensor, 值为new_val
update2 = tf.assign(state, 10000)  #没有fetch,便没有执行
init = tf.initialize_all_variables()
with tf.Session() as sess:
    sess.run(init)
    for _ in range(3):
        # print (sess.run(update))
        print (sess.run(state))

结果:

0.0
0.0
0.0

5、sess.run() 中的feed_dict

我们都知道feed_dict的作用是给使用placeholder创建出来的tensor赋值。其实,他的作用更加广泛:feed_dict

使用一个 值临时替换一个 op 的输出结果. 你可以提供 feed_dict 数据作为 run() 调用的参数. feed_dict 只在调用它的方法内有效, 方法结束, feed_dict 就会消失.

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import tensorflow as tf
y = tf.Variable(1)
b = tf.identity(y)
with tf.Session() as sess:
    tf.global_variables_initializer().run()
    print(sess.run(b,feed_dict={y:3})) #使用3 替换掉
    print(sess.run(b, feed_dict={y: 8}))  # 使用3 替换掉
    #tf.Variable(1)的输出结果,所以打印出来3
    #feed_dict{y.name:3} 和上面写法等价
    print(sess.run(b))  #由于feed只在调用他的方法范围内有效,所以这个打印的结果是 1
    print(sess.run(b))

结果:

3
8
1
1


一、【TensorFlow】tf.nn.softmax_cross_entropy_with_logits的用法

在计算loss的时候,最常见的一句话就是tf.nn.softmax_cross_entropy_with_logits,那么它到底是怎么做的呢?

首先明确一点,loss是代价值,也就是我们要最小化的值

tf.nn.softmax_cross_entropy_with_logits(logits, labels, name=None)

除去name参数用以指定该操作的name,与方法有关的一共两个参数

第一个参数logits:就是神经网络最后一层的输出如果有batch的话,它的大小就是[batchsize,num_classes],单样本的话,大小就是num_classes

第二个参数labels:实际的标签,大小同上

具体的执行流程大概分为两步:

第一步是先对网络最后一层的输出做一个softmax,这一步通常是求取输出属于某一类的概率,对于单样本而言,输出就是一个num_classes大小的向量([Y1,Y2,Y3...]其中Y1,Y2,Y3...分别代表了是属于该类的概率)

softmax的公式是:


第二步是softmax的输出向量[Y1,Y2,Y3...]和样本的实际标签做一个交叉熵,公式如下:


其中指代实际的标签中第i个的值(用mnist数据举例,如果是3,那么标签是[0,0,0,1,0,0,0,0,0,0],除了第4个值为1,其他全为0)

就是softmax的输出向量[Y1,Y2,Y3...]中,第i个元素的值

显而易见,预测越准确,结果的值越小(别忘了前面还有负号),最后求一个平均,得到我们想要的loss

注意!!!这个函数的返回值并不是一个数,而是一个向量,如果要求交叉熵,我们要再做一步tf.reduce_sum操作,就是对向量里面所有元素求和,最后才得到,如果求loss,则要做一步tf.reduce_mean操作,对向量求均值!



import tensorflow as tf

# 导入mnist数据集
from tensorflow.examples.tutorials.mnist import input_data
mnist=input_data.read_data_sets("/temp/data/",one_hot=True)

# 定义一些常量
learning_rate=0.01
epoch_times=25
display_step=1

# 定义批量梯度下降次数,每100张图计算一次梯度
batch_size=100

# 定义X,Y大小  None代表第几张图,784=28*28,10 classes
# Y=[[1,0,0...,0],
#    [0,0,1...,0],
#    [0,1,0...,0],
#    [0,0,0...,1],
#    ...........]
X=tf.placeholder("float", [None,784])
Y=tf.placeholder("float", [None,10])

# 定义W,b大小
W=tf.Variable(tf.zeros([784,10]))
b=tf.Variable(tf.zeros([10]))

# matmul()矩阵相乘  ;multiply()实数相乘
# sigmoid将一个real value映射到(0,1)的区间(当然也可以是(-1,1)),这样可以用来做二分类。 
# softmax把一个k维的real value向量(a1,a2,a3,a4….)映射成一个(b1,b2,b3,b4….)
# 其中b是一个0-1的常数,然后可以根据bi的大小来进行多分类的任务,如取权重最大的一维。 

# 返回一个10维矩阵 
# 注意X,W前后顺序 [None,784]*[784,10]=[None,10]
pred=tf.nn.softmax(tf.matmul(X, W)+b)

# -Y*tf.log(pred):交叉熵代价函数 
# 代价函数接近于0.(比如Y=0,pred~0;Y=1,pred~1时,代价函数都接近0)
# 这里的*指对应下标的数相乘,不属于向量相乘,因此返回矩阵大小仍为[None,10]

# tf.reduce_sum(-Y*tf.log(pred),1): 
# 返回每个实例的交叉熵(向量),1代表从水平方向求和
# tf.reduce_mean():返回所有交叉熵的平均值(实数)
cost= tf.reduce_mean(tf.reduce_sum(-Y*tf.log(pred),1))

# 调用梯度下降函数
optimizer=tf.train.GradientDescentOptimizer(learning_rate).minimize(cost)

# 初始化参数方法
init=tf.global_variables_initializer()

# 运行参数初始化方法
sess=tf.Session()
sess.run(init)

for epoch in range(epoch_times):
    
    # 初始训练集误差为0
    train_cost=0
    
    # 批量梯度下降,返回总批量次数(55000/100=550)
    batch_numbers=int(mnist.train.num_examples/batch_size)
    
    for i in range(batch_numbers):
        
        # 每次取100张图片
        batch_Xs,batch_Ys=mnist.train.next_batch(batch_size)
        
        # 运行优化函数
        # 这里返回一个[optimizer,cost]的list, 其中 _代表optimizer,batch_cost代表cost的值
        _,batch_cost=sess.run([optimizer,cost],feed_dict={X:batch_Xs,Y:batch_Ys})
        
        # 等价于上面
        # sess.run(optimizer,feed_dict={X:batch_Xs,Y:batch_Ys})
        # batch_cost=sess.run(cost,feed_dict={X:batch_Xs,Y:batch_Ys})
        
        # 返回训练集误差:每次计算100张图的batch_cost,计算了i次,所以最后除以batch_numbers
        train_cost+=batch_cost/batch_numbers
      
    # 打印每次迭代的误差
    if (epoch+1)%display_step==0:
        
        # %04d: % 转义说明符 ; 0 指以0填充前面的位数 ;4 四位数; d 十进制整数
        # "{:.9f}".format(train_cost)  以保留小数点后9位显示train_cost
        print("Epoch :","%04d"%(epoch+1),"Train_cost","{:9f}".format(train_cost))
    
print("Optimization finished!")

# tf.arg_max(pred,1):得到向量中最大数的下标,1代表水平方向
# tf.equal():返回布尔值,相等返回1,否则0
# 最后返回大小[none,1]的向量,1所在位置为布尔类型数据
correct_prediction=tf.equal(tf.arg_max(pred,1),tf.arg_max(Y,1))

# tf.cast():将布尔型向量转换成浮点型向量
# tf.reduce_mean():求所有数的均值
# 返回正确率:也就是所有为1的数目占所有数目的比例
accuracy=tf.reduce_mean(tf.cast(correct_prediction,tf.float32))

# 打印正确率
print("Train_accuracy :",sess.run(accuracy,feed_dict={X:mnist.train.images,Y:mnist.train.labels}))
print("Test_accuracy :",sess.run(accuracy,feed_dict={X:mnist.test.images,Y:mnist.test.labels}))



Epoch : 0001 Train_cost  1.182139
Epoch : 0002 Train_cost  0.664811
Epoch : 0003 Train_cost  0.552634
Epoch : 0004 Train_cost  0.498518
Epoch : 0005 Train_cost  0.465431
Epoch : 0006 Train_cost  0.442534
Epoch : 0007 Train_cost  0.425447
Epoch : 0008 Train_cost  0.412136
Epoch : 0009 Train_cost  0.401330
Epoch : 0010 Train_cost  0.392388
Epoch : 0011 Train_cost  0.384719
Epoch : 0012 Train_cost  0.378171
Epoch : 0013 Train_cost  0.372416
Epoch : 0014 Train_cost  0.367238
Epoch : 0015 Train_cost  0.362694
Epoch : 0016 Train_cost  0.358609
Epoch : 0017 Train_cost  0.354874
Epoch : 0018 Train_cost  0.351399
Epoch : 0019 Train_cost  0.348344
Epoch : 0020 Train_cost  0.345431
Epoch : 0021 Train_cost  0.342731
Epoch : 0022 Train_cost  0.340269
Epoch : 0023 Train_cost  0.337952
Epoch : 0024 Train_cost  0.335766
Epoch : 0025 Train_cost  0.333705
Optimization finished!
Train_accuracy : 0.907927
Test_accuracy : 0.9146



Guess you like

Origin blog.csdn.net/liulina603/article/details/79722405