可以使用帮助为 Keras SimpleRNN 正确格式化数据

Could use help formatting data correctly for a Keras SimpleRNN

我在将数据转换为适合 simpleRNN 的正确格式时遇到了一些困难,或者我在正确定义模型方面遇到了困难。我希望有人能发现问题?

我正在尝试class对长度为 278 的向量列表 X 进行化验,其中包含从长度为 9026 的字典 vocab 中选择的整数值作为属于到 class 0 或 1。这是我的输入数据的示例:

X=[[1,822,773,54,51,...],[2,3,1,41,3,...],[121,17,311,4,12,...],...]
y=[0,1,1,...]

例如 np.array(X).shape=(1000,278)len(y)=1000 我的模型是:

model.add(L.InputLayer([None],dtype='int32'))
model.add(L.Embedding(input_dim=len(vocab)+1,\
                      output_dim=64,\
                      input_length=278))
model.add(L.SimpleRNN(64,return_sequences=True))
model.add(L.TimeDistributed(L.Dense(1,activation='softmax')))
model.compile(optimizer='adam',\
              loss='categorical_crossentropy',\
              metrics=['accuracy']
             )
print(model.summary())

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding_8 (Embedding)      (None, 278, 64)           577728    
_________________________________________________________________
simple_rnn_7 (SimpleRNN)     (None, 278, 64)           8256      
_________________________________________________________________
time_distributed_7 (TimeDist (None, 278, 1)            65        
=================================================================
Total params: 586,049
Trainable params: 586,049
Non-trainable params: 0
_________________________________________________________________
None

我准备如下:

X=np.array(X)
y=keras.utils.to_categorical(y)

frac=0.3
random_state=42
X_train,X_tmp,y_train,y_tmp = \
    train_test_split(X,y,test_size=frac,random_state=random_state,\
                         stratify=y)
train=(X_train,y_train)
test=(X_tmp,y_tmp)

当我运行模特时:

model.fit(train[0],train[1],verbose=0,\
              batch_size=batch_size,\
              epochs=epochs,validation_data=test)

我收到以下错误:

ValueError: Error when checking target: expected time_distributed_1 
to have 3 dimensions, but got array with shape (5450, 2)

如果我将输入数据更改为

train=(X_train,y_train[:,:,np.newaxis])
test=(X_tmp,y_tmp[:,:,np.newaxis])

和 运行 模型,我得到这个错误:

ValueError: Error when checking target: expected time_distributed_1 
to have shape (278, 2) but got array with shape (2, 1)

好吧,很明显我有问题,因为我的最终致密层正在寻找形状 278 而不是 2。所以我尝试了这个模型但没有明确定义 input_length:

model.add(L.InputLayer([None],dtype='int32'))
model.add(L.Embedding(input_dim=len(vocab)+1,\
                      output_dim=64))
model.add(L.SimpleRNN(64,return_sequences=True))
model.add(L.TimeDistributed(L.Dense(1,activation='softmax')))
model.compile(optimizer='adam',\
              loss='categorical_crossentropy',\
              metrics=['accuracy']
             )
print(model.summary())

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding_10 (Embedding)     (None, None, 64)          577728    
_________________________________________________________________
simple_rnn_9 (SimpleRNN)     (None, None, 64)          8256      
_________________________________________________________________
time_distributed_9 (TimeDist (None, None, 2)           130       
=================================================================
Total params: 586,114
Trainable params: 586,114
Non-trainable params: 0

当我 运行 模型时,我得到

ValueError: Error when checking target: expected time_distributed_9
to have shape (None, 2) but got array with shape (2, 1)

我很困惑。谁能帮我诊断一下?

为什么要使用 TimeDistributed?你根本不需要那个。对于每个长度为 278 的向量,您只想预测一个介于 0 和 1 之间的数字。因此最后一层的输出形状应该是 (None,1)。删除 SimpleRNN 层的 return_sequences 参数,因为 well.You 也不需要它。像这样:

model.add(L.SimpleRNN(64))
model.add(L.Dense(1,activation='sigmoid'))

此外,你应该使用'sigmoid'作为激活函数,使最后一层输出一个介于0和1之间的值。并将'categorical_crossentropy'更改为'binary_crossentropy'。您也不需要将 y 转换为分类。它已经是 zeros 和 ones 了,没关系(只需将其转换为 numpy 数组);记住,你在这里做二分类。

另外,使用第一个模型。您的第二个模型没有意义,因为您提到所有输入向量的长度都相同(即 278)。

最后一点:删除 InputLayer。这是多余的。您已经在嵌入层中设置了输入形状。