TF - 代价函数和过拟合

二次代价函数(quadratic cost)

TF - 代价函数和过拟合_第1张图片
  • 其中,C表示代价函数,x表示样本,y表示实际值,a表示输出值,n表示样本的总数。为简单起见,同样一个样本为例进行说明,此时二次代价函数为:
TF - 代价函数和过拟合_第2张图片
  • a=σ(z), z=∑Wj*Xj+b
    σ() 是激活函数

  • 假如我们使用梯度下降法(Gradient descent)来调整权值参数的大小,权值w和偏置b的梯度推导
    如下:

TF - 代价函数和过拟合_第3张图片
  • 其中,z表示神经元的输入,σ表示激活函数。w和b的梯度跟激活函数的梯度成正比,激活函数的
    梯度越大,w和b的大小调整得越快,训练收敛得就越快。

假设我们的激活函数是sigmoid函数:

TF - 代价函数和过拟合_第4张图片
TF - 代价函数和过拟合_第5张图片
  • 案例的调整方案应该为:离目标比较远,梯度比较大,权值调整比较大;离目标近,梯度比较小,权值调整比较小;

交叉熵代价函数(cross-entropy)

  • 换一个思路,我们不改变激活函数,而是改变代价函数,改用交叉熵代价函数:
TF - 代价函数和过拟合_第6张图片
  • 其中,C表示代价函数,x表示样本,y表示实际值,a表示输出值,n表示样本的总数。
TF - 代价函数和过拟合_第7张图片
TF - 代价函数和过拟合_第8张图片
TF - 代价函数和过拟合_第9张图片
  • 权值和偏置值的调整与

    无关,另外,梯度公式中的

    表示输出值与实际值的误差。所以当误差越大时,梯度就越大,参数w和b的调整就越快,训练的速度也就越快。
  • 如果输出神经元(激活函数)是线性的,那么二次代价函数就是一种合适的选择。如果输出神经元是S型函数,那么比较适合用交叉熵代价函数。

对数释然代价函数(log-likelihood cost)

对数释然函数常用来作为softmax回归的代价函数,如果输出层神经元是sigmoid函数,可以采用交叉熵代价函数。而深度学习中更普遍的做法是将softmax作为最后一层,此时常用的代价函数是对数释然代价函数。

  • 条件概率分布p(y|x)的对数似然函数:


机器学习之Softmax回归模型

对数似然代价函数与softmax的组合和交叉熵与sigmoid函数的组合非常相似。对数释然代价函数在二分类时可以化简为交叉熵代价函数的形式。

  • 在Tensorflow中用:
    tf.nn.sigmoid_cross_entropy_with_logits()来表示跟sigmoid搭配使用的交叉熵。
    tf.nn.softmax_cross_entropy_with_logits()来表示跟softmax搭配使用的交叉熵。

拟合

TF - 代价函数和过拟合_第10张图片
回归问题
TF - 代价函数和过拟合_第11张图片
分类问题
  • 防止过拟合

① 增加数据集

② 在代价函数后面增加一个 正则化方法(w权值,n训练集的大小,入是调节参数)

在优化C的过程中,会使W权值较的越来越小,使得他的权值几乎等于0,就可以认为这个神经元是不存在的

  1. Dropout (在训练迭代的过程中使用部分神经元工作,在测试时激活全部神经元测试 )
TF - 代价函数和过拟合_第12张图片
  • 一般网络过于复杂,数据量较小,容易引起过拟合。(用训练集测试出来的准确率大于测试集很明显)下列建立过拟合场景,通过改变keep_prob值进行dropout
import tensorflow as tf
import os
from tensorflow.contrib.learn.python.learn.datasets.mnist import read_data_sets

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'

# 载入数据集(放在当前代码目录)
mnist = read_data_sets("MNIST_data/", one_hot=True)

# 每个批次的大小(每次训练图片的数量)
batch_size = 100
# 计算一共有多少个批次
n_batch = mnist.train.num_examples // batch_size

# 定义两个placeholder(输入图片和标签)
x = tf.placeholder(tf.float32, [None, 784])
y = tf.placeholder(tf.float32, [None, 10])
keep_prob = tf.placeholder(tf.float32)

# 创建神经网络

# 用截断的正态分布对权值进行初始化,标准差为0.1(这样初始化效果会比较好)
w1 = tf.Variable(tf.truncated_normal([784, 2000], stddev=0.1))
b1 = tf.Variable(tf.zeros([2000]) + 0.1)
# 定义双曲正切激活函数
L1 = tf.nn.tanh(tf.matmul(x, w1) + b1)
# keep_prob控制多少神经元在工作
L1_drop = tf.nn.dropout(L1, keep_prob)

# 加隐藏层
w2 = tf.Variable(tf.truncated_normal([2000, 2000], stddev=0.1))
b2 = tf.Variable(tf.zeros([2000]) + 0.1)
L2 = tf.nn.tanh(tf.matmul(L1_drop, w2) + b2)
L2_drop = tf.nn.dropout(L2, keep_prob)

w3 = tf.Variable(tf.truncated_normal([2000, 1000], stddev=0.1))
b3 = tf.Variable(tf.zeros([1000]) + 0.1)
L3 = tf.nn.tanh(tf.matmul(L2_drop, w3) + b3)
L3_drop = tf.nn.dropout(L3, keep_prob)

w4 = tf.Variable(tf.truncated_normal([1000, 10], stddev=0.1))
b4 = tf.Variable(tf.zeros([10]) + 0.1)
prediction = tf.nn.softmax(tf.matmul(L3_drop, w4) + b4)

# 换成交叉熵代价函数
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y, logits=prediction))

# 使用梯度下降法
train_step = tf.train.GradientDescentOptimizer(0.2).minimize(loss)

# 初始化变量
init = tf.global_variables_initializer()

# 比较真实值和预测值概率最大标签是否相同,结果存放在一个布尔型列表中
# argmax 返回一维张量中最大的值所在的位置
correct_prediction = tf.equal(tf.argmax(y, 1), tf.arg_max(prediction, 1))
# 求准确率
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

config = tf.ConfigProto()
config.gpu_options.allow_growth = True

with tf.Session(config=config) as sess:
    sess.run(init)
    for epoch in range(31):
        for batch in range(n_batch):
            batch_xs, batch_ys = mnist.train.next_batch(batch_size)
            sess.run(train_step, feed_dict={x: batch_xs, y: batch_ys, keep_prob: 1.0})

            test_acc = sess.run(accuracy, feed_dict={x: mnist.test.images, y: mnist.test.labels, keep_prob: 1.0})
            train_acc = sess.run(accuracy, feed_dict={x: mnist.train.images, y: mnist.train.labels, keep_prob: 1.0})
            print("Iter " + str(epoch) + ",Testing Accuracy " + str(test_acc) + ",Train Accuracy " + str(train_acc))

你可能感兴趣的:(TF - 代价函数和过拟合)