Tensorflow数值错误:logits和labels必须具有相同的形状((None,2)vs(None,1))

3

我刚接触机器学习,想从keras入手。我正在使用二元交叉熵将电影评论分类为三类(正面为1,中性为0,负面为-1)。但是,当我试图用tensorflow estimator包装keras模型时,会出现错误。
代码如下:

import tensorflow as tf
import numpy as np
import pandas as pd
import numpy as K

csvfilename_train = 'train(cleaned).csv'
csvfilename_test = 'test(cleaned).csv'

# Read .csv files as pandas dataframes
df_train = pd.read_csv(csvfilename_train)
df_test = pd.read_csv(csvfilename_test)

train_sentences  = df_train['Comment'].values
test_sentences  = df_test['Comment'].values

# Extract labels from dataframes
train_labels = df_train['Sentiment'].values
test_labels = df_test['Sentiment'].values

vocab_size = 10000
embedding_dim = 16
max_length = 30
trunc_type = 'post'
oov_tok = '<OOV>'

from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences

tokenizer = Tokenizer(num_words = vocab_size, oov_token = oov_tok)
tokenizer.fit_on_texts(train_sentences)
word_index = tokenizer.word_index
sequences = tokenizer.texts_to_sequences(train_sentences)
padded = pad_sequences(sequences, maxlen = max_length, truncating = trunc_type)

test_sequences = tokenizer.texts_to_sequences(test_sentences)
test_padded = pad_sequences(test_sequences, maxlen = max_length)

model = tf.keras.Sequential([
    tf.keras.layers.Embedding(vocab_size, embedding_dim, input_length = max_length),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(6, activation = 'relu'),
    tf.keras.layers.Dense(2, activation = 'sigmoid'),
])
model.compile(loss = 'binary_crossentropy', optimizer = 'adam', metrics = ['accuracy'])

num_epochs = 10
model.fit(padded, train_labels, epochs = num_epochs, validation_data = (test_padded, test_labels))

错误信息如下:

---> 10 model.fit(padded, train_labels, epochs = num_epochs, validation_data = (test_padded, test_labels))

最后,这个:
ValueError: logits and labels must have the same shape ((None, 2) vs (None, 1))

对标签进行独热编码 - Rahul Vishwakarma
@Rahul Vishwakarma 我的标签默认为-1、0、1。我是否仍需要进行独热编码?正如我所说,我对机器学习还很陌生,请提供更多信息。 - user13959036
1个回答

11

你的代码存在几个问题。

  1. 你使用了错误的损失函数。二元交叉熵损失函数用于二分类问题,但是这里进行的是多类别分类(3个类别-正面、负面、中性)。
  2. 在最后一层使用sigmoid激活函数是错误的,因为sigmoid将logit值映射到0和1之间的范围(然而,你的类标签是0、1和-1)。这清楚地表明,由于sigmoid函数(只能映射0和1之间的值),网络永远无法预测负值,因此永远学不会预测负类。

正确的方法是将其视为一个多类别分类问题,并在你的最后一个Dense层中使用带有softmax激活的分类交叉熵损失以及3个单元(每个类别一个)。请注意,对于分类交叉熵损失必须使用独热编码的标签,而可以使用整数标签与稀疏分类交叉熵损失一起使用。

下面是一个使用分类交叉熵损失的示例。

tf.keras.layers.Dense(3, activation = 'softmax')

注意以下三个更改:

  • 损失函数更改为分类交叉熵

  • 最后一个Dense层中的单元数为3

  • 需要对标签进行独热编码,并且可以使用tf.one_hot进行处理

    tf.one_hot(train_labels, 3)

.


4
Sigmoid函数可用于多标签-多类别问题。 - user8276908

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接