我正在尝试进行一对多多标签分类。我向每个分类器提供一批输入以及预期的标签。分类器使用 softmax 层进行输出来预测标签是或否。另外,我对每个分类器使用 softmax 交叉熵损失,并且每个分类器都尝试最小化其自身的损失。分类器在每一步中不断最小化损失,但预测每个标签为零。
我怀疑这是因为与整个数据集的大小相比,标签的正面示例非常小。
这是因为我训练模型的方式做错了,还是因为每个标签的数据分布不对称?
我希望限制负样本的数量,但只是想确保这是正确的方向。
这是我用于每个分类器的代码。我为每个标签都有一个分类器。
self.w1 = tf.Variable(tf.truncated_normal([embedding_size, hidden_size],-0.1,0.1), dtype=tf.float32, name="weight1")
self.b1 = tf.Variable(tf.zeros([hidden_size]), dtype=tf.float32, name="bias1")
self.o1 = tf.sigmoid(tf.matmul(embed,self.w1) + self.b1)
self.w2 = tf.Variable(tf.truncated_normal([hidden_size,2],-0.1,0.1), dtype=tf.float32, name="weight2")
self.b2 = tf.Variable(tf.zeros([1]), dtype=tf.float32, name="bias2")
self.logits = tf.matmul(self.o1, self.w2) + self.b2
self.prediction = tf.nn.softmax(self.logits, name="prediction")
self.loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=self.logits, labels=labels))
self.optimizer = tf.train.AdamOptimizer(1e-3).minimize(self.loss)
编辑: 使用带有 sigmoid_cross_entropy_with_logits 的简单多标签分类器后,它仍然收敛到零。我发布了此版本的代码,以防有帮助:
self.inp_x = tf.placeholder(shape=[None], dtype=tf.int32, name="inp_x")
self.labels = tf.placeholder(shape=[None,num_labels], dtype=tf.float32, name="labels")
self.embeddings = tf.placeholder(shape=[vocabulary_size,embedding_size], dtype=tf.float32,name="embeddings")
self.embed = tf.nn.embedding_lookup(self.embeddings, self.inp_x)
self.w1 = tf.Variable(tf.truncated_normal([embedding_size, hidden_size],-0.1,0.1), dtype=tf.float32, name="weight1")
self.b1 = tf.Variable(tf.zeros([hidden_size]), dtype=tf.float32, name="bias1")
self.o1 = tf.sigmoid(tf.matmul(self.embed,self.w1) + self.b1)
self.w2 = tf.Variable(tf.truncated_normal([hidden_size,num_labels],-0.1,0.1), dtype=tf.float32, name="weight2")
self.b2 = tf.Variable(tf.zeros([num_labels]), dtype=tf.float32, name="bias2")
self.logits = tf.matmul(self.o1, self.w2) + self.b2
self.prediction = tf.sigmoid(self.logits, name='prediction')
self.loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits = self.logits, labels = self.labels))
self.optimizer = tf.train.AdamOptimizer(1e-3).minimize(self.loss)
最佳答案
由于您没有提到实际的数据分布,因此很难猜测问题是出在您的代码还是数据集。但是,您可以尝试喂养一组均匀分布在各个类别中的集合并检查结果。如果问题确实是分布不均,您可以尝试以下操作:
- 通过复制实例来对正类(或少数类)进行过采样。
- 对多数类别进行欠采样。
- 使用加权损失函数。 Tensorflow 有一个名为
weighted_cross_entropy_with_logits
的内置函数,它提供了此功能,尽管仅适用于二元分类,您可以在其中指定要分配少数类别的pos_weight
。 - 您还可以手动过滤负面实例,但此方法需要一些领域知识。
关于machine-learning - 多标签分类收敛到全零,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43428357/