损失函数用于评价模型的准确度。无论什么样的网络结构,如果损失函数不正确,都难以训练出正确的模型。
损失值用于描述预测值与真实值之间的差距大小。
常用的损失函数是 均方差函数和交叉熵函数。
均方差
MSE = tf.reduce_mean(tf.pow(tf.sub(logits,outputs),2.0))
tensorflow中常见交叉熵函数
sigmoid交叉熵
softmax交叉熵
sparse 交叉熵
sigmoid 交叉熵
tf.nn.sigmoid_cross_entropy_with_logits
tf.nn.softmax_cross_entropy_with_logits 计算输出值与实际值的softmax交叉熵
tf.nn.sparse_cross_entropy_with_logits 不要求预测值one-hot编码,但是必须从0开始分类。3分类只能是0,1,2
tf.nn.sigmoid_cross_entropy_with_logits 在交叉熵的基础上给第一项乘以一个系数,用于改变正样本在计算交叉熵时的损失值。
实验,
import tensorflow as tf
import numpy as np
labels = np.array([[0,0,1],[0,1,0]]).astype(np.float)
logits = np.array([[2, 0.5, 6],[0.1, 0, 3]]).astype(np.float)
print(labels)
logits_scaled = tf.nn.softmax(logits)
logits_scaled2 = tf.nn.softmax(logits_scaled)
result1= tf.nn.softmax_cross_entropy_with_logits(labels=labels, logits= logits)
result2= tf.nn.softmax_cross_entropy_with_logits(labels=labels, logits= logits_scaled)
result3= -tf.reduce_sum(labels*tf.log(logits_scaled),1)
with tf.Session() as sess:
print("scaled=",sess.run(logits_scaled))
print("scaled2=",sess.run(logits_scaled2))
print("rel1",sess.run(result1),"\n")
print("rel2", sess.run(result2),"\n")
print("rel3", sess.run(result3))
输出结果:
scaled= [[0.01791432 0.00399722 0.97808846]
[0.04980332 0.04506391 0.90513277]]
scaled2= [[0.21747023 0.21446464 0.56806514]
[0.23002143 0.22893385 0.54104472]]
rel1 [0.02215516 3.09967364]
rel2 [0.56551919 1.4743222 ]
rel3 [0.02215516 3.09967364]
可以看出,softmax_cross_entropy_with_logits函数自带softmax功能,所以传入的值就不需要提前激活,如果已经激活过了就需要自行写交叉熵函数计算,而不能直接使用tensorflow提供的算法。
如果标签没有one-hot编码,softmax交叉熵的效果会很差。
labels = np.array([[0.4,0.1,0.5],[0.3,0.6,0.1]]).astype(np.float)
输出结果,可以看出错误数据和正确数据误差区别不大,而上面的误差查了几百倍。
rel1 [2.17215516 2.76967364]
如果标签是从0开始的分类,使用下面的误差函数,效果和one-hot编码的是一样的。
label2 = [2,1]
result4= tf.nn.sparse_softmax_cross_entropy_with_logits(labels=label2,logits=logits)
梯度下降
梯度下降是最优化算法,也叫最速下降法。使用负梯度为搜索方向,沿着梯度下降的方向求解极小值。
寻找最小的损失值,推出最小的学习参数b和w,常用梯度下降算法分为:批量梯度下降、随机梯度下降、小批量梯度下降。
批量梯度下降:每次都遍历全部数据,计算损失函数。计算量大,计算速度慢,不支持在线学习。
随机梯度下降:每看一个数据就算一下损失函数,然后求梯度更新参数。速度快,收敛性能不好
小批量梯度下降:克服上面2种方法的缺点,把数据分为若干批,按批更新参数,一批中的一组数据共同决定了本次梯度的方向。
操作 | 描述 |
---|---|
tf.train.GradientDescentOptimizer | 一般的梯度下降算法 |
tf.train.AdadeltaOptimizer | Adadelta优化器 |
tf.train.AdagradOptimizer | Adagrad优化器 |
tf.train.MomentumOptimizer | Momentum优化器 |
tf.train.AdamOptimizer | Adam优化器 |
tf.train.FtlrOptimizer | FTLR优化器 |
tf.train.RMSPropOptimizer | RMSProp优化器 |
梯度下降算法需要使用学习率,而学习率的选择可以使用“退化学习率”。
def exponential_decay(learning_rate,global_step,decay_step,decay_rate,staircase=False,name=None)
学习率衰减速度由 global_step,decay_steps决定。
decayed_learning_rate = learning_rate_*decay_rate^(global_step/decay_steps)
使用方法:
global_step= tf.Variable(0.,trainable=False)
inital_learning_rate = 0.1
learning_rate = tf.train.exponential_decay(inital_learning_rate,global_step= global_step,decay_steps=10,decay_rate=0.9)
opt = tf.train.GradientDescentOptimizer(learning_rate)
add_global = global_step.assign_add(1)
with tf.Session() as sess:
tf.global_variables_initializer().run()
print(sess.run(learning_rate))
for i in range(20):
g,rate = sess.run([add_global,learning_rate])
print(g,rate)
maxout网络是单个神经元的扩展,主要是扩展单个神经元的激活函数,将多个神经元并列放在一起,找出输出结果中最大的那个,代表对特征响应最敏感,然后取这个神经元的结果参与后面的运算。