这次扔使用上次的mnist数据集分类的简单版本程序,使用不同的代价函数做计算
二次代价函数
激活函数
使用二次代价函数的运行结果
# 使用二次代价函数的结果-精度
# loss=tf.reduce_mean(tf.square(y-prediction))
# 0.8322
# 0.8698
# 0.8818
# 0.8882
# 0.8935
# 0.8965
# 0.8999
# 0.9017
# 0.9039
# 0.9054
# 0.9062
# 0.9074
# 0.9081
# 0.9095
# 0.9099
# 0.91
# 0.9108
# 0.9125
# 0.9132
# 0.9132
# 0.9136
-
问题所在:
-
需求情况:
距离目标越近,调整越慢,越远则调整越快
交叉熵代价函数
- 这个怎么来的?
因为sigmoid函数的公式:
计算得到(自己求导试试)
信息熵的文章
熵其实是信息量的期望值,它是一个随机变量的确定性的度量。熵越大,变量的取值越不确定,反之就越确定。
–>与二次代价函数相比的优势所在。
越接近迈越小的步子
-
S形函数
比如:sigmoid函数 -
优势
调整的比较合理,速度快
使用交叉熵的结果
# # 交叉熵代价函数
# loss=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y,logits=prediction))
# 0.8334
# 0.895
# 0.9024
# 0.9057
# 0.9091
# 0.9108
# 0.912
# 0.913
# 0.9159
# 0.9162
# 0.9169
# 0.9191
# 0.9183
# 0.9203
# 0.9197
# 0.9201
# 0.9204
# 0.9206
# 0.9218
# 0.9215
# 0.9218
对数似然代价函数
似然最大估计
拟合
-
回归
-
欠拟合
-
正确拟合
-
过拟合:(未知数过多而已有的公式过少)
-
分类
防止过拟合
n是训练集的大小,λ是一个参数可以调节正则项的重要性,w是权值,C是误差
- dropout:
如果一个神经元的参数几乎都等于0的话,那么多少乘以0都还是0,所以可以认为这个神经元不存在,将之删除。
这样可以简化神经网络的
在执行过程中,可以只让部分神经元工作,而另一部分不工作,如右图所示。实线神经元为工作的神经元,虚线则为不工作的神经元
demo2dropout
-
加一个中间层
-
初始化为0,并不是好的初始化方式,一般使用随机数初始化。
# 加一个中间层keep_prob=tf.placeholder(tf.float32)# 创建一个简单的神经网络,直接784投影到10上W1=tf.Variable(tf.truncated_normal([784,2000],stddev=0.1))# tf.truncated_normal(shape, mean, stddev) :shape表示生成张量的维度,mean是均值,stddev是标准差.正态分布b1=tf.Variable(tf.zeros([2000])+0.1)L1=tf.nn.tanh(tf.matmul(x,W1)+b1)L1_drop=tf.nn.dropout(L1,keep_prob)W2=tf.Variable(tf.truncated_normal([2000,2000],stddev=0.1))# tf.truncated_normal(shape, mean, stddev) :shape表示生成张量的维度,mean是均值,stddev是标准差.正态分布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))# tf.truncated_normal(shape, mean, stddev) :shape表示生成张量的维度,mean是均值,stddev是标准差.正态分布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)# keep_prob-->设置他有多少个神经元是工作的:0-1.1:100%工作。0.5:一半是在工作的W4=tf.Variable(tf.truncated_normal([1000,10],stddev=0.1))b4=tf.Variable(tf.zeros([10]))#b的形状依据每个批次的形状而定,在中间层时,每个批次未必是一行n列,也可能变换成多行多列,此时b随之改变。prediction=tf.nn.softmax(tf.matmul(L3_drop,W4)+b4)#(形状(100,10)
不使用dropout
sess.run(train_step,feed_dict={x:batch_xs,y:batch_ys,keep_prob:1.0})
100%的神经元都工作的情况下
使用dropout
70%神经元工作情况下的训练结果
测试时仍有100%在工作,收敛速度很快,但后来上不去了,而且测试精度与训练精度相差很大
sess.run(train_step,feed_dict={x:batch_xs,y:batch_ys,keep_prob:0.7})print("test-iter:",epoch," acc:",sess.run(accuracy,feed_dict={x:mnist.test.images,y:mnist.test.labels,keep_prob:1.0}))
print("train-iter:",epoch," acc:",sess.run(accuracy, feed_dict={x: mnist.train.images, y: mnist.train.labels, keep_prob: 1.0}))
收敛速度变慢了,但三十次所达到的还不是极限,这个精度还能上升,并且,测试精度和训练精度相差不大
优化器Optimizer
训练时间:标准>批量>随机
噪音:标准<批量<随机
批量用的多
W:要训练的参数
J(W):代价函数
对W的梯度
gt同上,是梯度。
效果
星:全局最小
速度:adadelta最快,SGD最慢。momentum很快,但是路径绕,NAG相当于聪明版本的momentum
鞍顶问题
除了adaelta和adagrad外,都在窝里来回晃悠。后来除了SGD以外的才晃悠出来,如下
- SGD:慢,而且鞍顶也无法逃离,那是不是不用了?
每种优化器都有其适用范围,新的都快,但是SGD准确率高。
不知道哪个优化器最后的结果准确率最高,这个说不准,可能都要测试一次
优化器的比较:
https://blog.csdn.net/fengchao03/article/details/78208414
https://blog.csdn.net/weixin_40170902/article/details/80092628
https://www.jianshu.com/p/ee39eca29117
优化demo1
- 加中间层(中间层的层数、神经元数太多的话可以降低
- keep_drop改成0.7之类的试试
- 权值从0变成tf.truncated_normal([2000,1000],stddev=0.1),b变成0.1
- 优化器的选择,调节学习率
- 中间层的激活函数,tanh或者其他什么delu,softmax啊之类的
- 迭代次数要足够,趋于稳定