ValueError: Error when checking input: expected input_1 to have 3 dimensions

ValueError: Error when checking input: expected input_1 to have 3 dimensions

我实现了一个 python 脚本,我尝试在我传递的 2 个特征(句子、概率)上训练 CNN 并预测句子是对还是错。这类似于该领域流行的情感分析任务。

我最初为我命名为 triples 的句子生成词嵌入。每个 triple/sentence 恰好有 5 个单词。因此,词嵌入如下所示。

Number of lines 1860
[[2, 194, 21, 17, 227], [12, 228, 22, 17, 229], [2, 230, 21, 17, 229], ...]
Shape of triple:  (1860, 5)
Shape of truth:  (1860,)

三元组是句子,真理是目标class。

在我的数据集中,我有 3 个字段(包括目标 class、truth),其中有以下 2 个作为我想用来训练模型的特征:

因此,我定义了一个多输入 CNN 模型,其中第一个输入是词嵌入向量,第二个输入是概率。然后我合并这两个输入,到目前为止,一切似乎都正常。

However, I am having trouble with passing both the arrays (word embedding vector array and the probabilities array which I have defined as stv.

我尝试如下所示拟合这两个特征。

model.fit([X_train_pad,np.array(stv[:-num_validation_samples])], y_train, batch_size=128, epochs=25, validation_data=([X_test_pad,np.array(stv[-num_validation_samples:])], y_test), verbose=2)

但是,我不断收到以下错误。

ValueError: Error when checking input: expected input_1 to have 3 dimensions, but got array with shape (1302, 5)

Python 实施

import warnings
warnings.filterwarnings("ignore")
import string
from nltk.tokenize import word_tokenize
from nltk.corpus import stopwords
import numpy as np
import pandas as pd
from tensorflow.python.keras.preprocessing.text import Tokenizer
from sklearn.metrics import precision_recall_fscore_support
from termcolor import colored
from keras.preprocessing.sequence import pad_sequences
from keras.models import Model
from keras.layers import Dense
from keras.layers import Embedding, Input, Conv1D, GlobalMaxPooling1D, concatenate


# define documents
df = pd.DataFrame()
df = pd.read_csv('../../data/triple_with_stv.csv')
sentence_lines = list()
lines = df['triple'].values.tolist()
stv = df['stv'].values.tolist()

for line in lines:
    tokens = word_tokenize(line)
    tokens = [w.lower() for w in tokens]
    table = str.maketrans('','',string.punctuation)
    stripped = [w.translate(table) for w in tokens]
    words = [word for word in stripped if word.isalpha()]
    stop_words = set(stopwords.words('english'))
    words = [w for w in words if not w in stop_words]
    sentence_lines.append(words)

print('Number of lines', len(sentence_lines))
EMBEDDING_DIM = 200

#Vectorize the text samples into a S2 integer tensor
tokenizer_obj = Tokenizer()
tokenizer_obj.fit_on_texts(sentence_lines)
sequences = tokenizer_obj.texts_to_sequences(sentence_lines)

print(colored(sequences,'green'))

#define vocabulary size
vocab_size = len(tokenizer_obj.word_index) + 1

# print(colored(sequences,'green'))

#pad sequences
word_index = tokenizer_obj.word_index
max_length = 5

triple_pad = pad_sequences(sequences, maxlen=max_length)
truth = df['truth'].values
print('Shape of triple tensor: ', triple_pad.shape)
print('Shape of truth tensor: ', truth.shape)

#map embeddings from loaded word2vec model for each word to the tokenizer_obj.word_index vocabulary & create a wordvector matrix

num_words = len(word_index)+1

print(colored(num_words,'cyan'))

# first input model
emb = Embedding(vocab_size, EMBEDDING_DIM, input_length=max_length)
input_shape = triple_pad.shape
print(colored('Input SHAPE for sequences','cyan'))
# print(input_shape)
visible1 = Input(shape=input_shape)
conv11 = Conv1D(128, 4, activation='relu')(visible1)
pool11 = GlobalMaxPooling1D()(conv11)
den1 = Dense(10, activation='relu')(pool11)

# second input model
input_shape_stv = np.array(stv).shape
print(colored("Input Shape for stv: ",'cyan'))
print(input_shape_stv)
visible2 = Input(shape=input_shape_stv)
den2 = Dense(10, activation='relu')(visible2)

# # merge input models
merge = concatenate([den1, den2])

# interpretation model
hidden1 = Dense(10, activation='relu')(merge)
hidden2 = Dense(10, activation='relu')(hidden1)
output = Dense(1, activation='sigmoid')(hidden2)
model = Model(inputs=[visible1, visible2], outputs=output)

model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
print(model.summary())

#Split the data into training set and validation set
VALIDATION_SPLIT = 0.3

indices = np.arange(triple_pad.shape[0])
np.random.shuffle(indices)
triple_pad = triple_pad[indices]
truth = truth[indices]
num_validation_samples = int(VALIDATION_SPLIT * triple_pad.shape[0])

X_train_pad = triple_pad[:-num_validation_samples]
y_train = truth[:-num_validation_samples]
X_test_pad = triple_pad[-num_validation_samples:]
y_test = truth[-num_validation_samples:]

print('Shape of X_train_pad tensor: ',X_train_pad.shape)
print('Shape of y_train tensor: ',y_train.shape)
print('Shape of X_test_pad tensor: ',X_test_pad.shape)
print('Shape of y_test tensor: ',y_test.shape)

print(colored('Training...','green'))

history = model.fit([X_train_pad,np.array(stv[:-num_validation_samples])], y_train, batch_size=128, epochs=25, validation_data=([X_test_pad,np.array(stv[-num_validation_samples:])], y_test), verbose=2)

y_pred = model.predict_classes(x=[X_test_pad,np.array(stv[-num_validation_samples:])])
metrics = precision_recall_fscore_support(y_test, y_pred, average='weighted')

print()
print(colored("Precision: ",'green'),colored(metrics[0],'blue'))
print(colored("Recall: ",'green'),colored(metrics[1],'blue'))
print(colored("F1: ",'green'),colored(metrics[2],'blue'))

任何关于如何解决这个问题的建议将不胜感激。

Keras 中的 Conv1D 层预计由 3D 张量提供(Batch_size、size1、size2)
通过阅读您的错误,您似乎只提供了一个二维张量。

如果 X_train_pad 是 (1302, 5) 我想它是 (5, 1) 嵌入数组的 1302 个样本。

因此,在拟合模型之前尝试执行以下操作:

X_train_pad = np.expand_dims(X_train_pad, -1)

根据我收到的一些指导,似乎没有必要对概率 (psl) 层进行任何训练。因此,只有嵌入层需要使用池化进行训练,然后 psl 层可以通过管道传输到嵌入层并适合模型。

因此,这是工作脚本中模型的修改部分。

定义模型层

input1 = layers.Input(shape=(max_length,))
embedding = layers.Embedding(vocab_size, EMBEDDING_DIM, input_length=max_length)(input1)

cov = layers.Conv1D(128, 4, activation='relu')(embedding)
pooling = layers.GlobalMaxPooling1D()(cov)

input2 = layers.Input(shape=(1,))

concat = layers.Concatenate(axis=-1)([pooling, input2])

l1 = layers.Dense(10, activation='relu')(concat)
out = layers.Dense(1, activation='sigmoid')(l1)

model = models.Model(inputs=[input1, input2], outputs=[out])
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])

拆分和拟合模型

VALIDATION_SPLIT = 0.3

indices = np.arange(triple_pad.shape[0])
np.random.shuffle(indices)
triple_pad = triple_pad[indices]
truth = truth[indices]
num_validation_samples = int(VALIDATION_SPLIT * triple_pad.shape[0])

X_train_pad = triple_pad[:-num_validation_samples]
X_train_psl = stv[:-num_validation_samples]
y_train = truth[:-num_validation_samples]

X_test_pad = triple_pad[-num_validation_samples:]
X_test_psl = stv[-num_validation_samples:]
y_test = truth[-num_validation_samples:]

print('Shape of X_train_pad tensor: ', X_train_pad.shape)
print('Shape of y_train tensor: ', y_train.shape)
print('Shape of X_test_pad tensor: ', X_test_pad.shape)
print('Shape of y_test tensor: ', y_test.shape)

print(colored('Training...', 'green'))

history = model.fit([X_train_pad, X_train_psl], y_train, batch_size=128, epochs=25,
                    validation_data=([X_test_pad, X_test_psl], y_test), verbose=2)

希望这对遇到尝试在深度学习模型中使用多个输入的问题的其他人有所帮助。