当我们训练神经网络时,我们通常使用梯度下降,它依赖于一个连续的、可微的实值成本函数。例如,最后的成本函数可能采用均方误差。换句话说,梯度下降隐含地假定最终目标是回归--最小化一个实值误差度量。
有时,我们希望神经网络执行分类--给定输入,将其分类为两个或多个离散类别。在这种情况下,用户关心的最终目标是分类的准确性--正确分类案例的百分比。
但是当我们使用神经网络进行分类时,尽管我们的目标是分类精度,但这不是神经网络试图优化的。神经网络仍在努力优化实值成本函数.有时这些点指向相同的方向,但有时却并非如此。特别是,我遇到了这样的情况:经过训练以正确最小化成本函数的神经网络的分类精度低于简单的手编码阈值比较。
我使用TensorFlow将其简化为一个最小的测试用例。它建立了一个感知器(无隐层神经网络),在一个绝对最小的数据集(一个输入变量,一个二进制输出变量)上进行训练,评估结果的分类精度,并将其与简单的手编码阈值比较的分类精度进行比较,结果分别为60%和80%。直观地说,这是因为一个输入值大的孤立点产生了相应的较大的输出值,因此最小化成本函数的方法是在对另外两个普通情况进行错误分类的过程中,加倍努力地适应这一情况。感知器正确地完成了它被告知要做的事情,只是这与我们真正想要的分类器不匹配。但由于分类精度不是一个连续的可微函数,因此不能将其作为梯度下降的目标。
我们如何训练一个神经网络,使它最终达到最大的分类精度?
import numpy as np
import tensorflow as tf
sess = tf.InteractiveSession()
tf.set_random_seed(1)
# Parameters
epochs = 10000
learning_rate = 0.01
# Data
train_X = [
[0],
[0],
[2],
[2],
[9],
]
train_Y = [
0,
0,
1,
1,
0,
]
rows = np.shape(train_X)[0]
cols = np.shape(train_X)[1]
# Inputs and outputs
X = tf.placeholder(tf.float32)
Y = tf.placeholder(tf.float32)
# Weights
W = tf.Variable(tf.random_normal([cols]))
b = tf.Variable(tf.random_normal([]))
# Model
pred = tf.tensordot(X, W, 1) + b
cost = tf.reduce_sum((pred-Y)**2/rows)
optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost)
tf.global_variables_initializer().run()
# Train
for epoch in range(epochs):
# Print update at successive doublings of time
if epoch&(epoch-1) == 0 or epoch == epochs-1:
print('{} {} {} {}'.format(
epoch,
cost.eval({X: train_X, Y: train_Y}),
W.eval(),
b.eval(),
))
optimizer.run({X: train_X, Y: train_Y})
# Classification accuracy of perceptron
classifications = [pred.eval({X: x}) > 0.5 for x in train_X]
correct = sum([p == y for (p, y) in zip(classifications, train_Y)])
print('{}/{} = perceptron accuracy'.format(correct, rows))
# Classification accuracy of hand-coded threshold comparison
classifications = [x[0] > 1.0 for x in train_X]
correct = sum([p == y for (p, y) in zip(classifications, train_Y)])
print('{}/{} = threshold accuracy'.format(correct, rows))发布于 2017-12-20 16:13:11
我们如何训练一个神经网络,使它最终达到最大的分类精度? 我想找出一种更接近精确性的连续代理函数
首先,今天用于(深度)神经网络分类任务的损失函数不是与之一起发明的,但它可以追溯到几十年前,它实际上来自于logistic回归的早期。以下是二进制分类的简单情况的方程式:

它背后的想法就是想出一个连续的、可微的函数,这样我们就能够为分类问题开发(庞大的,而且还在不断扩展的)凸优化库。
可以肯定地说,考虑到上面提到的数学约束,上述损失函数是我们迄今为止所拥有的最好的。
我们是否应该考虑这个问题(即更好地逼近精度)得到解决和完成?至少原则上没有。我已经足够老了,可以记住一个时代,当时只有tanh和sigmoid是唯一可用的激活函数;接着,ReLU出现了,给这个领域带来了真正的推动力。类似地,最终可能有人会想出一个更好的损失函数,但可以说,这将在一篇研究论文中发生,而不是作为对这样一个问题的答案。
尽管如此,目前的损失函数来源于概率论和信息论的基本考虑(与目前的深入学习领域形成鲜明对比,这些领域的理论基础是坚实的),这一事实至少使人怀疑,关于损失的更好建议是否即将到来。
关于损失和准确性之间的关系还有另一个微妙的观点,这使得后者在质量上不同于前者,并且经常在这种讨论中迷失。让我再详细阐述一下..。
与此讨论有关的所有分类器(即神经网络、logistic回归等)都是概率的,即它们不返回硬类成员资格(0/1),而是返回类概率(连续实数为0,1)。
将简单性的讨论限制在二进制情况下,当将类概率转换为(硬)类成员时,我们隐含地涉及一个阈值,通常等于0.5,例如如果p[i] > 0.5,然后是class[i] = "1"。现在,我们可以发现很多情况下,这种天真的默认阈值选择将无法工作(首先想到的是严重不平衡的数据集),我们将不得不选择另一个。但我们在这里讨论的重点是,这种阈值选择虽然对精度至关重要,但完全是与最小损失的数学优化问题无关的,是它们之间的一个进一步的“绝缘层”,损害了关于损失只是精确性的代表的简单化观点(不是)。就像此交叉验证线程的回答一样好
当您输出新样本的每个类别的概率时,您的练习的统计组件就会结束。选择一个阈值,将新的观察归类为1比0,不再是统计数据的一部分。它是决策组件的一部分。
扩大了一个已经很广泛的讨论:我们能否完全摆脱连续和可微函数数学优化的(非常)极限约束?换句话说,我们能消除反向传播和梯度下降吗?
实际上,我们已经在这样做了,至少在强化学习的子领域是这样的:2017年是OpenAI的新研究关于进化策略登上头条的一年。作为额外的奖励,这里有一个关于这个问题的超新鲜(2017年12月) Uber的论文,再次在社区中生成热诚。
发布于 2017-12-19 18:46:13
我想你忘了把你的输出传递给一个简单的例子。固定在下面:
import numpy as np
import tensorflow as tf
sess = tf.InteractiveSession()
tf.set_random_seed(1)
# Parameters
epochs = 10000
learning_rate = 0.01
# Data
train_X = [
[0],
[0],
[2],
[2],
[9],
]
train_Y = [
0,
0,
1,
1,
0,
]
rows = np.shape(train_X)[0]
cols = np.shape(train_X)[1]
# Inputs and outputs
X = tf.placeholder(tf.float32)
Y = tf.placeholder(tf.float32)
# Weights
W = tf.Variable(tf.random_normal([cols]))
b = tf.Variable(tf.random_normal([]))
# Model
# CHANGE HERE: Remember, you need an activation function!
pred = tf.nn.sigmoid(tf.tensordot(X, W, 1) + b)
cost = tf.reduce_sum((pred-Y)**2/rows)
optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost)
tf.global_variables_initializer().run()
# Train
for epoch in range(epochs):
# Print update at successive doublings of time
if epoch&(epoch-1) == 0 or epoch == epochs-1:
print('{} {} {} {}'.format(
epoch,
cost.eval({X: train_X, Y: train_Y}),
W.eval(),
b.eval(),
))
optimizer.run({X: train_X, Y: train_Y})
# Classification accuracy of perceptron
classifications = [pred.eval({X: x}) > 0.5 for x in train_X]
correct = sum([p == y for (p, y) in zip(classifications, train_Y)])
print('{}/{} = perceptron accuracy'.format(correct, rows))
# Classification accuracy of hand-coded threshold comparison
classifications = [x[0] > 1.0 for x in train_X]
correct = sum([p == y for (p, y) in zip(classifications, train_Y)])
print('{}/{} = threshold accuracy'.format(correct, rows))产出:
0 0.28319069743156433 [ 0.75648874] -0.9745011329650879
1 0.28302448987960815 [ 0.75775659] -0.9742625951766968
2 0.28285878896713257 [ 0.75902224] -0.9740257859230042
4 0.28252947330474854 [ 0.76154679] -0.97355717420578
8 0.28187844157218933 [ 0.76656926] -0.9726400971412659
16 0.28060704469680786 [ 0.77650583] -0.970885694026947
32 0.27818527817726135 [ 0.79593837] -0.9676888585090637
64 0.2738055884838104 [ 0.83302218] -0.9624817967414856
128 0.26666420698165894 [ 0.90031379] -0.9562843441963196
256 0.25691407918930054 [ 1.01172411] -0.9567816257476807
512 0.2461051195859909 [ 1.17413962] -0.9872989654541016
1024 0.23519910871982574 [ 1.38549554] -1.088881492614746
2048 0.2241383194923401 [ 1.64616168] -1.298340916633606
4096 0.21433120965957642 [ 1.95981205] -1.6126530170440674
8192 0.2075471431016922 [ 2.31746769] -1.989408016204834
9999 0.20618653297424316 [ 2.42539024] -2.1028473377227783
4/5 = perceptron accuracy
4/5 = threshold accuracyhttps://stackoverflow.com/questions/47891197
复制相似问题