tensorflow conv1d, в этом коде, почему я не могу использовать kernel_size 2 или 3

#python #tensorflow #keras #deep-learning #conv-neural-network

#python #tensorflow #keras #глубокое обучение #conv-нейронная сеть

Вопрос:

У меня есть этот код

 df = pd.DataFrame()
df['tfidf'] = [[[np.random.uniform(0,1, 30)],[np.random.uniform(0,1, 30)]],
              [[np.random.uniform(0,1, 30)],[np.random.uniform(0,1, 30)]],
              [[np.random.uniform(0,1, 30)],[np.random.uniform(0,1, 30)]],
              [[np.random.uniform(0,1, 30)],[np.random.uniform(0,1, 30)]]]

df['is_similar'] = np.random.randint(0,2, 4)

def getmodel():
    x_input = keras.Input(shape=(2, 30), name="article1")  # Variable-length sequence of ints
    conv1d_1 = layers.Conv1D(64, 1, activation='relu')(x_input)
    flat = layers.Flatten()(conv1d_1)
    dense1 = layers.Dense(1024, name="dense1", activation="relu")(flat)
    encoder_conv_dense2 = layers.Dense(256, name="40_dense", activation="relu")(dense1)
    encoder_conv_dense3 = layers.Dense(1, name="similar_result", activation="sigmoid")(encoder_conv_dense2)

    model = keras.Model(
        inputs=x_input,
        outputs=encoder_conv_dense3,
    )

    return model


model = getmodel()
model.compile('adam', 'binary_crossentropy')
history = model.fit(
    {"article1": np.stack(df['tfidf'], 0)},
    {"similar_result": df['is_similar']},
    epochs=3,
)
  

поскольку у меня есть для каждого ввода матрица из 2 строк и 30 столбцов, я полагаю, что kernel_size может быть 2,3,5,9 … < 30, но в этой конкретной модели единственным вариантом, который мне позволяет, является kernel_size=1, другие разные значения генерируют следующую ошибку:

пример использования

conv1d_1 = слои.Conv1D(64, 3, activation=’relu’)(x_input)

 raise ValueError(str(e))
ValueError: Negative dimension size caused by subtracting 3 from 2 for '{{node conv1d/conv1d}} = Conv2D[T=DT_FLOAT, data_format="NHWC", dilations=[1, 1, 1, 1], explicit_paddings=[], padding="VALID", strides=[1, 1, 1, 1], use_cudnn_on_gpu=true](conv1d/conv1d/ExpandDims, conv1d/conv1d/ExpandDims_1)' with input shapes: [?,1,2,30], [1,3,30,64].
  

Может кто-нибудь, пожалуйста, помочь мне с этим недоразумением?

Ответ №1:

Я не совсем понимаю, как ваша модель должна обрабатывать данные, но вам нужен дополнительный функциональный канал в дополнение к измерению, которое имеет 30 элементов, для которых вы выполняете свертку. Возможно, вы хотите обрабатывать строки как своего рода подпакет последовательностей, для этого keras имеет TimeDistributed . Вот предупреждение: у вас есть 1 в качестве измерения перед последним в ваших данных, но вы устанавливаете 2 для ввода.

Если я неправильно понял вашу идею, вы можете начать вносить изменения отсюда.

 import pandas as pd
import tensorflow.keras as keras
import numpy as np
from tensorflow.keras import layers
from tensorflow.keras import backend as K

df = pd.DataFrame()
df['tfidf'] = [[[np.random.uniform(0,1, 30)],[np.random.uniform(0,1, 30)]],
              [[np.random.uniform(0,1, 30)],[np.random.uniform(0,1, 30)]],
              [[np.random.uniform(0,1, 30)],[np.random.uniform(0,1, 30)]],
              [[np.random.uniform(0,1, 30)],[np.random.uniform(0,1, 30)]]]

df['is_similar'] = np.random.randint(0,2, 4)


def getmodel():
    x_input = keras.Input(shape=(2, 30), name="article1")  # Variable-length sequence of ints
    # add one feature channel
    x_input1 = keras.layers.Lambda(lambda x: K.expand_dims(x,-1))(x_input)
    # timedistributed makes second dimension after batch dim sort of second batch dimension
    conv1d_1 = keras.layers.TimeDistributed(layers.Conv1D(64, 3, activation='relu', padding='same'))(x_input1)
    # will have 64 feature channels
    #print(conv1d_1)
    #Tensor("time_distributed/Reshape_1:0", shape=(?, 2, 30, 64), dtype=float32)
    flat = layers.Flatten()(conv1d_1)
    dense1 = layers.Dense(1024, name="dense1", activation="relu")(flat)
    encoder_conv_dense2 = layers.Dense(256, name="40_dense", activation="relu")(dense1)
    encoder_conv_dense3 = layers.Dense(1, name="similar_result", activation="sigmoid")(encoder_conv_dense2)

    model = keras.Model(
        inputs=x_input,
        outputs=encoder_conv_dense3,
    )

    return model


model = getmodel()
model.compile('adam', 'binary_crossentropy')
# removed 1 dimension from array shape # (4, 2, 1, 30)
history = model.fit(
    {"article1": np.stack(df['tfidf'], 0).squeeze()},
    {"similar_result": df['is_similar']},
    epochs=3,
)
  

Комментарии:

1. Я не понимаю, зачем мне нужно добавлять каналы. позвольте мне попытаться объяснить, что в каждом вводе у меня есть матрица из 2 строк и 30 столбцов, каждая строка — это отдельная метрика, которую я хочу сравнить с conv1d. Я имею в виду, что у меня есть матрица, в которой каждая строка имеет вид [[metric1(длина 30), metric2(длина 30)] для каждого ввода, поэтому я пишу «Ввод (форма =(2, 30)». Решение добавления канала работает хорошо, просто, не могли бы вы помочь мне понять, что я сделал не так и почему мне нужно добавить «x_input1 = keras. слои. Лямбда (лямбда x: K.expand_dims(x,-1))(x_input) «. заранее спасибо

2. @FerminPitol Извините, я не понимаю, как вы хотите сравнить две серии со сверткой и каким должен быть ее результат. Технически, 1d свертка требует ввода, чтобы иметь как минимум два измерения: (..., datapoints, input_feature_channels) . Таким образом, алгоритм свертки применяется для скользящего окна, перемещающегося по всем точкам данных, каждой из формы (1, input_feature_channels) . Количество выходных данных будет равно количеству выходных каналов (количеству различных фильтров для свертки), в вашем случае 64: x64 of (1, input_feature_channels)*conv -> (1, 64) .

3. @FerminPitol Вы хотели применить свертку с размером фильтра 2, 3 (2,3,5,9 … < 30), что невозможно для 2 точек данных по 30 объектов в каждой, поэтому я решил, что 2 — это количество последовательностей в пакете, 30 — фактические точки данных. Поэтому вам необходимо создать хотя бы один канал входных функций.