我想将2D稀疏矩阵转换为3D矩阵,因为我需要给它提供conv1d层作为输入,这需要3D张量。
这是conv1d层的输入。
from scipy.sparse import hstack
other_features_train = hstack((X_train_state_ohe, X_train_teacher_ohe, X_train_grade_ohe, X_train_category_ohe, X_train_subcategory_ohe,X_train_price_norm,X_train_number_norm))
other_features_cv = hstack((X_cv_state_ohe, X_cv_teacher_ohe, X_cv_grade_ohe,X_cv_category_ohe,X_cv_subcategory_ohe,X_cv_price_norm,X_cv_number_norm))
other_features_test = hstack((X_test_state_ohe, X_test_teacher_ohe, X_test_grade_ohe,X_test_category_ohe,X_test_subcategory_ohe,X_test_price_norm,X_test_number_norm))
print(other_features_train.shape)
print(other_features_cv.shape)
print(other_features_test.shape)
火车的形状,简历和测试数据
(49041, 101)
(24155, 101)
(36052, 101)
这是我的模型架构。
tf.keras.backend.clear_session()
vec_size = 300
input_model_1 = Input(shape=(300,),name='essay')
embedding = Embedding(vocab_size_essay, vec_size, weights=[word_vector_matrix], input_length = max_length, trainable=False)(input_model_1)
lstm = LSTM(16)(embedding)
flatten_1 = Flatten()(lstm)
input_model_2 = Input(shape=(101, ),name='other_features')
conv_layer1 = Conv1D(32, 3, strides=1, padding='valid', kernel_initializer='glorot_uniform', activation='relu')(input_model_2)
conv_layer2 = Conv1D(32, 3, strides=1, padding='valid', kernel_initializer='glorot_uniform', activation='relu')(conv_layer1)
conv_layer3 = Conv1D(32, 3, strides=1, padding='valid', kernel_initializer='glorot_uniform', activation='relu')(conv_layer2)
flatten_2 = Flatten()(conv_layer3)
concat_layer = concatenate(inputs=[flatten_1, flatten_2],name='concat')
dense_layer_1 = Dense(units=32, activation='relu', kernel_initializer='he_normal', name='dense_layer_1')(concat_layer)
dropout_1 = Dropout(0.2)(dense_layer_1)
dense_layer_2 = Dense(units=32, activation='relu', kernel_initializer='he_normal', name='dense_layer_2')(dropout_1)
dropout_2 = Dropout(0.2)(dense_layer_2)
dense_layer_3 = Dense(units=32, activation='relu', kernel_initializer='he_normal', name='dense_layer_3')(dropout_2)
output = Dense(units=2, activation='softmax', kernel_initializer='glorot_uniform', name='output')(dense_layer_3)
model_3 = Model(inputs=[input_model_1,input_model_2],outputs=output)
尝试提供2d数组时出现此错误。
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-18-44c8f6f0caa7> in <module>
9
10 input_model_2 = Input(shape=(101, ),name='other_features')
---> 11 conv_layer1 = Conv1D(32, 3, strides=1, padding='valid', kernel_initializer='glorot_uniform', activation='relu')(input_model_2)
12 conv_layer2 = Conv1D(32, 3, strides=1, padding='valid', kernel_initializer='glorot_uniform', activation='relu')(conv_layer1)
13 conv_layer3 = Conv1D(32, 3, strides=1, padding='valid', kernel_initializer='glorot_uniform', activation='relu')(conv_layer2)
~\AppData\Local\Programs\Python\Python37\lib\site-packages\tensorflow_core\python\keras\engine\base_layer.py in __call__(self, inputs, *args, **kwargs)
810 # are casted, not before.
811 input_spec.assert_input_compatibility(self.input_spec, inputs,
--> 812 self.name)
813 graph = backend.get_graph()
814 with graph.as_default(), backend.name_scope(self._name_scope()):
~\AppData\Local\Programs\Python\Python37\lib\site-packages\tensorflow_core\python\keras\engine\input_spec.py in assert_input_compatibility(input_spec, inputs, layer_name)
175 'expected ndim=' + str(spec.ndim) + ', found ndim=' +
176 str(ndim) + '. Full shape received: ' +
--> 177 str(x.shape.as_list()))
178 if spec.max_ndim is not None:
179 ndim = x.shape.ndims
ValueError: Input 0 of layer conv1d is incompatible with the layer: expected ndim=3, found ndim=2. Full shape received: [None, 101]
model_3.summary()
model_3.compile(loss = "binary_crossentropy", optimizer=Adam()
编译模型
model_3.compile(loss = "binary_crossentropy", optimizer=Adam(), metrics=["accuracy"])
适合模型
model_3.fit(train_features,y_train_ohe,batch_size=16,epochs=10,validation_data=(cv_features,y_cv_ohe))
train_features = [train_text, other_features_train]
cv_features = [cv_text, other_features_cv]
test_featues = [test_text, other_features_test]
文字功能
train_text = X_train['essay'].tolist()
cv_text = X_cv['essay'].tolist()
test_text = X_test['essay'].tolist()
token = Tokenizer()
token.fit_on_texts(train_text)
vocab_size_essay = len(token.word_index) + 1
print("No. of unique words = ", vocab_size_essay)
encoded_train_text = token.texts_to_sequences(train_text)
encoded_cv_text = token.texts_to_sequences(cv_text)
encoded_test_text = token.texts_to_sequences(test_text)
#print(encoded_test_text[:5])
max_length = 300
train_text = pad_sequences(encoded_train_text, maxlen=max_length, padding='post')
cv_text = pad_sequences(encoded_cv_text, maxlen=max_length, padding='post')
test_text = pad_sequences(encoded_test_text, maxlen=max_length, padding='post')
print("\n")
print(train_text.shape)
print(cv_text.shape)
print(test_text.shape)
文字特征的形状
No. of unique words = 41468
(49041, 300)
(24155, 300)
(36052, 300)
所以,我想在
中重塑(49041,101,1)
(24155,101,1)
(36052,101,1)
请提出建议。
答案 0 :(得分:1)
这里的解决方案要求以下几个概念清晰。我将在以下各节中解释这些概念。
keras
期望作为输入keras
模型进行什么样的修改以允许稀疏输入矩阵numpy
数组转换为3D numpy
数组scipy.sparse.coo_matrix
用于2D numpy
阵列sparse.COO
用于3D numpy
阵列tf.keras
模型的输入一种选择是使用todense()
方法将稀疏输入矩阵转换为非稀疏(密集)格式。这使矩阵成为常规的numpy
数组。参见kaggle讨论[3]和[4]。
另一种选择是通过子类tf.keras.layers.Layer
的类为稀疏和密集输入编写自己的自定义图层。参见这篇文章[2]。
看来tensorflow.keras
现在允许使用稀疏权重进行模型训练。因此,它具有处理稀疏性的能力。您可能需要浏览此方面的文档[{1]。
您可以使用np.newaxis
将另一个轴添加到numpy数组,如下所示。
import numpy as np
## Make a 2D array
a2D = np.zeros((10,10))
# Make a few elements non-zero in a2D
aa = a2D.flatten()
aa[[0,13,41,87,98]] = np.random.randint(1,10,size=5)
a2D = aa.reshape(a2D.shape)
# Make 3D array from 2D array by adding another axis
a3D = a2D[:,:,np.newaxis]
#print(a2D)
print('a2D.shape: {}\na3D.shape: {}'.format(a2D.shape, a3D.shape))
输出:
a2D.shape: (10, 10)
a3D.shape: (10, 10, 1)
话虽如此,请查看参考部分中的链接。
由于稀疏数组具有很少的非零值,因此将常规的numpy数组转换为稀疏数组后,会将其存储为几种稀疏格式:
csr_matrix
:非零值和索引的按行排列csc-matrix
:非零值和索引的列式数组coo-matrix
:具有三列的表格
稀疏矩阵期望2D输入矩阵
但是,上述三种类型的稀疏矩阵的scipy.sparse
实现仅将2D非稀疏矩阵作为输入。
from scipy.sparse import csr_matrix, coo_matrix
coo_a2D = coo_matrix(a2D)
coo_a2D.shape # output: (10, 10)
# scipy.sparse only accepts 2D input matrices
# the following line will throw an !!! ERROR !!!
coo_a3D = coo_matrix(coo_a2D.todense()[:,:,np.newaxis])
是的,您可以使用sparse
库进行此操作。它还支持scipy.sparse
和numpy
数组。要将稀疏矩阵转换为非稀疏(密集)格式(这不是神经网络中的密集层),请使用todense()
方法。
## Installation
# pip install -U sparse
import sparse
## Create sparse coo_matrix from a
# 3D numpy array (dense format)
coo_a3D = sparse.COO(a3D)
## Test that
# coo_a3D == coo made from (coo_a2D + newaxis)
print(
(coo_a3D == sparse.COO(coo_a2D.todense()[:,:,np.newaxis])).all()
) # output: True
## Convert to dense (non-sparse) format
# use: coo_a3D.todense()
print((a3D == coo_a3D.todense()).all()) # output: True
答案 1 :(得分:0)
您可以简单地使用np.reshape
https://numpy.org/doc/1.18/reference/generated/numpy.reshape.html
other_features_train = other_features_train.reshape(other_features_train.shape[0], other_features_train.shape[1], 1)
other_features_cv = other_features_cv.reshape(other_features_cv.shape[0], other_features_cv.shape[1], 1)
other_features_test = other_features_test.reshape(other_features_test.shape[0], other_features_test.shape[1], 1)
此外,您需要更改此行
input_model_2 = Input(shape=(101, 1),name='other_features')
Conv1D需要3d数据,而不是2d。