形状 (None, 1) 和 (None, 3) 不兼容,multi-class classification

Shapes (None, 1) and (None, 3) are incompatible, multi-class classification

所以我有多重class class化。我想编译我的模型:

feature_layer = DenseFeatures(feature_columns) # A layer that produces a dense Tensor
model = Sequential([

feature_layer,
  Dense(32, activation='relu'),
  Dense(3, activation='softmax')
])

所以我用categorical_crossentropy损失:

model.compile(optimizer='adam',
              loss='categorical_crossentropy',
              metrics=['accuracy'])

model.fit(train_ds,
          validation_data=val_ds,
          epochs=10)

但是,当然,它给了我一个错误。我知道 to_categorical 方法,但它没有将 BatchDataset 作为参数,而 train_ds 和 val_ds 是。

请指导我

更新:我试着做这样的事情:

def df_to_dataset(df, shuffle=True, batch_size=32): 
  df = df.copy()
  labels = df.pop('class')
  ds = tf.data.Dataset.from_tensor_slices((dict(df), labels))
  if shuffle:
    ds = ds.shuffle(buffer_size=len(df))
    ds = ds.batch(batch_size).map(lambda x, y: (x, tf.one_hot(y, depth=3)))
  return ds

batch_size = 32
train_ds = df_to_dataset(train, batch_size=batch_size)  # error
val_ds = df_to_dataset(val, shuffle=False, batch_size=batch_size)
test_ds = df_to_dataset(test, shuffle=False, batch_size=batch_size)

它给了我:

传递给参数 'indices' 的值的数据类型字符串不在允许值列表中:uint8、int32、int64

我的 class 列有字符串值(它告诉对象是恒星、星系还是类星体,其他是 int/float),但我弹出它:

def df_to_dataset(df, shuffle=True, batch_size=32): 
  df = df.copy()
  labels = df.pop('class')
  ds = tf.data.Dataset.from_tensor_slices((dict(df), labels))
  if shuffle:
    ds = ds.shuffle(buffer_size=len(df))
  return ds
df_to_dataset(df)

标签:

<ShuffleDataset shapes: ({objid: (), ra: (), dec: (), u: (), g: (), r: (), i: (), z: (), run: (), rerun: (), camcol: (), field: (), specobjid: (), redshift: (), plate: (), mjd: (), fiberid: ()}, ()), types: ({objid: tf.float64, ra: tf.float64, dec: tf.float64, u: tf.float64, g: tf.float64, r: tf.float64, i: tf.float64, z: tf.float64, run: tf.int64, rerun: tf.int64, camcol: tf.int64, field: tf.int64, specobjid: tf.float64, redshift: tf.float64, plate: tf.int64, mjd: tf.int64, fiberid: tf.int64}, tf.string)>

您可以将标签转换为单热编码标签并使用 categorical_crossentropy 损失函数:

one_hot_encoded_train_ds = train_ds.map(lambda x, y: (x, tf.one_hot(y, depth=3)))
one_hot_encoded_val_ds = val_ds.map(lambda x, y: (x, tf.one_hot(y, depth=3)))

或者将您的损失函数更改为 sparse_categorical_crossentropy 并将您的标签保留为整数:

model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

更新:将您的字符串标签转换为整数:

def df_to_dataset(df, shuffle=True, batch_size=32): 
  df = df.copy()
  labels = df.pop('class')
  dicts = {'STAR': 0, 'GALAXY': 1, 'QSO': 2}
  converted_labels = np.array([dicts[l] for l in labels.to_list()])
  ds = tf.data.Dataset.from_tensor_slices((dict(df), converted_labels))
  if shuffle:
    ds = ds.shuffle(buffer_size=len(df))
  return ds
df_to_dataset(df)