将二维稀疏矩阵转换为三维矩阵

2024-09-06 07:12:37 发布

您现在位置:Python中文网/ 问答频道 /正文

我想将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)

列车形状、cv和试验数据

(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) 

请建议怎么做


Tags: textnametestlayerinputmodeltrainkernel
2条回答

您只需使用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需要的是三维数据,而不是二维数据

解决方案

这里的解决方案需要明确以下几个概念。我将解释这些概念 在下面的章节中

  • {}期望输入什么
  • 可以对keras模型进行何种修改以允许稀疏输入矩阵
  • 将2Dnumpy数组转换为3Dnumpy数组
  • 使用在稀疏和非稀疏(或密集)数组之间来回转换
    • scipy.sparse.coo_matrix用于2Dnumpy数组
    • sparse.COO用于3Dnumpy数组

使用稀疏矩阵作为tf.keras模型的输入

  • 一个选项是使用以下命令将稀疏输入矩阵转换为非稀疏(密集)格式: todense()方法。这使得矩阵成为一个规则的numpy数组。参见kaggle的讨论, [3][4]

  • 另一种选择是通过以下方式为稀疏和密集输入编写自己的自定义层: 子类化tf.keras.layers.Layer类。见这篇文章[2]

  • 看起来tensorflow.keras现在允许使用稀疏权重进行模型训练。所以 在某些地方,它有能力处理稀疏性。您可能需要浏览文档, [1]在这方面

向numpy阵列添加新轴

您可以使用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:一个有三列的表
    • 划船
    • 纵队
    • 非零值

Scipy稀疏矩阵需要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])

来自3D非稀疏输入矩阵的稀疏矩阵

是的,您可以使用^{}库执行此操作。 它还支持scipy.sparsenumpy数组。将稀疏矩阵转换为 非稀疏(密集)格式(这不是神经网络中的密集层),使用 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

scipy.sparse.coo_matrix vs. sparse.COO

Source

PyTorch:torch.sparse🔥 ⭐

PyTorch库还提供了使用Space张量的方法

参考资料

  1. Train sparse TensorFlow models with Keras

  2. How to design deep learning models with sparse inputs in Tensorflow Keras

  3. Neural network for sparse matrices

  4. Training Neural network with scipy sparse matrix?

  5. Documentation of ^{} library

相关问题 更多 >