多标签分类keras中的奇怪准确性
Posted
技术标签:
【中文标题】多标签分类keras中的奇怪准确性【英文标题】:Weird accuracy in multilabel classification keras 【发布时间】:2017-12-03 16:01:09 【问题描述】:我有一个多标签分类问题,我使用了以下代码,但验证准确率在第一个 epoch 跃升至 99%,考虑到数据的复杂性,这很奇怪,因为输入特征是从初始模型 (pool3:0) 中提取的 2048 ) 层和标签是 [1000],(这里是包含特征样本和标签的文件的链接:https://drive.google.com/file/d/0BxI_8PO3YBPPYkp6dHlGeExpS1k/view?usp=sharing), 我在这里做错了吗??
注意:标签是稀疏向量,仅包含 1 ~ 10 个条目,其余为 0
model.compile(optimizer='adadelta', loss='binary_crossentropy', metrics=['accuracy'])
预测的输出为零!
我在训练模型以影响预测时做错了什么?
#input is the features file and labels file
def generate_arrays_from_file(path ,batch_size=100):
x=np.empty([batch_size,2048])
y=np.empty([batch_size,1000])
while True:
f = open(path)
i = 1
for line in f:
# create Numpy arrays of input data
# and labels, from each line in the file
words=line.split(',')
words=map(float, words[1:])
x_= np.array(words[0:2048])
y_=words[2048:]
y_= np.array(map(int,y_))
x_=x_.reshape((1, -1))
#print np.squeeze(x_)
y_=y_.reshape((1,-1))
x[i]= x_
y[i]=y_
i += 1
if i == batch_size:
i=1
yield (x, y)
f.close()
model = Sequential()
model.add(Dense(units=2048, activation='sigmoid', input_dim=2048))
model.add(Dense(units=1000, activation="sigmoid",
kernel_initializer="uniform"))
model.compile(optimizer='adadelta', loss='binary_crossentropy', metrics=
['accuracy'])
model.fit_generator(generate_arrays_from_file('train.txt'),
validation_data= generate_arrays_from_file('test.txt'),
validation_steps=1000,epochs=100,steps_per_epoch=1000,
verbose=1)
【问题讨论】:
生成器是否正确创建了标签?听起来你给模型的真实值都是零。 您的数据集统计数据有哪些?如果您的训练数据集太小,您肯定处于过度拟合的情况。如果不是这种情况,您应该尝试应用一些 dropout 以避免过度拟合。 @AlessandroSuglia 我们的数据集是 200k 图像,所以它不小,关于 dropout 我尝试过,但我有同样的问题 @Daniel 我认为问题出在生成器上,但我确定输入标签并非全为零,我是这样从文件生成的 给定示例的类是否独立?也许二进制交叉熵不是最适合您的问题的解决方案。 【参考方案1】:我认为准确性的问题在于您的输出稀疏。
Keras 使用以下公式计算准确度:
K.mean(K.equal(y_true, K.round(y_pred)), axis=-1)
因此,在您的情况下,只有 1~10 个非零标签,所有 0 的预测将产生 99.9% ~ 99% 的准确度。
至于不学习的问题,我认为问题在于您使用 sigmoid 作为最后一次激活并使用 0 或 1 作为输出值。这是不好的做法,因为为了让 sigmoid 返回 0 或 1,它作为输入获得的值必须非常大或非常小,这反映在具有非常大(绝对值)权重的网络上。此外,由于在每个训练输出中,1 远小于 0,因此网络很快就会到达一个稳定点,在该点它简单地输出全零(这种情况下的损失也不是很大,应该在 0.016~0.16 左右)。
您可以做的是缩放输出标签,使其介于 (0.2, 0.8) 之间,例如,这样网络的权重就不会变得太大或太小。或者,您可以使用relu
作为激活函数。
【讨论】:
谢谢你,但我仍然有同样的问题,我将输出从 0.2 缩放到 0.8,但我的模型无法正确预测,因为输出也位于 0,2 尝试使用relu
。或者,您是否尝试过添加更多隐藏层?走得更深通常比走得更宽要好。看起来您正在尝试使用非常浅的网络对复杂问题进行建模。 1000 个标签很多,GoogLeNet 使用非常深的网络对使用相同数量标签的图像进行分类(尽管它们有 224x224 图像作为输入)。您可以做的是尝试使用较少的标签进行分类,然后增加数量(从 10 开始,然后是 100,依此类推)。如果它仍然没有训练,那么代码可能有问题
@gionni 如果深度网络也出现同样的问题该怎么办?
我不知道,这取决于数据和架构【参考方案2】:
您是否尝试使用余弦相似度作为损失函数?
我有同样的多标签 + 高维问题。
余弦距离考虑了模型输出(预测)和期望输出(真实类)向量的方向。
它是两个向量之间的归一化点积。
在 keras 中 cosine_proximity 函数是 -1*cosine_distance。这意味着 -1 对应于具有相同大小和方向的两个向量。
【讨论】:
以上是关于多标签分类keras中的奇怪准确性的主要内容,如果未能解决你的问题,请参考以下文章