Построить настраиваемый процесс федеративного усреднения с ValueError: Layer Sequential ожидает 1 входных данных, но получил 3 входных тензора.

Я пытаюсь загрузить набор данных из CSV и выполнить федеративное обучение на доступных данных.

Мне удается загрузить объединенный набор данных из заданного CSV-файла и загрузить как поезд, так и тестовые данные.

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

Вот мой код, но он не работает:

import collections
import os

import numpy as np
import pandas as pd
import tensorflow as tf
import tensorflow_federated as tff
from absl import app
from tensorflow.keras import layers

from src.main import Parameters

global input_spec


def main(args):
    working_dir = "D:/User/Documents/GitHub/TriaBaseMLBackup/input/fakehdfs/nms/ystr=2016/ymstr=1/ymdstr=26"
    client_id_colname = 'counter'
    SHUFFLE_BUFFER = 1000
    NUM_EPOCHS = 1

    for root, dirs, files in os.walk(working_dir):
        file_list = []

        for filename in files:
            if filename.endswith('.csv'):
                file_list.append(os.path.join(root, filename))
        df_list = []
        for file in file_list:
            df = pd.read_csv(file, delimiter="|", usecols=[1, 2, 6, 7], header=None, na_values=["NIL"],
                             na_filter=True, names=["time", "meas_info", "counter", "value"])
            # df_list.append(df[["value"]])

        if df_list:
            rawdata = pd.concat(df_list)

    client_ids = df.get(client_id_colname)
    train_client_ids = client_ids.sample(frac=0.5).tolist()

    # test_client_ids = [x for x in client_ids if x not in train_client_ids]
    example_dataset = train_data.create_tf_dataset_for_client(
    train_data.client_ids[0]
     )
    def create_tf_dataset_for_client_fn(client_id):
        # a function which takes a client_id and returns a
        # tf.data.Dataset for that client
        # target = df.pop('value')
        client_data = df[df['value'] == client_id]
        print(df.head())
        features = ['time', 'meas_info', 'value']
        LABEL_COLUMN = 'counter'
        dataset = tf.data.Dataset.from_tensor_slices(
            (collections.OrderedDict(df[features].to_dict('list')),
             df[LABEL_COLUMN].to_list())
        )
        global input_spec
        input_spec = dataset.element_spec
        dataset = dataset.shuffle(SHUFFLE_BUFFER).batch(1).repeat(NUM_EPOCHS)
        return dataset

    train_data = tff.simulation.ClientData.from_clients_and_fn(
        client_ids=train_client_ids,
        create_tf_dataset_for_client_fn=create_tf_dataset_for_client_fn
    )

    # split client id into train and test clients
    loss_builder = tf.keras.losses.SparseCategoricalCrossentropy
    metrics_builder = lambda: [tf.keras.metrics.SparseCategoricalAccuracy()]

    def retrieve_model():
        initializer = tf.keras.initializers.GlorotNormal(seed=0)
        model = tf.keras.models.Sequential([
            tf.keras.layers.LSTM(2, input_shape=(1, 2), return_sequences=True),
            tf.keras.layers.Dense(256, activation=tf.nn.relu),
            tf.keras.layers.Activation(tf.nn.softmax),
        ])

        return model

    print(input_spec)

    def tff_model_fn() -> tff.learning.Model:
        return tff.learning.from_keras_model(
            keras_model=retrieve_model(),
            input_spec=example_dataset.element_spec,
            loss=loss_builder(),
            metrics=metrics_builder())

    iterative_process = tff.learning.build_federated_averaging_process(
        tff_model_fn, Parameters.server_adam_optimizer_fn, Parameters.client_adam_optimizer_fn)
    server_state = iterative_process.initialize()

    for round_num in range(Parameters.FLAGS.total_rounds):
        sampled_clients = np.random.choice(
            train_data.client_ids,
            size=Parameters.FLAGS.train_clients_per_round,
            replace=False)
        sampled_train_data = [
            train_data.create_tf_dataset_for_client(client)
            for client in sampled_clients
        ]
        server_state, metrics = iterative_process.next(server_state, sampled_train_data)
        train_metrics = metrics['train']
        print(metrics)


if __name__ == '__main__':
    app.run(main)


def start():
    app.run(main)

Вот вывод input_spec

(OrderedDict([('time', TensorSpec(shape=(), dtype=tf.int32, name=None)), ('meas_info', TensorSpec(shape=(), dtype=tf.int32, name=None)), ('value', TensorSpec(shape=(), dtype=tf.int64, name=None))]), TensorSpec(shape=(), dtype=tf.float32, name=None))

Вот ошибка, которую я получил

ValueError: Layer sequential expects 1 inputs, but it received 3 input tensors. Inputs received: [<tf.Tensor 'batch_input:0' shape=() dtype=int32>, <tf.Tensor 'batch_input_1:0' shape=() dtype=int32>, <tf.Tensor 'batch_input_2:0' shape=() dtype=int64>]

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


person Mixalis Navridis    schedule 16.07.2021    source источник


Ответы (1)


Как говорится в сообщении об ошибке: ValueError: Layer sequential expects 1 inputs, but it received 3 input tensors., модель Keras определяется только с одним входом (первый уровень в списке):

model = tf.keras.models.Sequential([
  tf.keras.layers.LSTM(2, input_shape=(1, 2), return_sequences=True),
  tf.keras.layers.Dense(256, activation=tf.nn.relu),
  tf.keras.layers.Activation(tf.nn.softmax),
])

Попробуйте проверить model.input_spec, чтобы увидеть, какие объекты модель ожидает использовать в качестве входных данных.

>>> [InputSpec(shape=(None, None, 2), ndim=3)]

Где, как определяет набор данных и OrderedDict из 3 тензоров для входных функций:

features = ['time', 'meas_info', 'value']
LABEL_COLUMN = 'counter'
dataset = tf.data.Dataset.from_tensor_slices(
   (collections.OrderedDict(df[features].to_dict('list')),
   df[LABEL_COLUMN].to_list())
)

Попробуйте проверить значение dataset.element_spec, чтобы увидеть, какие объекты набор данных будет кормить модель.

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

SEQUENCE_LENGTH = 5
input_dict =  {f: tf.keras.layers.Input(shape=(SEQUENCE_LENGTH, 1), name=f) for f in features}
concatenated_inputs = tf.keras.layers.Concatenate()(input_dict.values())
lstm_output = tf.keras.layers.LSTM(2, input_shape=(1, 2), return_sequences=True)(concatenated_inputs)
logits = tf.keras.layers.Dense(256, activation=tf.nn.relu)(lstm_output)
predictions = tf.keras.layers.Activation(tf.nn.softmax)(logits)
model = tf.keras.models.Model(inputs=input_dict, outputs=predictions

Обратите внимание, что для уровня LSTM мне нужно было предоставить дополнительные SEQUENCE_LENGTH переменную и размер. shape=(SEQUENCE_LENGTH, 1) необходимо будет изменить, чтобы он соответствовал форме объектов, выходящих из набора данных.

Чтобы быстро проверить совместимость модели и набора данных (без всего остального оборудования), убедитесь, что следующее не вызывает ошибку:

model(next(iter(dataset))[0])
person Zachary Garrett    schedule 17.07.2021
comment
Я получаю эту ошибку ValueError: Вход 0 слоя lstm несовместим со слоем: ожидаемый ndim = 3, найденный ndim = 1. Получена полная форма: [Нет]. Есть рекомендации, как это исправить? - person Mixalis Navridis; 18.07.2021
comment
Это означает, что уровень LSTM ожидает формы [X, Y, Z] (ndim = 3), но входные слои предоставляют формы [X] (ndim = 1). Тензоры, ожидаемые моделью, несовместимы с тензорами, полученными из набора данных. Может быть, попробовать выяснить, дает ли набор данных последовательности? - person Zachary Garrett; 18.07.2021
comment
Можете ли вы предоставить мне какое-либо решение, я застрял на этом - person Mixalis Navridis; 18.07.2021
comment
я даю щедрость. Не могли бы вы дать мне более подробный ответ о том, как решить указанную выше ошибку на рабочем примере, потому что я застрял. Я думаю, что этот ответ поможет многим людям, которые они пытаются создать индивидуальный подход федеративного обучения - person Mixalis Navridis; 18.07.2021
comment
Мне нужно изменить форму tf.keras.layers.Reshape ((5,3)) (concatenated_inputs) для подачи lstm с ndim 3? Есть предложения? - person Mixalis Navridis; 19.07.2021
comment
Еще раз приносим извинения за неудобства. Не могли бы вы проверить этот вопрос stackoverflow.com/questions/68467540/ - person Mixalis Navridis; 21.07.2021