美文网首页
TensorFlow 深度学习基本概念

TensorFlow 深度学习基本概念

作者: 音符纸飞机 | 来源:发表于2018-12-25 00:21 被阅读25次

1. 深度学习

特性:

  • 多层:单层神经网络其实就是感知机(1958年由Frank Rosenblatt提出),感知机的最大问题在于无法解决异或问题。
  • 非线性:线性模型不管有多少层,其实和单层没有区别,本质还是线性模型,因为线性模型的最大特点是任意线性模型的组合任然是线性模型。节点的激活函数(在线性函数外面又包了一层的函数)决定了模型是否是线性的。常用的非线性模型有ReLU、sigmoid、tanh。
    ReLU: f(x) = max(x, 0)
    sigmoid: f(x) = \frac{1}{1+e^{-x}}
    tanh: f(x) = \frac{1-e^{-2x}}{1+e^{-2x}}
非线性模型
a = tf.nn.relu(tf.matmul(x, w1) + biases1)
y = tf.nn.relu(tf.matmul(a, w2) + biases2)

2. 经典损失函数

交叉熵

判断一个输出向量和期望的向量距离的一个常用方法是使用交叉熵。
交叉熵描述的是两个概率分布p、q之间的距离。

H(p,q)=-\sum_{x}p(x)log \cdot q(x)

  • 值越小,两个概率分布的距离越近。
  • 交叉熵是不对称的,即H(p, q)\neq H(q , p),前着表述的是通过概率分布q来表达p的困难程度。当用于神经网络的损失函数时,p代表正确值,q表示预测值。
# 二值输出的交叉熵样例
cross_entropy = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y, 1e-10, 1.0))
                                + (1 - y_) * tf.log(tf.clip_by_value(1 - y, 1e-10, 1.0)))
'''
y_是正确值, y是预测值。
tf.clip_by_value(y, 1e-10, 1.0) 将 y的值限定在1e-10, 1.0之间(大于1的统统为1,小于等于0的统统为1e-10)。保证不会出现log0的情况。
* 是各元素相乘,不是矩阵相乘。
tf.reduce_mean计算矩阵所有元素的平均值。
'''

但是神经网络的输出却不一定是一个概率分布,那么如何将神经网络向前传播得到的结果也变成概率分布呢?

Softmax回归

假设原始的输出是y_i,经过softmax处理之后的输出为:
softmax(y)_i = y_{i}^{'} = \frac{e^{y_i}}{\sum_{j=1}^{n}e^{y_i}}

  • 原始的输出作为新输出的置信度
  • 新的输出满足概率分布的要求:
    (1)任意事件发生的概率在0到1之间 。
    (2)所有事件的概率之和为1。
  • 新的输出可以理解成一个样例为不同类别的概率分别为多大。
# 使用了softmax回归之后的交叉损失函数
cross_entropy = tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y)

# 针对只有一个正确值的加速版本
cross_entropy_for_only_one_class = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y_, logits=y)

均方误差

对于回归问题,一般只有一个输出节点,即预测值,最常用的损失函数是均方误差。

MSE(y, {y}')=\frac{\sum_{i=1}^{n}(y_i-y_i^{'})^2}{n}

mse_loss = tf.reduce_mean(tf.square(y_ - y))

3. 神经网络优化算法

梯度下降算法

用于优化单个参数的取值。算法细节参考这篇简书

反向传播算法

给出了一个高效的方式,在所有参数上使用梯度下降算法。算法细节参阅这篇简书
论文Learning-Representations-by-back-propagating-errors

4. 神经网络算法优化

学习率

'''
指数衰减发
'''
import tensorflow as tf

global_step = tf.Variable(0)
learning_rate = tf.train.exponential_decay(     #生成学习率
    learning_rate=0.1,        #初始学习率
    global_step=global_step,  #当前迭代次数
    decay_steps=100,          #衰减速度 (在迭代到该次数时学习率衰减为learning_rate * decay_rate)
    decay_rate=0.96,          #衰减系数
    staircase=True,           #True 表示 global_step/decay_steps会转化成整数,使得学习率的变化成一个阶梯函数,这样
    name=None
)
'''
学习率的变化: decayed_learning_rate = learning_rate * decay_rate ^ (global_step / decay_steps)
'''
train_op = tf.train.AdamOptimizer(learning_rate).minimize(any_loss, global_step=global_step)


'''
其他衰减方法:
tf.train.exponential_decay
tf.train.inverse_time_decay
tf.train.natural_exp_decay
tf.train.piecewise_constant
tf.train.polynomial_decay
'''

过拟合

解决过拟合的常用方法是正则化,正则化的细节请参考这篇简书
J(\theta)+\lambda R(w)

'''
均方误差+L2正则化的损失函数
'''
import tensorflow as tf

v_lambda = 0.001
w = tf.Variable(tf.random_normal([2, 1], stddev=1, seed=1))
y = tf.matmul(x, w)
mse_loss = tf.reduce_mean(tf.square(y_ - y) + tf.contrib.layers.l2_regularizer(v_lambda)(w))
实例
import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
'''
1. 生成模拟数据集。
'''
dataset_size = 200
data = []
label = []
np.random.seed(0)

# 以原点为圆心,半径为1的圆把散点划分成红蓝两部分,并加入随机噪音。
for i in range(dataset_size):
    x1 = np.random.uniform(-1,1)
    x2 = np.random.uniform(0,2)
    if x1**2 + x2**2 <= 1:
        data.append([np.random.normal(x1, 0.1),np.random.normal(x2,0.1)])
        label.append(0)
    else:
        data.append([np.random.normal(x1, 0.1), np.random.normal(x2, 0.1)])
        label.append(1)
        
data = np.hstack(data).reshape(-1,2)
label = np.hstack(label).reshape(-1, 1)
plt.scatter(data[:,0], data[:,1], c=np.squeeze(label),  # np.squeeze: 从数组的形状中删除单维度条目,即把shape中为1的维度去掉
           cmap="RdBu", vmin=-.2, vmax=1.2, edgecolor="white")
plt.show()
测试数据
'''
2. 定义一个获取权重,并自动加入正则项到损失的函数。一般tf.Variable都是需要训练的权重参数
'''
def get_weight(shape, var_lambda):
    w = tf.Variable(tf.random_normal(shape), dtype=tf.float32)
    tf.add_to_collection('losses', tf.contrib.layers.l2_regularizer(var_lambda)(w))
    return w

'''
3. 定义神经网络。
'''
x = tf.placeholder(tf.float32, shape=(None, 2))
y_ = tf.placeholder(tf.float32, shape=(None, 1))

# 每层节点的个数
layer_dimension = [2,10,5,3,1]

n_layers = len(layer_dimension)

cur_layer = x
in_dimension = layer_dimension[0]

# 循环生成网络结构,输入层X[None, 2],隐藏层W1[2, 10]、W2[10, 5]、W3[5, 3],输出层Y[None, 1]
for i in range(1, n_layers):
    out_dimension = layer_dimension[i]
    weight = get_weight([in_dimension, out_dimension], 0.003)
    bias = tf.Variable(tf.constant(0.1, shape=[out_dimension]))
    cur_layer = tf.nn.elu(tf.matmul(cur_layer, weight) + bias)
    in_dimension = layer_dimension[i]

y= cur_layer

# 损失函数的定义。
mse_loss = tf.reduce_sum(tf.pow(y_ - y, 2)) / dataset_size
tf.add_to_collection('losses', mse_loss)
loss = tf.add_n(tf.get_collection('losses'))

'''
4. 训练不带正则项的损失函数mse_loss。
'''

# 定义训练的目标函数mse_loss,训练次数及训练模型
train_op = tf.train.AdamOptimizer(0.001).minimize(mse_loss)
TRAINING_STEPS = 10000

with tf.Session() as sess:
    tf.global_variables_initializer().run()
    for i in range(TRAINING_STEPS):
        sess.run(train_op, feed_dict={x: data, y_: label})
        if i % 1000 == 1000 - 1:
            print("After %d steps, mse_loss: %f" % (i,sess.run(mse_loss, feed_dict={x: data, y_: label})))

    # 画出训练后的分割曲线       
    xx, yy = np.mgrid[-1.2:1.2:.01, -0.2:2.2:.01]
    grid = np.c_[xx.ravel(), yy.ravel()]
    probs = sess.run(y, feed_dict={x:grid})
    probs = probs.reshape(xx.shape)

plt.scatter(data[:,0], data[:,1], c=np.squeeze(label),
           cmap="RdBu", vmin=-.2, vmax=1.2, edgecolor="white")
plt.contour(xx, yy, probs, levels=[.5], cmap="Greys", vmin=0, vmax=.1)
plt.show()
不带正则项的分类结果
'''
5. 训练带正则项的损失函数loss
'''
# 定义训练的目标函数loss,训练次数及训练模型
train_op = tf.train.AdamOptimizer(0.001).minimize(loss)
TRAINING_STEPS = 10000

with tf.Session() as sess:
    tf.global_variables_initializer().run()
    for i in range(TRAINING_STEPS):
        sess.run(train_op, feed_dict={x: data, y_: label})
        if i % 1000 == 1000 - 1:
            print("After %d steps, loss: %f" % (i, sess.run(loss, feed_dict={x: data, y_: label})))

    # 画出训练后的分割曲线       
    xx, yy = np.mgrid[-1:1:.01, 0:2:.01]
    grid = np.c_[xx.ravel(), yy.ravel()]
    probs = sess.run(y, feed_dict={x:grid})
    probs = probs.reshape(xx.shape)

plt.scatter(data[:,0], data[:,1], c=np.squeeze(label),
           cmap="RdBu", vmin=-.2, vmax=1.2, edgecolor="white")
plt.contour(xx, yy, probs, levels=[.5], cmap="Greys", vmin=0, vmax=.1)
plt.show()
带正则项的分类结果

滑动平均模型

v1 = tf.Variable(0, dtype=tf.float32)
step = tf.Variable(0, trainable=False)
ema = tf.train.ExponentialMovingAverage(decay=0.99, num_updates=step)
# 每一次操作的时候,列表变量[v1]都会被更新
maintain_averages_op = ema.apply([v1])

with tf.Session() as sess:
    
    # 初始化
    init_op = tf.global_variables_initializer()
    sess.run(init_op)
    print(sess.run([v1, ema.average(v1)]))
    
    # 更新变量v1的取值
    sess.run(tf.assign(v1, 5))
    sess.run(maintain_averages_op)
    print(sess.run([v1, ema.average(v1)]))
    
    # 更新step和v1的取值
    sess.run(tf.assign(step, 10000))  
    sess.run(tf.assign(v1, 10))
    sess.run(maintain_averages_op)
    print(sess.run([v1, ema.average(v1)]))
    
    # 更新一次v1的滑动平均值
    sess.run(maintain_averages_op)
    print(sess.run([v1, ema.average(v1)]))

相关文章

网友评论

      本文标题:TensorFlow 深度学习基本概念

      本文链接:https://www.haomeiwen.com/subject/igovkqtx.html