TensorFlow 基本概念与操作
计算图
除了默认图之外,TF支持通过tf.Graph来生成新的。
可以用来隔离张量,运算等
- 1234567891011121314# Get default graphtf.get_default_graph()g1 = tf.Graph()with g1.as_default():# Passwith tf.Session(graph=g1) as sess:tf.global_variables_initializer().run()with tf.variable_scope("name", resue=True):passwith g1.device('/gpu:0'):pass
|
|
|
- 12sess.run(tensor)tensor.eval(session=sess)功能一样
交互式会话,适合jupyter调试
tf.InteractiveSession()
该方法默认将生成的会话注册为默认会话无论哪种方法都可以通过ConfigProto Protocol Buffer来配置需要生成会话。 可以配置并行的线程数,GPU分配策略,运算超时时间。allow_soft_placement,用来配置GPU,true允许将GPU运算放在CPU算,log_device会记录每个节点在哪个设备上,来方便调试,生产环境可以设置为false
1234config = tf.ConfigProto(allow_soft_placement=True,log_device_placement=True)sess1 = tf.InteractiveSession(config=config)sess2 = tf.Session(config=config)
变量初始化
| Function | 随机分布 | 参数 |
| ——————- | ——————————- | ——————- |
| tf.random_normal | 正态分布 | mean, stddev, dtype |
| tf.truncated_normal | 正态分布,如果随机出来的值偏离平均值超过2个标准差,则重新随机 | |
| tf.random_uniform | 平均分布 | |
| tf.random_gamma | Gamma分布 | alpha, beta || Function | 功能 |
| ———– | ———- |
| tf.zeros | |
| tf.ones | |
| tf.fill | 全部为给定数值的数组 |
| tf.constant | 给定值常量 |通过其他变量来初始化
- W2 = tf.Variable(weights.initialized_value())
维度在运行中是可能改变的,但是需要设置参数validate_shape=False
W1 = 2, 3 w2 = 2, 2 tf.assign(w1, w2, validate_shape=False)
之所以使用placeholder而不用tf.constant,是因为constant每次需要生成一个节点插入到计算图中,而placeholder则只是一个节点,每次更新内容而已
如果选取batch_size的数据
1234start = (i*batch_size) % dataset_sizeend = min(start + batch_size, dataset_size)feed_dict={x:X[start:end], y_: Y[start:end]}
深层NN
单层的Perceptron不具有异或的学习能力(Perceptrons: An introduction to computational geometry),但是加了隐藏层就有了该能力。DNN具有组合特征提取的功能,这个特性对于不易提取特征向量的问题,比如图片识别,语音识别有很大的帮助。
经典损失函数
多分类问题:
判断一个输出向量和期望的向量有多接近呢?cross entropy刻画了俩个概率分布之间的距离。是分类问题中使用比较广的一种损失函数。
为什么多分类一般需要softmax? 因为cross entropy刻画的是概率分布之间的距离,而神经网络的输出却不一定是一个概率分布。softmax就是将输出转化为概率分布的函数。原始的神经网络的输出被用作置信度来生成新的输出。从交叉熵的公式可以看到其是不对称的,刻画的是通过概率分布q来表达p的困难程度。所以当交叉熵作为神经网络的损失函数时,P代表的是正确答案,q代表的是预测值。H(p, q)= -plog(q)
12H((1,0,0), (0.5,0.4,0.1)) = -(1*log0.5 + 0 + 0) = 0.3H((1,0,0), (0.8,0.1,0.1)) = 0.1因为交叉熵一般与softmax一起用,所以tensorflow提供了该函数封装
12tf.nn.softmax_cross_entropy_with_logits(y, y_) # y predict, y_ ground truthtf.nn.sparse_softmax_cross_entropy_with_logits 适用于只有一个正确答案
回归问题
回归问题一般只有一个输出节点,常用的Loss为均方误差。 MSE
1mse = tf.reduce_mean(tf.square(y_ - y))
自定义损失函数
有些时候需要根据问题自己去定义更加符合实际的损失函数,例如有些时候预测多了,比预测少了损失要小一些,这时用MSE就无法体现出多少的差别。
可以使用的函数有
1tf.reduce_sum(tf.select(tf.greater(v1, v2), func1, func2))tf.select和tf.greater都是element-wise operation
对于相同的神经网络不同的损失函数可以对训练得到的模型产生重要影响
优化算法
- GD vs SGD:
- GD 在全部数据集上更新, SGD只在一条数据上更新,一般使用折中, batch GD。
- GD vs SGD:
学习率
tf提供的学习率的设置方法: 指数衰减法。 tf.train.exponential_decay
123456tf.train.exponential_decay 实现了decayed_lr = lr * decay_rate^(global_step/ decay_step)decay_rate 衰减率 decay_step衰减速度,一般exponential_decay中如果staircase=False,衰减是连续的如果是True,则会对global/decay取整,导致整个学习率是阶梯状的。如果将decay_step设置为all/batch_size,则表示每过一轮全部数据,学习率衰减一次,那么表示每轮中的所有数据的贡献率是一致的(因为lr一致)- 12345global_step = tf.Variable(0)lr = tf.train.exponential_decay(0.1, global_step, 100, 0.96, staircase=True)# 使用指数衰减学习率,在mini传入global_step将自动更新global 参数, 从而使得学习率也得到相应的更新train_step = tf.train.GradientDescentOptimizer(lr).minimize(loss, global_step=global_step)
正则化
L1, L2, L2不会让参数稀疏的原因在于当参数很小的时候,比如0.001那么的它的平方基本上就可以忽略不计了。于是模型不会进一步将这个参数调整为0. 实践中也可以结合L1, L2同时使用
- 1234tf.contrib.layers.l2_regularizer(lambda, w)或者不使用contrib使用tf.nn.l2_lossregularizer = tf.nn.l2_loss(w)loss = tf.reduce_mean(loss + lambda * regularizer)
更加general的写法,尤其当网络定于与损失函数的定义不在同一个文件或者不在同一个函数中的时候,此时采用collection更加方便
123456789101112131415161718192021222324252627282930313233343536import tensorflow as tfdef get_weight(shape, lambda):var = tf.Variable(tf.random_normal(shape), dtype=tf.float32)#添加集合tf.add_to_collection('losses', tf.contrib.layers.l2_regularzier(labmda)(var))return varx = 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 = xin_dimension = layer_dimension[0]#循环构建网络for i in range(1, n_layers):out_dimension = layer_dimension[i]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]mse_loss = tf.reduce_mean(tf.square(y_ - cur_layer))#添加集合tf.add_to_collection('losses', mse_loss)#将所有损失相加loss = tf.add_n(tf.get_collection('losses'))
滑动平均模型
- 123tf.train.ExponentialMovingAverage# 提供decay, step, 维护一个shadown varialbeshadow_variable = decay * shadow_variable + (1-decay) * variable
从公式可以看到,decay越大模型越稳定。实际中,常取值0.999 或者 0.9999, 为了使模型在训练前期可以更新得更快, ExponentialMovingAverage还提供了num_updates参数来动态设置decay的大小, $min{decay, \cfrac{1+num_updates}{10+num_updates}}$
直接使用代码
1# todo