【TensorFlow】TensorFlow学习笔记(入门)

2018.2.4

1.计算图是tensorflow中最基本的概念,tensorflow中所有的计算都会被转化为计算图上的节点。

2.在tensorflow中,张量可以简单的被理解为多维数组。

3.TensorFlow是一个通过计算图的形式来表述计算的编程系统。TensorFlow中的每一个计算都是计算图上的一个节点,而节点之间的边描述了计算之间的依赖关系。

4.TensorFlow程序一般可分为两个阶段。第一阶段需要定义计算图中所有的计算,第二阶段为执行计算。

5.Python中一般采用“import tensorflow as tf”的形式来载入TensorFlow,可使程序更加简洁。在这个过程中,TensorFlow会自动将定义的计算转化为计算图上的节点,在程序中,系统会自动维护一个默认的计算图,通过 tf.get_default_graph 函数可以获取当前默认的计算图。

 

#通过a.graph可以查看张量所属的计算图
print(a.graph is tf.get_default_graph()) #输出应为True

6.除了使用默认的计算图,TensorFlow支持通过 tf.Graph 函数来生成新的计算图,不同计算图上的张量和运算都不会共享。

7.TensorFlow数据模型——张量。TensorFlow中,所有的数据都通过张量的形式来表示。从功能角度上看,可简单的被理解为多维数组。其中,零阶张量表示标量(scalar),也即一个数;一阶张量为向量(vector),也即一个一维数组;n阶张量可理解为一个n维数组。

8.Tensorflow的计算结果不是一个具体的数字,而是一个张量结构,一个张量中主要保存了三个属性:名称(name),维度(shape) 和类型 (type)

import tensorflow as tf
a = tf.constant([1.0,2.0],name = "a")
b = tf.constant([2.0,3.0],name = "b")
result = tf.add(a, b, name="add")
print(result)
输出:
Tensor("add:0", shape=(2,), dtype=float32)

名称:张量和计算图上节点所代表的计算结果是对应的,因此张量的命名可通过“node:src_output”的形式给出,其中node为节点名,src_output表示当前张量来自节点的第几个输出(编号从0开始)。
维度:shape=[m,n] 表示第一维有m个元素,第二维有n个元素,例:

# 2-D tensor `a`  
 a = tf.constant([1, 2, 3, 4, 5, 6], shape=[2, 3]) => [[1. 2. 3.]  
                                                       [4. 5. 6.]]  
 # 2-D tensor `b`  
 b = tf.constant([7, 8, 9, 10, 11, 12], shape=[3, 2]) => [[7. 8.]  
                                                          [9. 10.]  
                                                          [11. 12.]]  
  
 # 3-D tensor `a`  
 a = tf.constant(np.arange(1,13), shape=[2, 2, 3]) => [[[ 1.  2.  3.]  
                                                        [ 4.  5.  6.]],  
                                                       [[ 7.  8.  9.]  
                                                        [10. 11. 12.]]]  
  
 # 3-D tensor `b`  
 b = tf.constant(np.arange(13,25), shape=[2, 3, 2]) => [[[13. 14.]  
                                                         [15. 16.]  
                                                         [17. 18.]],  
                                                        [[19. 20.]  
                                                         [21. 22.]  
                                                         [23. 24.]]]  

类型:TensorFlow支持14种类型:实数(tf.float32、tf.float64)、整数(tf.int8、tf.int16、tf.int32、tf.int64、tf.uint8)、布尔型(tf.bool)、复数(tf.complex64、tf.complex128)。

 

 

 

 


 

2018.2.5

 

1.使用神经网络解决分类问题的步骤:

 (1)提取问题中实体的特征向量作为输入;

 (2)定义神经网络结构及如何从输入得到输出;

 (3)通过训练数据调整神经网络参数的取值,也即训练神经网络的过程;

 (4)使用训练好的神经网络来预测、未知的数据。

2.矩阵乘法功能的实现:tf.matmul() 函数

 

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


3.神经网络参数与TensorFlow变量

 

变量(tf.Variable)的作用就是保存和更新神经网络的参数。TensorFlow中的变量也需要指定初始值。因在神经网络中给参数赋予随机初始值最为常见,所以一般也使用随机数给TensorFlow中的变量初始化:

weights = tf.Variable(tf.random_normal([2, 3], stddev=2)) #产生一个2*3的矩阵,矩阵中的元素是均值为0,标准差为2的随机数。

        TensorFlow随机数生成函数

 

函数名随机数分布主要参数
tf.random_normal正态分布平均值、标准差、取值类型
tf.truncated_normal满足正态分布的随机值,但若随机值偏离平均值超过2个标准差,则这个数会被重新随机平均值、标准差、取值类型
tf.random_uniform平均分布最大、最小值、取值类型
tf.random_gammaGramma分布形状参数alpha、尺度参数beta、取值类型

TensorFlow也支持通过常数来初始化一个变量。

        TensorFlow常数生成函数

 

函数名功能示例
tf.zeros产生全0的数组tf.zeros([2, 3],tf.int32) -> [[0,0,0],[0,0,0]]
tf.ones产生全1的数组tf.ones([2, 3],tf.int32) -> [[1,1,1],[1,1,1]]
tf.fill产生一个全部为给定数组的数组tf.fill([2,3], 9) -> [[9,9,9],[9,9,9]]
tf.constant产生一个给定值的常量tf.constant([2,3,4]) -> [1,2,3]

 

在神经网络中,偏置项(bias)通常会使用常数来设置初始值:

biases = tf.Variable(tf.zeros([3]))

4.通过变量实现神经网络参数并实现前向传播的样例:

import tensorflow as tf

#声明w1,w2两个变量
#通过seed参数设定随机种子,保证每次运行得到的结果是一样的
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.constant([[0.7, 0.9]])

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

with tf.Session() as sess:
    #与以往的计算不同,这里不能直接通过sess.run(y)来获取y的值,
    #因为虽然在变量定义时给出了变量初始化的方法,但这个方法并没有被真正运行
    #也即w1,w2还没有运行初始化过程,下面进行初始化
    init = tf.global_variables_initializer()
    sess.run(init)
    print(sess.run(y))

 

 

2018.2.6

 

1.在一个计算图中,可以通过集合 (collection) 来管理不同类别的资源。如:通过tf.add_to_collection函数可以将资源加入一个或多个集合中,然后通过tf.get_collection 获取一个集合里面所有的资源。TensorFlow中自动管理了一些常用的集合:

集合名称集合内容使用场景
tf.GraphKeys.VARIABLES所有变量持久化TensorFlow模型
tf.GraphKeys.TRAINABLE_VARIABLES可学习的变量(一般指神经网络中的参数)模型训练、生成模型可视化内容
tf.GraphKeys.SUMMARIES日志生成相关的张量TensorFlow计算可视化
tf.GraphKeys.QUEUE_RUNNERS处理输入的QueueRunner输入处理
tf.GraphKeys.MOVING_AVERAGE_VARIABLES所有计算了滑动平均值的变量计算变量的滑动平均值

 

2.TensorFlow中的所有变量都会被自动加入 tf.GraphKeys.VARIABLES 集合中,通过tf.global_variables() 函数可以拿到当前计算图上的所有变量。拿到计算图上的所有变量有助于持久化整个计算图的运行状态。当构建机器学习模型时,比如神经网络,可以通过变量声明函数中的trainable 参数来区分需要优化的参数(比如神经网络的参数)和其他参数(比如迭代的轮数,即超参数),若trainable = True,则此变量会被加入 tf.GraphKeys.TRAINABLE_VARIABLES 集合。然后通过tf.trainiable_variables 函数便可得到所有需要优化的参数。TensorFlow中提供的优化算法会将tf.GraphKeys.TRAINABLE_VARIABLES 集合中的变量作为 默认的优化对象。


3.类似张量,维度(shape)和类型(type)也是变量最重要的两个属性。变量的类型是不可更改的,一个变量在构建后,类型就不能再改变了;但变量的维度是有可能更改的,需设置参数validate_shape = False,用法比较罕见。

 

 

 

2018.2.7

 

1.监督学习的重要思想就是,在已知答案的标注数据集上,模型给出的预测结果要尽量接近真实答案。通过调整神经网络中的参数对训练数据进行拟合,可以使得模型对未知的样本提供预测能力。

2.为了避免使用常量造成计算图节点增加、计算图庞大,TensorFlow提供了placeholder机制用于提供输入数据,它相当于定义了一个位置,这个位置的数据在程序运行时再指定。

3.目前TensorFlow支持7种优化器,比较常用的有三种:tf.train.GradientDescentOptimizer、tf.train.AdamOptimizer、tf.train.MomentumOptimizer。

4.解决二分类问题的完整神经网络样例:

# -*- coding: utf-8 -*-
"""
Spyder Editor

This is a temporary script file.
"""

import tensorflow as tf

#通过Numpy工具包生成模拟数据集
from numpy.random import RandomState

#定义训练数据batch的大小
batch_size = 8

#定义神经网络的参数及结构
w1 = tf.Variable(tf.random_normal([2,3], stddev=1, seed=1))
w2 = tf.Variable(tf.random_normal([3,1], stddev=1, seed=1))

#在shape上的一个维度使用None可以方便使用不同的batch大小。
#在训练时需要把数据分成比较小的batch,但在测试时,可以一次性使用全部数据。
#当数据集比较小时这样方便测试,但数据集比较大时可能导致内存溢出
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)

#定义损失函数和反向传播算法
cross_entrophy = -tf.reduce_mean(
        y_ * tf.log(tf.clip_by_value(y, 1e-10, 1.0)))
train_step = tf.train.AdamOptimizer(0.001).minimize(cross_entrophy)

#通过随机数生成一个模拟数据集
rdm = RandomState(1)
dataset_size = 128
X = rdm.rand(dataset_size, 2)
#定义规则来给出样本标签。在这里所有x1+x2<1的样例都被认为是正样本,而其他为负样本
#一般都会采用0表示负样本,1表示正样本
Y = [[int(x1+x2 < 1)] for (x1, x2) in X]


#创建一个会话来运行TensorFLow程序
with tf.Session() as sess:
    init_op = tf.global_variables_initializer()
    sess.run(init_op)
    print("训练之前w1的值为:")
    print(sess.run(w1))
    print("训练之前w2的值为:")
    print(sess.run(w2))
    
    #设定训练轮数
    STEPS = 5000
    for i in range(STEPS):
        #每次选取batch_size 个样本进行训练
        start = (i * batch_size) % dataset_size
        end = min(start + batch_size, dataset_size)
        
        #通过选取的样本训练神经网络并更新参数
        sess.run(train_step,
                 feed_dict={x:X[start:end], y_:Y[start:end]})
        
        if(i % 1000 == 0):
            #每隔一段时间计算所有数据上的交叉熵并输出
            tatol_cross_entrophy = sess.run(
                    cross_entrophy, feed_dict={x:X, y_:Y})
            print("After %d training step(s), cross_entrophy on all data is %g"%
                  (i, tatol_cross_entrophy))
    
    
    print("训练后w1的值为:")             
    print(sess.run(w1))
    print("训练后w2的值为:")
    print(sess.run(w2))

#输出结果为:

训练之前w1的值为:
[[-0.8113182   1.4845988   0.06532937]
 [-2.4427042   0.0992484   0.5912243 ]]
训练之前w2的值为:
[[-0.8113182 ]
 [ 1.4845988 ]
 [ 0.06532937]]
After 0 training step(s), cross_entrophy on all data is 0.0674925
After 1000 training step(s), cross_entrophy on all data is 0.0163385
After 2000 training step(s), cross_entrophy on all data is 0.00907547
After 3000 training step(s), cross_entrophy on all data is 0.00714436
After 4000 training step(s), cross_entrophy on all data is 0.00578471
训练后w1的值为:
[[-1.9618275  2.582354   1.6820377]
 [-3.4681718  1.0698231  2.11789  ]]
训练后w2的值为:
[[-1.824715 ]
 [ 2.6854665]
 [ 1.418195 ]]


5.训练神经网络的过程分为以下三个步骤:

(1)定义神经网络的结构和前向传播的输出结果;

(2)定义损失函数以及选择反向传播优化的算法;

(3)生成会话,并在训练数据上反复运行反向传播优化算法。

 

 

2018.2.8

 

1.深度学习是一类通过多层非线性变换对高复杂数据建模算法的集合。

2.如果一个问题可以通过一条直线来划分,那么线性模型也是可以用来解决这个问题的。

3.激活函数实现去线性化。如果将每一个神经元(也就是神经网络中的节点)的输出通过一个非线性函数,那么整个神经网络的模型也就不再是线性的了。这个非线性函数就是激活函数。几种常用的非线性激活函数:tf.sigmoid、tf.tanh、tf.nn.relu

 

4.异或运算直观来说就是如果两个输入的符号相同时则输出0,否则输出为1。

5.交叉熵(cross-entrophy)是判断一个输出向量和期望向量有多接近的评判方法之一。交叉熵刻画了两个概率分布之间的距离,是分类问题中使用较为广泛的一种损失函数。

p代表正确答案,q代表预测值。代码如下:

cross_entrophy = -tf.reduce_mean(
        y_ * tf.log(tf.clip_by_value(y, 1e-10, 1.0)))

tf.clip_by_value函数可以将一个张量中的数值限制在一个范围内;
tf.log函数完成了对张量种所有元素一次求对数的功能;
* ” 不是矩阵乘法,而是元素之间的直接相乘;
tf.reduce_mean函数计算整个矩阵的平均交叉熵,分类问题的类别数量不变,故而可以直接对整个矩阵做平均而不改变计算结果的意义。

6.神经网络的输出不一定是概率分布,而Softmax回归用来将神经网络前向传播得到的结果转变为概率分布。假设原始的神经网络输出为y₁,y₂,…,yn,那么经过Softmax回归处理后的输出为:

                                              

这个新的输出可以理解为经过神经网络的推导,一个样例为不同类别的概率分别是多大,这样就把神经网络的输出也变成了一个概率分布。因交叉熵一般会与softmax回归一起使用,所以TensorFlow对这两个功能进行统一封装,并提供了tf.nn.softmax_cross_entrophy_with_logits函数:

cross_entrophy = tf.nn.softmax_cross_entrophy_with_logits(y, y_)

在只有一个正确答案的分类问题中,TensorFlow还提供了tf.nn.sparse_softmax_cross_entrophy_with_logits函数来进一步加速计算过程。

7.与分类问题不同,回归问题解决的是对具体数值的预测,比如房价等。其最常用的损失函数是均方误差(MSE, mean squared error),定义如下:,代码如下:

mse = tf.reduce_mean(tf.square(y_, y))

8.自定义损失函数。

loss = tf.reduce_sum(tf.select(tf.greater(v1, v2),
                               (v1 - v2) * a, (v2 - v1) * b))

tf.greater函数输入的是两个张量,此函数会比较两个输入张量中每一个元素的大小,并返回比较结果;
tf.select函数有三个参数,第一个作为选择条件根据,当选择为True时,tf.select函数会选择第二个参数中的值,否则使用第三个参数中的值。

 

 

 

2018.2.10

 

 

1.关于MNIST数据集无法通过网络下载问题的解决:

(1)从http://yann.lecun.com/exdb/mnist/手动下载四个数据集,下载后不需要解压,把下载好的文件放到.py文件的同一个目录下,将代码修改为:

mnist = input_data.read_data_sets('./', one_hot = True)

 

2.为了加速训练过程,可以使用随机梯度下降算法(stochastic gradient descent),此算法优化的不是在全部训练数据上的损失函数,而是在每一轮迭代中,随机优化某一条训练数据上的损失函数。其问题也显然易见:在某一条数据上损失函数更小并不代表在全部数据上损失函数最小,因此又是甚至无法做到局部最优。  为了综合梯度下降和随机梯度下降的优缺点实际中一般采用——每次计算一小部分训练数据的损失函数(batch)。

 

3.学习率不能过大,也不能过小,TensorFlow提供了一种灵活的设置方法——指数衰减法。tf.train.exponential_decay函数实现了这个方法:

global_step = tf.Variable(0)    #初始化变量global_step

learning_rate = tf.train.exponential_decay(         #生成学习率
        LEARNING_RATE_BASE, global_step, DECAY_STEPS, LEARNING_RATE_DECAY, staircase=True)

#使用指数衰减的学习率,在minimize函数中传入global_step将自动更新global_step参数
#从而使学习率也得到相应的更新
learning_step = tf.train.GradientDescentOptimizer(learning_rate)\
                    .minimize(loss, global_step=global_step)

 

staircase的默认值为False,这时学习率随迭代轮数变化的趋势为平滑的曲线。当staircase值为True时学习率称为一个阶梯函数,这种设置的常用场景是每完整过一遍训练数据,学习率就减小一次,可以使得训练数据中的所有数据对模型训练有相等的作用。

 

4.正则化(regularization)——避免过拟合。常用的正则化函数有两种——L1、L2,基本思想都是通过限制权重的大小,使得模型不能任意拟合训练数据中的噪音。L1正则化会让参数变得稀疏(更多参数变成0),而L2不会。L1正则化计算公式不可导,而L2可导。tf.contrib.layers.l1_regularizertf.contrib.layers.l2_regularizer函数实现了两种方法:

loss = tf.reduce_mean(tf.square(y_ - y)) + 
        tf.contrib.layers.l2_regularizer(Lambda)(weight)

 

当神经网络的参数增多后这样的方法首先可能导致损失函数loss的定义很长,可读性差容易出错;但更主要的是,当网络结构复杂后定义网络结构的部分和计算损失函数的部分可能不在同一个函数中,这样通过变量这种方式计算损失函数就不方便了。为了解决这个问题,TensorFlow提供了集合(collection),它可以在一个计算图中保存一组实体(比如张量),以下代码给出了通过集合计算一个5层神经网络带L2正则化的损失函数的计算方法:

import tensorflow as tf

#获取一层神经网络边上的权重,并将这个权重的L2正则化损失加入名称为‘losses’的集合中
def get_weight(shape, klambda):
    #生成一个变量
    var = tf.Variable(tf.random_normal(shape), dtype = tf.float32)
    #tf.add_to_collection函数将这个新生成变量的L2正则化损失项加入集合
    tf.add_to_collection(
            'losses',tf.contrib.layers.l2_regularizer(klambda)(var))
    #返回生成的变量
    return var

x = tf.placeholder(tf.float32, shape=(None, 2))
y_ = tf.placeholder(tf.float32, shape=(None, 1))
batch_size = 8

#定义每一层网络中节点的个数
layer_dimension = [2, 10, 10, 10, 1]
#神经网络的层数
n_layers = len(layer_dimension)


#这个变量维护前向传播时最深层的节点,开始的时候就是输入层
cur_layer = x
#当前层的节点个数
in_dimension = layer_dimension[0]


#通过循环生成5层全连接的神经网络结构
for i in range(1, n_layers):
    out_dimension = layer_dimension[i]
    #生成当前层中权重的变量,并将这个变量的L2正则化损失加入计算图上的集合
    weight = get_weight([in_dimension, out_dimension], 0.001)
    bias = tf.Variable(tf.constant(0.1, shape=[out_dimension]))
    cur_layer = tf.nn.relu(tf.matmul(cur_layer, weight) + bias)
    in_dimension = layer_dimension[i]
    
#在定义神经网络前向传播的同时已经将所有的L2正则化损失加入了图上的集合
#在这里只需要计算刻画模型在训练数据上的损失函数    
mse_loss = tf.reduce_mean(tf.square(y_ - cur_layer))

#将均方误差损失函数加入损失集合
tf.add_to_collection('losses', mse_loss)

#get_collection返回一个列表,这个列表时所有这个集合中的元素。
#在这个样例中,这些元素就是损失函数的不同部分,将它们加起来即可得到最终的损失函数
loss = tf.add_n(tf.get_collection('losses'))

 

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

McGregorWwww

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值