Python 如何在tf.keras中创建具有多个输出的回归模型?

Python 如何在tf.keras中创建具有多个输出的回归模型?,python,tensorflow,keras,tensorflow2.0,tf.keras,Python,Tensorflow,Keras,Tensorflow2.0,Tf.keras,我试图训练一个回归模型来预测音乐的属性,比如BPM。该模型接收256x128px png文件中音频片段的频谱图,并输出两个连续值。到目前为止,我在tensorflow网站上开发了以下代码: import tensorflow as tf import os import random import pathlib AUTOTUNE = tf.data.experimental.AUTOTUNE TRAINING_DATA_DIR = r'specgrams' def gen_model():

我试图训练一个回归模型来预测音乐的属性,比如BPM。该模型接收256x128px png文件中音频片段的频谱图,并输出两个连续值。到目前为止,我在tensorflow网站上开发了以下代码:

import tensorflow as tf
import os
import random
import pathlib

AUTOTUNE = tf.data.experimental.AUTOTUNE
TRAINING_DATA_DIR = r'specgrams'

def gen_model():
    model = tf.keras.models.Sequential([
      tf.keras.layers.Flatten(input_shape=(256, 128, 3)),
      tf.keras.layers.Dense(256, activation='relu'),
      tf.keras.layers.Dense(2)
    ])

    model.compile(optimizer=tf.keras.optimizers.RMSprop(0.001),
                  loss='mse',
                  metrics=['mse', 'mae'])

    return model


def fetch_batch(batch_size=1000):
    all_image_paths = []
    all_image_labels = []

    data_root = pathlib.Path(TRAINING_DATA_DIR)
    files = data_root.iterdir()

    for file in files:
        file = str(file)
        all_image_paths.append(os.path.abspath(file))
        label = file[:-4].split('-')[2:]
        label = float(label[0]) / 200, int(label[1]) / 1000.0
        all_image_labels.append(label)

    def preprocess_image(path):
        img_raw = tf.io.read_file(path)
        image = tf.image.decode_png(img_raw, channels=3)
        image = tf.image.resize(image, [256, 128])
        image /= 255.0
        return image

    def preprocess(path, label):
        return preprocess_image(path), label

    path_ds = tf.data.Dataset.from_tensor_slices(all_image_paths)
    image_ds = path_ds.map(preprocess_image, num_parallel_calls=AUTOTUNE)
    label_ds = tf.data.Dataset.from_tensor_slices(all_image_labels)
    ds = tf.data.Dataset.zip((image_ds, label_ds))
    ds = ds.shuffle(buffer_size=len(os.listdir(TRAINING_DATA_DIR)))
    ds = ds.repeat()
    ds = ds.batch(batch_size)
    ds = ds.prefetch(buffer_size=AUTOTUNE)

    return ds

ds = fetch_batch()
model = gen_model()
model.fit(ds, epochs=1, steps_per_epoch=10)
然而,我相信我在模型结构或如何预处理训练数据方面犯了一个错误,因为我得到了一个关于不正确维度的错误,但我正在努力缩小问题的确切范围。我知道我遵循的指南是针对分类问题,而不是回归,我的“标签”是一个2值数组,这是导致问题的原因,但我不确定如何解决这个问题

对于上下文,文件名的格式为
xxx-xxx-A-B.png
,其中A和B是模型的两个所需输出值。A是介于70和180之间的浮点值,B是介于0-1000之间的整数值。因此,每个图像的
标签
变量如下所示:
(0.64,0.319)

这是我在尝试执行上述脚本时看到的错误:

Traceback (most recent call last):
  File "C:\Users\cainy\Desktop\BeatNet\training.py", line 60, in <module>
    model.fit(ds, epochs=1, steps_per_epoch=3)
  File "C:\Users\cainy\AppData\Local\Programs\Python\Python37\lib\site-packages\tensorflow\python\keras\engine\training.py", line 791, in fit
    initial_epoch=initial_epoch)
  File "C:\Users\cainy\AppData\Local\Programs\Python\Python37\lib\site-packages\tensorflow\python\keras\engine\training.py", line 1515, in fit_generator
    steps_name='steps_per_epoch')
  File "C:\Users\cainy\AppData\Local\Programs\Python\Python37\lib\site-packages\tensorflow\python\keras\engine\training_generator.py", line 257, in model_iteration
    batch_outs = batch_function(*batch_data)
  File "C:\Users\cainy\AppData\Local\Programs\Python\Python37\lib\site-packages\tensorflow\python\keras\engine\training.py", line 1259, in train_on_batch
    outputs = self._fit_function(ins)  # pylint: disable=not-callable
  File "C:\Users\cainy\AppData\Local\Programs\Python\Python37\lib\site-packages\tensorflow\python\keras\backend.py", line 3217, in __call__
    outputs = self._graph_fn(*converted_inputs)
  File "C:\Users\cainy\AppData\Local\Programs\Python\Python37\lib\site-packages\tensorflow\python\eager\function.py", line 558, in __call__
    return self._call_flat(args)
  File "C:\Users\cainy\AppData\Local\Programs\Python\Python37\lib\site-packages\tensorflow\python\eager\function.py", line 627, in _call_flat
    outputs = self._inference_function.call(ctx, args)
  File "C:\Users\cainy\AppData\Local\Programs\Python\Python37\lib\site-packages\tensorflow\python\eager\function.py", line 415, in call
    ctx=ctx)
  File "C:\Users\cainy\AppData\Local\Programs\Python\Python37\lib\site-packages\tensorflow\python\eager\execute.py", line 66, in quick_execute
    six.raise_from(core._status_to_exception(e.code, message), None)
  File "<string>", line 3, in raise_from
tensorflow.python.framework.errors_impl.InvalidArgumentError: Can not squeeze dim[1], expected a dimension of 1, got 2
     [[{{node metrics/accuracy/Squeeze}}]] [Op:__inference_keras_scratch_graph_734]
回溯(最近一次呼叫最后一次):
文件“C:\Users\cainy\Desktop\BeatNet\training.py”,第60行,在
模型拟合(ds,历元=1,每历元步长=3)
文件“C:\Users\cainy\AppData\Local\Programs\Python\Python37\lib\site packages\tensorflow\Python\keras\engine\training.py”,第791行
初始_历元=初始_历元)
文件“C:\Users\cainy\AppData\Local\Programs\Python\Python37\lib\site packages\tensorflow\Python\keras\engine\training.py”,第1515行,在fit\U生成器中
步骤(名称=“每个时代的步骤”)
文件“C:\Users\cainy\AppData\Local\Programs\Python\Python37\lib\site packages\tensorflow\Python\keras\engine\training\u generator.py”,第257行,在模型迭代中
批处理输出=批处理功能(*批处理数据)
文件“C:\Users\cainy\AppData\Local\Programs\Python\Python37\lib\site packages\tensorflow\Python\keras\engine\training.py”,第1259行,在批处理的列中
输出=self._fit_函数(ins)35; pylint:disable=不可调用
文件“C:\Users\cainy\AppData\Local\Programs\Python\Python37\lib\site packages\tensorflow\Python\keras\backend.py”,第3217行,在调用中__
输出=自。\图形\ fn(*转换的\输入)
文件“C:\Users\cainy\AppData\Local\Programs\Python\Python37\lib\site packages\tensorflow\Python\eager\function.py”,第558行,在调用中__
返回自我。呼叫平面(args)
文件“C:\Users\cainy\AppData\Local\Programs\Python\Python37\lib\site packages\tensorflow\Python\eager\function.py”,第627行,位于调用平面中
输出=自我推理函数调用(ctx,args)
调用中第415行的文件“C:\Users\cainy\AppData\Local\Programs\Python\Python37\lib\site packages\tensorflow\Python\eager\function.py”
ctx=ctx)
文件“C:\Users\cainy\AppData\Local\Programs\Python\Python37\lib\site packages\tensorflow\Python\eager\execute.py”,第66行,在quick\u execute中
六、将_从(核心状态)提升到_异常(例如代码、消息),无
文件“”,第3行,从
tensorflow.python.framework.errors\u impl.InvalidArgumentError:无法压缩dim[1],应为1,得到2
[{{node metrics/accurity/squence}}][Op:uuu推断_ukeras_uscratch_734]

编辑:我已将源代码上载到GitHub。

您当前只有1个输出-长度为2的张量(每个批处理元素)。如果要使用/监视单独的损失,则需要在模型输出和标签中都使用它

我不确定
models.Sequential
是否合适,但您肯定可以使用函数API:

def gen_model():
inputs=tf.keras.layers.Input(shape=(256,128,3),dtype=tf.float32)
x=输入
x=tf.keras.layers.density(256,活化='relu')
x=tf.keras.layers.致密(2)
a、 b=tf.keras.layers.Lambda(tf.unstack,arguments=dict(axis=-1))(x)
model=tf.keras.models.model(输入=输入,输出=[a,b])
compile(optimizer=tf.keras.optimizers.RMSprop(0.001),
损失=['mse','mae'],
指标=['mse'],['mae']])
回归模型
在预处理过程中:

def预处理(路径、标签): 返回预处理图像(路径),tf.unstack(标签,轴=-1)
是的,我还有一个问题要问。我已经意识到我的损失指标应该类似于mse。但是,我根本无法运行此模型,因为我不知道如何在每个值都没有两个单独的模型的情况下输出2个值。答案已更新。没有数据就无法测试,因此请在此处发布任何错误:)啊,谢谢!这看起来很有希望,我会调查的。我担心发行音乐的版权问题,但我可以上传一些我制作的样本光谱图。是一个包含一千个图像的zip文件:)