Python 神经网络:神秘的ReLu
作为一个更大项目的一部分,我一直在构建一个编程语言检测器,即代码片段的分类器。 我的基线模型非常简单:将输入标记化,并将片段编码为一袋单词或, 在这种情况下,您可以打包令牌,并在这些功能的基础上创建一个简单的NN NN的输入是一个固定长度的计数器数组,其中包含最独特的令牌,例如Python 神经网络:神秘的ReLu,python,tensorflow,machine-learning,neural-network,deep-learning,Python,Tensorflow,Machine Learning,Neural Network,Deep Learning,作为一个更大项目的一部分,我一直在构建一个编程语言检测器,即代码片段的分类器。 我的基线模型非常简单:将输入标记化,并将片段编码为一袋单词或, 在这种情况下,您可以打包令牌,并在这些功能的基础上创建一个简单的NN NN的输入是一个固定长度的计数器数组,其中包含最独特的令牌,例如“def”, “self”,“function”,“->”,“const”,“#include”,等等,这些都是从语料库中自动提取的。 其想法是,这些标记对于编程语言来说是非常独特的,因此即使是这种幼稚的方法也应该得到支
“def”
,
“self”
,“function”
,“->”
,“const”
,“#include”
,等等,这些都是从语料库中自动提取的。
其想法是,这些标记对于编程语言来说是非常独特的,因此即使是这种幼稚的方法也应该得到支持
准确率高
Input:
def 1
for 2
in 2
True 1
): 3
,: 1
...
Output: python
安装程序
我很快就得到了99%的准确率,并认为这是它正常工作的标志。这是模型
(完整的可运行脚本如下所示):
#占位符
x=tf.placeholder(shape=[None,vocab_size],dtype=tf.float32,name='x')
y=tf.placeholder(shape=[None],dtype=tf.int32,name='y')
training=tf.placeholder_,默认值为(False,shape=[],name='training')
#一个隐藏层与辍学
reg=tf.contrib.layers.l2_正则化器(0.01)
hidden1=tf.layers.dense(x,units=96,kernel_regulazer=reg,
激活=tf.nn.elu,name='hidden1')
dropout1=tf.layers.dropout(hidden1,rate=0.2,training=training,name='dropout1')
#输出层
logits=tf.layers.dense(dropout1,units=classes,kernel\u regulazer=reg,
激活=tf.nn.relu,name='logits')
#交叉熵损失
损失=tf.reduce_平均值(
tf.nn.sparse\u softmax\u cross\u entropy\u with\u logits(logits=logits,abels=y))
#杂项报告:准确性、正确/错误分类样本等。
correct_predicted=tf.nn.in_top_k(logits,y,1,name='in-top-k')
预测=tf.argmax(logits,轴=1)
错误的\u预测=tf.逻辑的\u不(正确的\u预测,name='not-in-top-k')
x_misclassified=tf.boolean_掩码(x,预测错误,name='misclassified')
准确度=tf.reduce\u平均值(tf.cast(正确预测,tf.float32),name='accurity')
产出相当令人鼓舞:
迭代=5损失=2.580列车acc=0.34277
迭代=10损失=2.029列车acc=0.69434
迭代=15损失=2.054列车acc=0.92383
迭代=20损失=1.934列车acc=0.98926
迭代=25损失=1.942列车acc=0.99609
Files.VAL平均精度=0.99121预测分布
在玩了一段时间后,我决定可视化两个模型的实际预测分布:
predicted_distribution = tf.nn.softmax(logits, name='distribution')
下面是分布的直方图,以及它们是如何随时间演变的
带ReLu(错误型号)
不带ReLu(正确型号)
第一个直方图是有意义的,大多数概率接近0
。
但ReLu模型的直方图是可疑的:经过几次迭代后,值似乎集中在0.15
附近。打印实际预测证实了这一想法:
[0.14286 0.14286 0.14286 0.14286 0.14286 0.14286 0.14286]
[0.14286 0.14286 0.14286 0.14286 0.14286 0.14286 0.14286]
我有7门课(当时有7种不同的语言),而且0.14286
是1/7
。事实证明,“完美”模型学会了输出
0
logits,这反过来转化为统一预测
但是,如何才能将此分布报告为99%的准确率
tf.nn.in\u top\u k
在深入研究之前,我检查了另一种计算精度的方法:
true_correct = tf.equal(tf.argmax(logits, 1), tf.cast(y, tf.int64))
alternative_accuracy = tf.reduce_mean(tf.cast(true_correct, tf.float32))
。。。对最高预测等级和基本事实进行诚实的比较。结果是:
iteration=2 loss=3.992 train-acc=0.13086 train-alt-acc=0.13086
iteration=4 loss=3.590 train-acc=0.13086 train-alt-acc=0.12207
iteration=6 loss=2.871 train-acc=0.21777 train-alt-acc=0.13672
iteration=8 loss=2.466 train-acc=0.37695 train-alt-acc=0.16211
iteration=10 loss=2.099 train-acc=0.62305 train-alt-acc=0.10742
iteration=12 loss=2.066 train-acc=0.79980 train-alt-acc=0.17090
iteration=14 loss=2.016 train-acc=0.84277 train-alt-acc=0.17285
iteration=16 loss=1.954 train-acc=0.91309 train-alt-acc=0.13574
iteration=18 loss=1.956 train-acc=0.95508 train-alt-acc=0.06445
iteration=20 loss=1.923 train-acc=0.97754 train-alt-acc=0.11328
事实上,tf.nn.in_top_k
withk=1
很快偏离了正确的准确度,并开始报告幻想的99%值。
那么它实际上是做什么的呢?这是什么
他说:
说明目标是否在前K预测中
这将输出一个batch\u size
bool数组,如果目标类的预测值在前k中,则条目out[i]
为真
所有预测中的预测,例如i。
注意,InTopK
的行为与TopK
op在处理领带时的行为不同;
如果多个类具有相同的预测值并跨越top-k边界,
所有这些类别都被视为前k名
就是这样。如果概率是一致的(这实际上意味着“我不知道”),那么它们都是正确的。情况更糟,因为如果logits分布几乎是均匀的,softmax可能会将其转换为完全均匀的分布,如本简单示例所示:
x = tf.constant([0, 1e-8, 1e-8, 1e-9])
tf.nn.softmax(x).eval()
# >>> array([0.25, 0.25, 0.25, 0.25], dtype=float32)
。。。这意味着,根据规范中的tf.nn.,每个几乎一致的预测都可以被认为是“正确的”
结论
在tensorflow中,tf.nn.in_top_k
是一个危险的精度度量选择,因为它可能会默默地吞噬错误的预测
并报告为“正确”。相反,您应该始终使用以下长而可信的表达式:
accuracy = tf.reduce_mean(tf.cast(tf.equal(tf.argmax(logits, 1), tf.cast(y, tf.int64)), tf.float32))