NumPy - 4-мерный массив выглядит как 2-мерный - PullRequest
1 голос
/ 10 марта 2020

Я работаю над моделью разрешения привязки и пытаюсь передать большую матрицу данных во входной слой моей CNN. В целях иллюстрации я обрезал свои данные для работы с более управляемыми числами.

Функция форматирования данных

EMBEDDING_DIM = 400

...

@staticmethod
def get_train_data(data: DefaultDict[ClusteredDictKey, PreCoCoreferenceDatapoint], embedding_model) -> Tuple[List[Tensor], List[Tensor]]:
    """
    (n_samples, n_words, n_attributes (word embedding, pos, etc))
    [ [ [ word_embedding, pos ] ] ]

    xtrain[sentence_sample][word_position][attribute]
    xtrain[0][0] -> first word's attributes in first sentence
    xtrain[37][5] -> sixth word's attributes in 38th sentence
    xtrain[0][0][0] -> word_embedding
    xtrain[0][0][1] -> pos one-hot encoding
    """
    xtrain = []
    ytrain = []
    pos_onehot = PreCoParser.get_pos_onehot() # dictionary mapping POS to one-hot encoding

    for key, value in data.items():
        training_data = []

        sentence_embeddings = PreCoParser.get_embedding_for_sent(key.sentence, embedding_model) # Returns tensor (ndarray) of shape: (tokens_in_sent, EMBEDDING_DIM)
        pos = PreCoParser.get_pos_onehot_for_sent(key.sentence, pos_onehot) # Returns tensor (ndarray) of shape: (45,)

        assert sentence_embeddings.shape == (len(key.sentence), EMBEDDING_DIM)
        assert pos.shape == (len(key.sentence), 45)

        for i, embedding in enumerate(sentence_embeddings):
            training_data.append(np.asarray([embedding, np.asarray(pos[i])]))

        cluster_indices = list(sum([cluster.indices for cluster in value], ()))
        # Delete every third element to remove sentence index
        del cluster_indices[0::3]

        if len(training_data) > 0:
            xtrain.append(np.asarray(training_data))
            ytrain.append(np.asarray(cluster_indices) / len(key.sentence)) # normalize output data

    gc.collect()
    return (np.asarray(xtrain), np.asarray(ytrain))

Сокращенный выпуск

Короче говоря, у меня есть NumPy массив, на котором я могу успешно выполнить следующее утверждение:

assert self.xtrain[0][0][0].shape == (EMBEDDING_DIM,)

, подразумевая, по крайней мере для меня, что массив содержит 4 измерения, а последний вектор содержит число элементов EMBEDDING_DIM (400 в моем case).

Однако выполнение следующего кода дает странный результат:

>>> self.xtrain.shape
(500,) 
>>> self.xtrain[0].shape # on sentence with 11 words
(11,2)
>>> self.xtrain[0][0].shape # two attributes
(2,)
>>> self.xtrain[0][0][0].shape
(400,)
>>> self.xtrain[0][0][1].shape
(45,)

, где 500 относится к моему усеченному количеству выборок (и все выходные данные верны с тем, что я ожидал ). Кроме того, при подаче этих данных через простой входной слой Keras Conv2D меня встречает следующая ошибка:

    self.model.fit(self.xtrain, self.ytrain, epochs=1)
  File "/usr/local/lib/python3.7/site-packages/keras/engine/training.py", line 1154, in fit
    batch_size=batch_size)
  File "/usr/local/lib/python3.7/site-packages/keras/engine/training.py", line 579, in _standardize_user_data
    exception_prefix='input')
  File "/usr/local/lib/python3.7/site-packages/keras/engine/training_utils.py", line 135, in standardize_input_data
    'with shape ' + str(data_shape))
ValueError: Error when checking input: expected conv2d_1_input to have 4 dimensions, but got array with shape (499, 1)

Я с удовольствием выложу больше кода, если потребуется, но любая помощь в этой текущей точке будет с благодарностью!

Ответы [ 2 ]

1 голос
/ 10 марта 2020

Я хотел бы оставить это как комментарий, но, поскольку моя репутация не> 50, это не позволило бы мне :(

Единственное предположение, которое я делаю с ошибкой, это то, что для модели .fit () вы потеряли ytrain с xtrain, так как для ytrain я мог бы представить ввод формы (499, 1). Боюсь, мне понадобится больше кода для того, когда модель подается с входные данные и метки.

0 голосов
/ 10 марта 2020

Для тех, кто может найти это в будущем, hpaulj частично правильно указал на эту проблему. Другая проблема, с которой я столкнулся, была с моим анализом данных. В конечном итоге я преобразовал входные данные в NumPy массив формы (n_training_samples, INPUT_MAXLEN, 2, EMBEDDING_DIM). Как только я нормализовал структуру матрицы и удалил массивы с помощью dtype='object', все заработало отлично.

Я обратился на этот сайт, чтобы эффективно инициализировать пустой массив NumPy: http://akuederle.com/create-numpy-array-with-for-loop

Финальный код:

EMBEDDING_DIM = 400

...
@staticmethod
def get_train_data(data: DefaultDict[ClusteredDictKey, PreCoCoreferenceDatapoint], inputmaxlen: int, embedding_model) -> Tuple[List[Tensor], List[Tensor]]:
    """
    (n_samples, n_words, n_attributes (word embedding, pos, etc))
    [ [ [ word_embedding, pos ] ] ]

    xtrain[sentence_sample][word_position][attribute]
    xtrain[37][5] -> sixth word's attributes in 38th sentence (np.ndarray containing two np.ndarrays)
    xtrain[0][0][0] -> word_embedding (np.ndarray)
    xtrain[0][0][1] -> pos one-hot encoding (np.ndarray)
    """
    xtrain = np.empty((len(data), inputmaxlen, 2, EMBEDDING_DIM))
    ytrain = []
    pos_onehot = PreCoParser.get_pos_onehot()

    for i, (key, value) in enumerate(data.items()):
        training_data = []

        sentence_embeddings = PreCoParser.get_embedding_for_sent(key.sentence, embedding_model)
        pos = PreCoParser.get_pos_onehot_for_sent(key.sentence, pos_onehot)
        assert sentence_embeddings.shape == (len(key.sentence), EMBEDDING_DIM)
        assert pos.shape == (len(key.sentence), 45)

        for j, word_embeddings in enumerate(sentence_embeddings):
            pos_embeddings = sequence.pad_sequences([pos[j]], maxlen=EMBEDDING_DIM, dtype='float32', padding='post')[0]
            xtrain[i][j][0] = word_embeddings
            xtrain[i][j][1] = pos_embeddings

        cluster_indices = list(sum([cluster.indices for cluster in value], ()))
        # Delete every third element to remove sentence index
        del cluster_indices[0::3]

        ytrain.append(np.asarray(cluster_indices) / len(key.sentence))

    gc.collect()
    return (np.asarray(xtrain, dtype='float32'), np.asarray(ytrain, dtype='float32'))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...