我正在使用TensorFlow从头开始构建我的第一个神经网络,但我遇到了问题。我试图解决一个多类文本序列分类问题(3个类别)。我一直在按照TensorFlow的教程进行操作,但我不知道哪里出了问题。
我的输入数据如下:
样本 = 文本序列的字符串列表,长度从1到295个词不等
标签 = 295个整数的列表(每个样本一个),这些整数为0、1或2。
我的代码如下:
import tensorflow as tffrom keras.preprocessing.text import Tokenizerfrom keras.preprocessing.sequence import pad_sequencesfrom keras.layers import Embeddingfrom keras import preprocessingfrom keras.models import Sequentialfrom keras.layers import Flatten, Denseimport numpy as np
# 对文本数据进行标记化和向量化以准备嵌入tokenizer = Tokenizer()tokenizer.fit_on_texts(samples)sequences = tokenizer.texts_to_sequences(samples)word_index = tokenizer.word_indexprint(f'找到 {len(word_index)} 个唯一标记。')# one_hot_results = tokenizer.texts_to_matrix(samples, mode='binary')# 设置变量num_samples = len(word_index) # 1499# Input_dim: 这是文本数据中词汇表的大小。input_dim = num_samples # 1499# output_dim: 这是将词嵌入到的向量空间的大小。output_dim = 32 # 教程推荐# max_sequence_length: 这是输入序列的长度max_sequence_length = len(max(sequences, key=len)) # 295# 训练/测试索引分割变量training_samples = round(len(samples)*.8)data = pad_sequences(sequences, maxlen=max_sequence_length)# 预处理标签labels = np.asarray(labels)indices = np.arange(data.shape[0])np.random.shuffle(indices)data = data[indices] # 形状 (499, 295)labels = to_categorical(labels, num_classes=None, dtype='float32')# 创建训练/测试数据(80% 训练,20% 测试)x_train = data[:training_samples]y_train = labels[:training_samples]x_test = data[training_samples:]y_test = labels[training_samples:]# 创建嵌入层,其形状为 [样本中唯一词的数量, 样本中最长样本的长度]# embedding_layer = Embedding(len(word_index)+1, len(max(samples, key=len)))model = Sequential()model.add(Embedding(input_dim, output_dim, input_length=max_sequence_length))model.add(Dense(32, activation='relu'))model.add(Dense(3, activation='softmax'))model.summary()model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])model.fit(x_train, y_train, epochs=10, batch_size=32, validation_data=(x_test, y_test))
基本上,我只是试图将我的文本数据作为标记输入到嵌入层、密集层,然后是用于分类的3个节点的Softmax层。当我运行这个时,我得到了以下错误:
找到 1499 个唯一标记。WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/keras/backend/tensorflow_backend.py:66: The name tf.get_default_graph is deprecated. Please use tf.compat.v1.get_default_graph instead.WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/keras/backend/tensorflow_backend.py:541: The name tf.placeholder is deprecated. Please use tf.compat.v1.placeholder instead.WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/keras/backend/tensorflow_backend.py:4432: The name tf.random_uniform is deprecated. Please use tf.random.uniform instead.Model: "sequential_1"_________________________________________________________________Layer (type) Output Shape Param # =================================================================embedding_1 (Embedding) (None, 295, 32) 47968 _________________________________________________________________dense_1 (Dense) (None, 295, 32) 1056 _________________________________________________________________dense_2 (Dense) (None, 295, 3) 99 =================================================================Total params: 49,123Trainable params: 49,123Non-trainable params: 0_________________________________________________________________WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/keras/optimizers.py:793: The name tf.train.Optimizer is deprecated. Please use tf.compat.v1.train.Optimizer instead.WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/keras/backend/tensorflow_backend.py:3576: The name tf.log is deprecated. Please use tf.math.log instead.---------------------------------------------------------------------------ValueError Traceback (most recent call last)<ipython-input-8-94cb754412aa> in <module>() 49 epochs=10, 50 batch_size=32,---> 51 validation_data=(x_test, y_test))2 frames/usr/local/lib/python3.6/dist-packages/keras/engine/training_utils.py in standardize_input_data(data, names, shapes, check_batch_axis, exception_prefix) 129 ': expected ' + names[i] + ' to have ' + 130 str(len(shape)) + ' dimensions, but got array '--> 131 'with shape ' + str(data_shape)) 132 if not check_batch_axis: 133 data_shape = data_shape[1:]ValueError: Error when checking target: expected dense_2 to have 3 dimensions, but got array with shape (399, 3)
回答:
我需要更多信息来解决您面临的问题。但我可以告诉您哪里出了问题。
您的目标集大小为 [399, 3]
。然而,您的模型摘要如下所示。
Model: "sequential_9"_________________________________________________________________Layer (type) Output Shape Param # =================================================================embedding_5 (Embedding) (None, 295, 50) 5000 _________________________________________________________________dense_12 (Dense) (None, 295, 32) 1632 _________________________________________________________________dense_13 (Dense) (None, 295, 3) 99 =================================================================
您可以看到,尽管您有一个二维的标签列表,但您的模型期望目标集有三维。
现在解决这个问题,嗯…那就是另一回事了。让我们看看我们的选择。
每个样本恰好有295个词,并且有399个这样的样本。
如果您100%确定您的数据中的每个序列都是295个元素长,您可以通过添加一个 Flatten()
层来简单地解决这个问题。然而,请记住,这将增加您模型中的参数数量,包括,
- 您的序列长度
- 嵌入大小
model = Sequential()model.add(Embedding(input_dim, output_dim, input_length=max_sequence_length, input_shape=(295,)))#model.add(lambda x: tf.reduce_mean(x, axis=1))model.add(Flatten())model.add(Dense(32, activation='relu'))model.add(Dense(3, activation='softmax'))model.summary()
您有399个样本,但每个样本可以有1到295个任意数量的项目
现在您的输入可以有不同的长度。因此,您需要相应地为第一层定义 input_shape
参数。
第二个问题是您的 Embedding
层会产生不同大小的输出(取决于序列长度)。但密集层不能接受可变大小的输入。因此,您需要在中间进行某种“压缩”转换。通常与 Embeddings
一起工作良好的一个是取平均值。您可以这样做:
model = Sequential()model.add(Embedding(input_dim, output_dim, input_length=max_sequence_length, input_shape=(None,)))model.add(Lambda(lambda x: tf.reduce_mean(x, axis=1)))model.add(Flatten())model.add(Dense(32, activation='relu'))model.add(Dense(3, activation='softmax'))model.summary()