Как использовать Keras Sequential с слоями LocallyConnected

Вопрос или проблема

введите описание изображения здесь
введите описание изображения здесь

Я пытаюсь использовать локально связанные нейронные сети для оценки конечных элементов математической функции, используя модель Keras Sequential. Когда я использую плотные слои, мой код работает идеально и очень точно.

Но когда я переключаюсь на использование слоев LocallyConnected1D, возникает ошибка, показанная на изображении. Тем не менее, я ожидаю, что он будет работать нормально для любого типа слоев, которые я использую, даже для слоев dropout.

Исходя из скриншота, я думаю, что проблема в измерениях, но я не могу это понять. Какие-либо советы о том, что означает ошибка простыми словами и, возможно, как ее разрешить? Спасибо.

Код:

from keras.models import Sequential
from keras.layers import Dense
from keras.callbacks import EarlyStopping
from keras.layers import Dense, LocallyConnected1D
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
import os
import sys
os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"
# %%
def LinearSampler(x_i_minus_1, x_i_plus_1, N):
    gamma=1/2;

    N0=int(N*gamma); Nrest=N-N0;
    p1 = x_i_minus_1 / (x_i_minus_1 + 1 - x_i_plus_1)
    p2 = (1 - x_i_minus_1) / (x_i_minus_1 + 1 - x_i_plus_1)
    x1 = np.linspace(0, x_i_minus_1, int(p1 * Nrest))
    x2 = np.linspace(x_i_minus_1, x_i_plus_1, int(N0))
    x3 = np.linspace(x_i_plus_1, 1, int(p2 * Nrest))
    x = np.concatenate((x1, x2, x3))
    return x

# %% Определение функций FEM

def tent_function(x, x_i_minus_1, x_i_plus_1):
    """
    Вычисляем функцию палатки для заданной точки x и интервала [x_i_minus_1, x_i, x_i_plus_1].
    k = количество конечных элементов, k = 1, 2, ... m < Inf
    i = индекс необходимой функции конечного элемента; 1 = 1, 2, ..., k
    """

    x_i = (x_i_minus_1 + x_i_plus_1)/2

    if x <= x_i_minus_1 or x >= x_i_plus_1:
        return 0
    elif x_i_minus_1 <= x < x_i:
        return (x - x_i_minus_1) / (x_i - x_i_minus_1)
    else:
        return (x_i_plus_1 - x) / (x_i_plus_1 - x_i)

# %% Основы

k = int(input('Введите общее количество конечных элементов: '))
i = int(input('Введите индекс конечного элемента, который нужно подстроить: '))
if i > k:
    print("Требуемый конечный элемент находится вне диапазона доступных. То есть, 'i' ВСЕГДА ДОЛЖЕН быть меньше или равен 'k'")
    sys.exit()
elif i == 0:
    x_i_minus_1 = 0
else:
    x_i_minus_1 = (i - 1)/(k + 1)

x_i_plus_1 = x_i_minus_1 + (2 / (k + 1)) 

# %% Генерация обучающего набора данных

train_x = LinearSampler(x_i_minus_1, x_i_plus_1, 50000)
train_y = np.array([tent_function(xi, x_i_minus_1, x_i_plus_1) for xi in train_x])

# %% Определение архитектуры модели
model = Sequential()
model.add(LocallyConnected1D(64, 3, input_shape=(10, 1), activation='relu'))
model.add(Dense(16, activation='relu'))
model.add(Dense(1, activation='linear'))

# Компиляция модели
model.compile(loss="mse", optimizer="Adam", metrics=['accuracy'])

# Обучение модели на данных
early_stop = EarlyStopping(monitor="loss", patience=10*i) ## Раннее завершение модели в случае, если она не работает
history = model.fit(train_x, train_y, epochs=50, verbose=1, callbacks=[early_stop])

и ошибка;

WARNING:tensorflow:Модель была построена с формой (None, 10, 1) для входа KerasTensor(type_spec=TensorSpec(shape=(None, 10, 1), dtype=tf.float32, name="locally_connected1d_2_input"), name="locally_connected1d_2_input", description="created by layer 'locally_connected1d_2_input'"), но она была вызвана с входными данными с несовместимой формой (None,).
Traceback (most recent call last):

  File C:\ProgramData\Anaconda3\envs\tf\lib\site-packages\spyder_kernels\py3compat.py:356 in compat_exec
    exec(code, globals, locals)

  File e:\desktop\...\file.py:111
    history = model.fit(train_x, train_y, epochs=50, verbose=1, callbacks=[early_stop])

  File C:\ProgramData\Anaconda3\envs\tf\lib\site-packages\keras\utils\traceback_utils.py:70 in error_handler
    raise e.with_traceback(filtered_tb) from None

  File ~\AppData\Local\Temp\__autograph_generated_filekrq21sck.py:15 in tf__train_function
    retval_ = ag__.converted_call(ag__.ld(step_function), (ag__.ld(self), ag__.ld(iterator)), None, fscope)

ValueError: в пользовательском коде:

    File "C:\ProgramData\Anaconda3\envs\tf\lib\site-packages\keras\engine\training.py", line 1160, in train_function  *
        return step_function(self, iterator)
    File "C:\ProgramData\Anaconda3\envs\tf\lib\site-packages\keras\engine\training.py", line 1146, in step_function  **
        outputs = model.distribute_strategy.run(run_step, args=(data,))
    File "C:\ProgramData\Anaconda3\envs\tf\lib\site-packages\keras\engine\training.py", line 1135, in run_step  **
        outputs = model.train_step(data)
    File "C:\ProgramData\Anaconda3\envs\tf\lib\site-packages\keras\engine\training.py", line 993, in train_step
        y_pred = self(x, training=True)
    File "C:\ProgramData\Anaconda3\envs\tf\lib\site-packages\keras\utils\traceback_utils.py", line 70, in error_handler
        raise e.with_traceback(filtered_tb) from None
    File "C:\ProgramData\Anaconda3\envs\tf\lib\site-packages\keras\engine\input_spec.py", line 232, in assert_input_compatibility
        raise ValueError(

    ValueError: Исключение, возникшее при вызове слоя "sequential_2" "                 f"(типа Sequential).

    Вход 0 слоя "locally_connected1d_2" несовместим со слоем: ожидается ndim=3, найден ndim=1. Полная форма, полученная: (None,)

    Аргументы вызова, полученные слоем "sequential_2" "                 f"(типа Sequential):
      • inputs=tf.Tensor(shape=(None,), dtype=float32)
      • training=True
      • mask=None

Сообщение об ошибке, которое вы предоставили, указывает на то, что есть проблема с размерами входных данных. Слой LocallyConnected1D ожидает 3-мерный ввод, но вы предоставляете 1-мерный ввод.

Чтобы решить эту проблему, вам нужно изменить форму ваших входных данных, чтобы они имели правильные размеры. В вашем случае вы можете изменить форму ваших данных train_x на (50000, 10, 1). Это можно сделать с помощью функции reshape из numpy:

train_x = train_x.reshape((50000, 10, 1))

После изменения формы входных данных вы можете передать их функции model.fit:

history = model.fit(train_x, train_y, epochs=50, verbose=1, callbacks=[early_stop])

Ответ или решение

Как использовать Keras Sequential с LocallyConnected слоями

Вопрос, с которым вы столкнулись, связан с несовместимостью размеров входных данных, когда вы пытаетесь использовать LocallyConnected1D слой в вашей модели Keras. Давайте разберем это подробнее и предложим решения.

Проблема с размерами входных данных

Слой LocallyConnected1D ожидает на вход данные в 3D формате, тогда как ваши исходные данные имеют 1D формат. Ошибка, которую вы получили, говорит о том, что входные данные для LocallyConnected1D не соответствуют ожидаемой размерности:

ValueError: Input 0 of layer "locally_connected1d_2" is incompatible with the layer: expected ndim=3, found ndim=1. Full shape received: (None,)

Решение проблемы

Чтобы исправить эту ошибку, вам нужно изменить форму ваших входных данных, train_x, на (число образцов, 10, 1). Это можно сделать с помощью функции reshape из библиотеки NumPy.

Вот как это можно выполнить:

# Преобразуйте train_x в нужный формат
train_x = train_x.reshape((50000, 10, 1))

После этого вы сможете передавать преобразованные данные в метод fit, который тренирует вашу модель:

# Обучение модели на подготовленных данных
history = model.fit(train_x, train_y, epochs=50, verbose=1, callbacks=[early_stop])

Упрощенный пример кода

Вот сборка всех исправлений в вашем коде:

import numpy as np
from keras.models import Sequential
from keras.layers import Dense, LocallyConnected1D
from keras.callbacks import EarlyStopping

# Ваши функции LinearSampler и tent_function остаются без изменений

# Генерация обучающего набора данных
k = 10  # например, общее количество конечных элементов
i = 1   # индекс конечного элемента для подгонки
x_i_minus_1 = (i - 1) / (k + 1)

x_i_plus_1 = x_i_minus_1 + (2 / (k + 1)) 
train_x = LinearSampler(x_i_minus_1, x_i_plus_1, 50000)
train_y = np.array([tent_function(xi, x_i_minus_1, x_i_plus_1) for xi in train_x])

# Преобразование train_x в нужный формат
train_x = train_x.reshape((50000, 10, 1))

# Определение архитектуры модели
model = Sequential()
model.add(LocallyConnected1D(64, 3, input_shape=(10, 1), activation='relu'))
model.add(Dense(16, activation='relu'))
model.add(Dense(1, activation='linear'))

# Компиляция модели
model.compile(loss="mse", optimizer="adam", metrics=['accuracy'])

# Обучение модели
early_stop = EarlyStopping(monitor="loss", patience=10*i)
history = model.fit(train_x, train_y, epochs=50, verbose=1, callbacks=[early_stop])

Заключение

В заключение, при использовании слоев Keras, таких как LocallyConnected1D, важно всегда учитывать ожидаемую размерность входных данных. Преобразование ваших данных в нужный формат позволит избежать ошибок и повысит точность вашей модели. Учитывая эти рекомендации, ваша модель должна работать корректно, и вы сможете эффективно использовать локально связанные слои в Keras для решения задач, связанных с оценкой математических функций.

Оцените материал
Добавить комментарий

Капча загружается...