关于卷积神经网络运行出错,找不到问题原因了

用卷积神经网络和MPG数据集做预测,错误提示如下:

ValueError: Input 0 of layer conv1d is incompatible with the layer: : expected min_ndim=3, found ndim=2. Full shape received: (None, 9)

代码如下:


```python
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
import pandas as pd

# 加载MPG数据集
url = 'https://archive.ics.uci.edu/ml/machine-learning-databases/auto-mpg/auto-mpg.data'
columns = ['MPG', 'Cylinders', 'Displacement', 'Horsepower', 'Weight',
           'Acceleration', 'Model Year', 'Origin']
mpg_data = pd.read_csv(url, names=columns, na_values='?', comment='\t',
                       sep=' ', skipinitialspace=True)

# 处理缺失值
mpg_data = mpg_data.dropna()

# 将Origin列映射为不同的整数(重点)
mpg_data['Origin'] = mpg_data['Origin'].map({1: 'USA', 2: 'Europe', 3: 'Japan'})

# 创建训练集和验证集
train_dataset = mpg_data.sample(frac=0.8, random_state=0)
val_dataset = mpg_data.drop(train_dataset.index)

# 将Origin列转换为独热编码
train_dataset = pd.get_dummies(train_dataset, prefix='', prefix_sep='')
val_dataset = pd.get_dummies(val_dataset, prefix='', prefix_sep='')

# 获取输入维度
input_shape = [train_dataset.shape[1] - 1]

# 构建模型
model = keras.Sequential([
    # 卷积层
    layers.Conv1D(filters=64, kernel_size=3, activation='relu', input_shape=input_shape),
    layers.BatchNormalization(),
    # 池化层
    layers.MaxPooling1D(),
    # 平均池化层
    layers.GlobalAveragePooling1D(),
    # 全连接层
    layers.Dense(units=64, activation='relu'),
    layers.BatchNormalization(),
    # 输出层
    layers.Dense(units=1)
])

# 编译模型
model.compile(optimizer='adam',
              loss='mean_squared_error')

# 将输入和输出分离
train_features = train_dataset.drop('MPG', axis=1).to_numpy()
train_labels = train_dataset['MPG'].to_numpy()

val_features = val_dataset.drop('MPG', axis=1).to_numpy()
val_labels = val_dataset['MPG'].to_numpy()

# 训练模型
history = model.fit(train_features, train_labels,
                    validation_data=(val_features, val_labels),
                    epochs=100, batch_size=32)

# 评估模型
test_loss = model.evaluate(val_features, val_labels)

# 打印测试集上的损失
print(f'Test loss: {test_loss:.4f}')

```

TechWhizKid参考GPT回答:

  • 是因为你将2D数据输入到Conv1D层中。Conv1D层要3D的输入,而你的数据只有2D。这里的3D数据通常表示为(batch_size, steps, channels),你的案例中,这可能意味着(汽车数量,时间步长,特性数量)。
  • 在处理时间序列数据或者序列数据时,卷积神经网络(特别是Conv1D)通常非常有用,因为他们可以捕捉到输入序列中的模式。但是在你的案例中,你的数据并不是时间序列数据或者序列数据,而是一组汽车的特性值。因此,对于你的问题,全连接网络或者深度神经网络可能是一个更好的解决方案。
  • 然而,如果你仍然想用Conv1D,你要将你的输入数据从2D转换为3D。由于你的数据并不是序列数据,所以你要创建一个虚拟的序列维度。这可以通过用tf.expand_dims方法在你的数据中添加一个额外的维度来实现。

下面是修改后的代码段:

# 导入必要的库
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
import pandas as pd

# 加载MPG数据集
url = 'https://archive.ics.uci.edu/ml/machine-learning-databases/auto-mpg/auto-mpg.data'
columns = ['MPG', 'Cylinders', 'Displacement', 'Horsepower', 'Weight',
           'Acceleration', 'Model Year', 'Origin']
mpg_data = pd.read_csv(url, names=columns, na_values='?', comment='\t',
                       sep=' ', skipinitialspace=True)

# 处理缺失值
mpg_data = mpg_data.dropna()

# 将Origin列映射为不同的整数(重点)
mpg_data['Origin'] = mpg_data['Origin'].map({1: 'USA', 2: 'Europe', 3: 'Japan'})

# 创建训练集和验证集
train_dataset = mpg_data.sample(frac=0.8, random_state=0)
val_dataset = mpg_data.drop(train_dataset.index)

# 将Origin列转换为独热编码
train_dataset = pd.get_dummies(train_dataset, prefix='', prefix_sep='')
val_dataset = pd.get_dummies(val_dataset, prefix='', prefix_sep='')

# 获取输入维度
input_shape = [train_dataset.shape[1] - 1, 1]  # 修改此处,将输入维度从2D转为3D

# 构建模型
model = keras.Sequential([
    # 卷积层
    layers.Conv1D(filters=64, kernel_size=3, activation='relu', input_shape=input_shape, padding="same"),  # 使用 padding="same"来处理 kernel 大小和步长可能引起的问题
    layers.BatchNormalization(),
    # 池化层
    layers.MaxPooling1D(),
    # 平均池化层
    layers.GlobalAveragePooling1D(),
    # 全连接层
    layers.Dense(units=64, activation='relu

'),
    layers.BatchNormalization(),
    # 输出层
    layers.Dense(units=1)
])

# 编译模型
model.compile(optimizer='adam',
              loss='mean_squared_error')

# 将输入和输出分离
train_features = train_dataset.drop('MPG', axis=1).to_numpy()
train_labels = train_dataset['MPG'].to_numpy()

val_features = val_dataset.drop('MPG', axis=1).to_numpy()
val_labels = val_dataset['MPG'].to_numpy()

# 增加一个维度
train_features = tf.expand_dims(train_features, axis=-1)
val_features = tf.expand_dims(val_features, axis=-1)

# 训练模型
history = model.fit(train_features, train_labels,
                    validation_data=(val_features, val_labels),
                    epochs=100, batch_size=32)

# 评估模型
test_loss = model.evaluate(val_features, val_labels)

# 打印测试集上的损失
print(f'Test loss: {test_loss:.4f}')
  • 这样你就可以将数据传入Conv1D层了。卷积神经网络可能并不是处理这种问题的最佳模型,你可能需要尝试其他类型的模型,比如全连接网络或者深度神经网络。

维度少了,Conv1D层期望的输入维度最小为3,你的输入为2,需要有时间维度才可以。
这份数据可能并不合适用卷积,用全连接比较好。


如果有帮助,请点击一下采纳该答案~谢谢