某些预测问题需要同时预测数值和类别标签。
一种简单的方法是针对相同数据开发回归和分类预测模型,然后顺序使用这些模型。
另一种通常更有效的方法是开发一个单一的神经网络模型,该模型可以从相同的输入预测数值和类别标签值。这被称为“多输出模型”,使用 Keras 和 TensorFlow 等现代深度学习库可以相对容易地开发和评估。
在本教程中,您将了解如何开发一个用于联合回归和分类预测的神经网络。
完成本教程后,您将了解:
- 某些预测问题要求为每个输入示例预测数值和类别标签值。
- 如何为需要多个输出的问题开发单独的回归和分类模型。
- 如何开发和评估一个能够同时进行回归和分类预测的神经网络模型。
让我们开始吧。

开发用于联合分类和回归的神经网络
照片由 Sang Trinh 拍摄,保留部分权利。
教程概述
本教程分为三个部分;它们是:
- 用于回归和分类的单一模型
- 单独的回归和分类模型
- 鲍鱼数据集
- 回归模型
- 分类模型
- 联合回归和分类模型
用于回归和分类的单一模型
通常为回归或分类问题开发深度学习神经网络模型,但在某些预测建模任务中,我们可能希望开发一个模型,该模型可以同时进行回归和分类预测。
回归是指涉及给定输入预测数值的预测建模问题。
分类是指涉及给定输入预测类别标签或类别概率的预测建模问题。
有关分类和回归之间差异的更多信息,请参阅教程
可能存在一些问题,我们希望同时预测数值和分类值。
解决此问题的一种方法是为每个需要的预测开发一个单独的模型。
这种方法的问题在于,由单独模型做出的预测可能会出现分歧。
在使用神经网络模型时,可以使用一种替代方法,即开发一个单一模型,该模型能够从相同的输入同时为数值和类别输出做出单独的预测。
这被称为多输出神经网络模型。
这类模型的好处是我们有一个模型需要开发和维护,而不是两个模型,并且同时在两种输出类型上训练和更新模型可以为两种输出类型之间的预测提供更多一致性。
我们将开发一个能够同时进行回归和分类预测的多输出神经网络模型。
首先,让我们选择一个适合此需求的数据集,并开始开发单独的回归和分类预测模型。
单独的回归和分类模型
在本节中,我们将首先选择一个实际数据集,我们可能需要同时进行回归和分类预测,然后为每种类型的预测开发单独的模型。
鲍鱼数据集
我们将使用“鲍鱼”数据集。
确定鲍鱼的年龄是一项耗时的任务,因此最好仅根据物理细节来确定年龄。
这是一个描述鲍鱼物理细节的数据集,需要预测鲍鱼的环数,这是生物年龄的代理。
您可以从这里了解更多关于数据集的信息
“年龄”可以预测为数值(年)或类别标签(作为类别的序数年)。
无需下载数据集,因为我们将在示例工作中自动下载。
该数据集提供了一个示例,说明我们可能需要对输入进行数值和分类。
首先,让我们开发一个下载和总结数据集的示例。
1 2 3 4 5 6 7 8 9 10 |
# 加载和总结鲍鱼数据集 from pandas import read_csv from matplotlib import pyplot # 加载数据集 url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/abalone.csv' dataframe = read_csv(url, header=None) # 总结形状 print(dataframe.shape) # 总结前几行 print(dataframe.head()) |
运行示例将首先下载并总结数据集的形状。
我们可以看到有 4,177 个示例(行)可用于训练和评估模型,以及 9 个特征(列),包括目标变量。
我们可以看到,除了第一个是字符串值外,所有输入变量都是数值的。
为了简化数据准备,我们将从模型中删除第一列,并专注于对数值输入值进行建模。
1 2 3 4 5 6 7 |
(4177, 9) 0 1 2 3 4 5 6 7 8 0 M 0.455 0.365 0.095 0.5140 0.2245 0.1010 0.150 15 1 M 0.350 0.265 0.090 0.2255 0.0995 0.0485 0.070 7 2 F 0.530 0.420 0.135 0.6770 0.2565 0.1415 0.210 9 3 M 0.440 0.365 0.125 0.5160 0.2155 0.1140 0.155 10 4 I 0.330 0.255 0.080 0.2050 0.0895 0.0395 0.055 7 |
我们可以将数据作为开发单独的回归和分类多层感知器(MLP)神经网络模型的基础。
注意:我们不是试图为该数据集开发最佳模型;而是演示一种特定技术:开发一种能够同时进行回归和分类预测的模型。
回归模型
在本节中,我们将为鲍鱼数据集开发一个回归 MLP 模型。
首先,我们必须将列分成输入和输出元素,并删除包含字符串值的第一个列。
我们还将强制所有加载的列具有浮点类型(神经网络模型期望的),并记录输入特征的数量,模型稍后需要知道这一点。
1 2 3 4 5 |
... # 分割为输入 (X) 和输出 (y) 变量 X, y = dataset[:, 1:-1], dataset[:, -1] X, y = X.astype('float'), y.astype('float') n_features = X.shape[1] |
接下来,我们可以将数据集分成训练集和测试集。
我们将使用 67% 的随机样本来训练模型,其余 33% 来评估模型。
1 2 3 |
... # 将数据拆分为训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1) |
然后我们可以定义一个 MLP 神经网络模型。
该模型将有两个隐藏层,第一个有 20 个节点,第二个有 10 个节点,都使用 ReLU 激活和“he normal”权重初始化(良好的实践)。层数和节点数是任意选择的。
输出层将有一个节点用于预测数值,并使用线性激活函数。
1 2 3 4 5 6 |
... # 定义 Keras 模型 model = Sequential() model.add(Dense(20, input_dim=n_features, activation='relu', kernel_initializer='he_normal')) model.add(Dense(10, activation='relu', kernel_initializer='he_normal')) model.add(Dense(1, activation='linear')) |
模型将通过最小化均方误差 (MSE) 损失函数来训练,使用随机梯度下降的有效 Adam 版本。
1 2 3 |
... # 编译 Keras 模型 model.compile(loss='mse', optimizer='adam') |
我们将模型训练 150 个 epoch,迷你批次大小为 32 个样本,同样是任意选择的。
1 2 3 |
... # 在数据集上拟合 Keras 模型 model.fit(X_train, y_train, epochs=150, batch_size=32, verbose=2) |
最后,在模型训练完成后,我们将在保留的测试数据集上对其进行评估,并报告平均绝对误差 (MAE)。
1 2 3 4 5 |
... # 在测试集上评估 yhat = model.predict(X_test) error = mean_absolute_error(y_test, yhat) print('MAE: %.3f' % error) |
总而言之,下面列出了鲍鱼数据集回归问题的 MLP 神经网络完整示例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
# 鲍鱼数据集的回归 MLP 模型 from pandas import read_csv from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense from sklearn.metrics import mean_absolute_error from sklearn.model_selection import train_test_split # 加载数据集 url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/abalone.csv' dataframe = read_csv(url, header=None) dataset = dataframe.values # 分割为输入 (X) 和输出 (y) 变量 X, y = dataset[:, 1:-1], dataset[:, -1] X, y = X.astype('float'), y.astype('float') n_features = X.shape[1] # 将数据拆分为训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1) # 定义 Keras 模型 model = Sequential() model.add(Dense(20, input_dim=n_features, activation='relu', kernel_initializer='he_normal')) model.add(Dense(10, activation='relu', kernel_initializer='he_normal')) model.add(Dense(1, activation='linear')) # 编译 Keras 模型 model.compile(loss='mse', optimizer='adam') # 在数据集上拟合 Keras 模型 model.fit(X_train, y_train, epochs=150, batch_size=32, verbose=2) # 在测试集上评估 yhat = model.predict(X_test) error = mean_absolute_error(y_test, yhat) print('MAE: %.3f' % error) |
运行示例将准备数据集、拟合模型并报告模型误差的估计。
注意:由于算法或评估程序的随机性,或数值精度的差异,您的结果可能会有所不同。可以尝试运行示例几次并比较平均结果。
在这种情况下,我们可以看到模型达到了大约 1.5(环)的误差。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
... 纪元 145/150 88/88 - 0s - loss: 4.6130 纪元 146/150 88/88 - 0s - loss: 4.6182 第 147 周期/150 88/88 - 0s - loss: 4.6277 第 148 周期/150 88/88 - 0s - loss: 4.6437 第 149 周期/150 88/88 - 0s - loss: 4.6166 第 150 周期/150 88/88 - 0s - loss: 4.6132 MAE: 1.554 |
到目前为止进展顺利。
接下来,我们来看看开发一个类似的分类模型。
分类模型
鲍鱼数据集可以被视为一个分类问题,其中每个“环”整数被视为一个单独的类别标签。
示例和模型与上面回归示例非常相似,只有几个重要的变化。
这首先需要为每个“环”值分配一个单独的整数,从 0 开始,到“类别”总数减一结束。
这可以通过 LabelEncoder 来实现。
我们还可以记录类别总数,即编码类别值的总数,模型稍后需要用到。
1 2 3 4 |
... # 将字符串编码为整数 y = LabelEncoder().fit_transform(y) n_class = len(unique(y)) |
在像之前一样将数据分割成训练集和测试集后,我们可以定义模型,并将模型的输出数量更改为等于类别数量,并使用 softmax 激活函数,这对于多类别分类很常见。
1 2 3 4 5 6 |
... # 定义 Keras 模型 model = Sequential() model.add(Dense(20, input_dim=n_features, activation='relu', kernel_initializer='he_normal')) model.add(Dense(10, activation='relu', kernel_initializer='he_normal')) model.add(Dense(n_class, activation='softmax')) |
由于我们已将类别标签编码为整数值,我们可以通过最小化稀疏类别交叉熵损失函数来拟合模型,该函数适用于具有整数编码类别标签的多类别分类任务。
1 2 3 |
... # 编译 Keras 模型 model.compile(loss='sparse_categorical_crossentropy', optimizer='adam') |
在模型像之前一样在训练数据集上拟合后,我们可以通过计算保留测试集上的分类准确率来评估模型的性能。
1 2 3 4 5 6 |
... # 在测试集上评估 yhat = model.predict(X_test) yhat = argmax(yhat, axis=-1).astype('int') acc = accuracy_score(y_test, yhat) print('Accuracy: %.3f' % acc) |
总而言之,下面列出了将鲍鱼数据集作为分类问题进行处理的 MLP 神经网络的完整示例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
# 鲍鱼数据集的分类 MLP 模型 from numpy import unique from numpy import argmax from pandas import read_csv from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense from sklearn.metrics import accuracy_score from sklearn.model_selection import train_test_split 从 sklearn.preprocessing 导入 LabelEncoder # 加载数据集 url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/abalone.csv' dataframe = read_csv(url, header=None) dataset = dataframe.values # 分割为输入 (X) 和输出 (y) 变量 X, y = dataset[:, 1:-1], dataset[:, -1] X, y = X.astype('float'), y.astype('float') n_features = X.shape[1] # 将字符串编码为整数 y = LabelEncoder().fit_transform(y) n_class = len(unique(y)) # 将数据拆分为训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1) # 定义 Keras 模型 model = Sequential() model.add(Dense(20, input_dim=n_features, activation='relu', kernel_initializer='he_normal')) model.add(Dense(10, activation='relu', kernel_initializer='he_normal')) model.add(Dense(n_class, activation='softmax')) # 编译 Keras 模型 model.compile(loss='sparse_categorical_crossentropy', optimizer='adam') # 在数据集上拟合 Keras 模型 model.fit(X_train, y_train, epochs=150, batch_size=32, verbose=2) # 在测试集上评估 yhat = model.predict(X_test) yhat = argmax(yhat, axis=-1).astype('int') acc = accuracy_score(y_test, yhat) print('Accuracy: %.3f' % acc) |
运行示例将准备数据集、拟合模型并报告模型误差的估计。
注意:由于算法或评估程序的随机性,或数值精度的差异,您的结果可能会有所不同。可以尝试运行示例几次并比较平均结果。
在这种情况下,我们可以看到模型达到了大约 27% 的准确率。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
... 纪元 145/150 88/88 - 0s - loss: 1.9271 纪元 146/150 88/88 - 0s - loss: 1.9265 第 147 周期/150 88/88 - 0s - loss: 1.9265 第 148 周期/150 88/88 - 0s - loss: 1.9271 第 149 周期/150 88/88 - 0s - loss: 1.9262 第 150 周期/150 88/88 - 0s - loss: 1.9260 Accuracy: 0.274 |
到目前为止进展顺利。
接下来,我们来看看开发一个能够同时进行回归和分类预测的组合模型。
联合回归和分类模型
在本节中,我们可以开发一个单一的 MLP 神经网络模型,该模型可以为单个输入同时进行回归和分类预测。
这被称为多输出模型,并可以使用 Keras 的函数式 API 来开发。
有关此函数式 API 的更多信息,初学者可能会觉得有些棘手,请参阅教程
首先,必须准备数据集。
我们可以像之前为分类那样准备数据集,但应该将编码后的目标变量保存到一个单独的名称中,以区别于原始目标变量值。
1 2 3 4 |
... # 将字符串编码为整数 y_class = LabelEncoder().fit_transform(y) n_class = len(unique(y_class)) |
然后,我们可以将输入、原始输出和编码输出变量分割成训练集和测试集。
1 2 3 |
... # 将数据拆分为训练集和测试集 X_train, X_test, y_train, y_test, y_train_class, y_test_class = train_test_split(X, y, y_class, test_size=0.33, random_state=1) |
接下来,我们可以使用函数式 API 定义模型。
模型接受的输入与独立模型相同的数量,并使用两个以相同方式配置的隐藏层。
1 2 3 4 5 |
... # 输入 visible = Input(shape=(n_features,)) hidden1 = Dense(20, activation='relu', kernel_initializer='he_normal')(visible) hidden2 = Dense(10, activation='relu', kernel_initializer='he_normal')(hidden1) |
然后,我们可以定义两个单独的输出层,它们连接到模型的第二个隐藏层。
第一个是回归输出层,有一个节点和一个线性激活函数。
1 2 3 |
... # 回归输出 out_reg = Dense(1, activation='linear')(hidden2) |
第二个是分类输出层,每个被预测的类都有一个节点,并使用 softmax 激活函数。
1 2 3 |
... # 分类输出 out_clas = Dense(n_class, activation='softmax')(hidden2) |
然后,我们可以定义一个具有单个输入层和两个输出层的模型。
1 2 3 |
... # 定义模型 model = Model(inputs=visible, outputs=[out_reg, out_clas]) |
考虑到两个输出层,我们可以为模型编译两个损失函数:第一个(回归)输出层的均方误差损失,以及第二个(分类)输出层的稀疏类别交叉熵。
1 2 3 |
... # 编译 Keras 模型 model.compile(loss=['mse', 'sparse_categorical_crossentropy'], optimizer='adam') |
我们还可以创建一个模型图以供参考。
这需要安装 pydot 和 pygraphviz。如果这有问题,可以注释掉此行以及 plot_model() 函数的导入语句。
1 2 3 |
... # 绘制模型图 plot_model(model, to_file='model.png', show_shapes=True) |
每次模型进行预测时,它都会预测两个值。
同样,在训练模型时,它需要每个输出每样本一个目标变量。
因此,我们可以训练模型,小心地将回归目标和分类目标数据提供给模型的每个输出。
1 2 3 |
... # 在数据集上拟合 Keras 模型 model.fit(X_train, [y_train, y_train_class], epochs=150, batch_size=32, verbose=2) |
然后,拟合的模型可以对保留的测试集中的每个示例进行回归和分类预测。
1 2 3 |
... # 对测试集进行预测 yhat1, yhat2 = model.predict(X_test) |
第一个数组可用于通过平均绝对误差评估回归预测。
1 2 3 4 |
... # 计算回归模型的误差 error = mean_absolute_error(y_test, yhat1) print('MAE: %.3f' % error) |
第二个数组可用于通过分类准确率评估分类预测。
1 2 3 4 5 |
... # 评估分类模型的准确率 yhat2 = argmax(yhat2, axis=-1).astype('int') acc = accuracy_score(y_test_class, yhat2) print('Accuracy: %.3f' % acc) |
就是这样。
总而言之,下面列出了在鲍鱼数据集上训练和评估组合回归和分类预测的多输出模型的完整示例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# 鲍鱼数据集上组合回归和分类预测的 MLP from numpy import unique from numpy import argmax from pandas import read_csv from sklearn.metrics import mean_absolute_error from sklearn.metrics import accuracy_score from sklearn.model_selection import train_test_split from sklearn.preprocessing import LabelEncoder from tensorflow.keras.models import Model from tensorflow.keras.layers import Input from tensorflow.keras.layers import Dense from tensorflow.keras.utils import plot_model # 加载数据集 url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/abalone.csv' dataframe = read_csv(url, header=None) dataset = dataframe.values # 分割为输入 (X) 和输出 (y) 变量 X, y = dataset[:, 1:-1], dataset[:, -1] X, y = X.astype('float'), y.astype('float') n_features = X.shape[1] # 将字符串编码为整数 y_class = LabelEncoder().fit_transform(y) n_class = len(unique(y_class)) # 将数据拆分为训练集和测试集 X_train, X_test, y_train, y_test, y_train_class, y_test_class = train_test_split(X, y, y_class, test_size=0.33, random_state=1) # 输入 visible = Input(shape=(n_features,)) hidden1 = Dense(20, activation='relu', kernel_initializer='he_normal')(visible) hidden2 = Dense(10, activation='relu', kernel_initializer='he_normal')(hidden1) # 回归输出 out_reg = Dense(1, activation='linear')(hidden2) # 分类输出 out_clas = Dense(n_class, activation='softmax')(hidden2) # 定义模型 model = Model(inputs=visible, outputs=[out_reg, out_clas]) # 编译 Keras 模型 model.compile(loss=['mse', 'sparse_categorical_crossentropy'], optimizer='adam') # 绘制模型图 plot_model(model, to_file='model.png', show_shapes=True) # 在数据集上拟合 Keras 模型 model.fit(X_train, [y_train, y_train_class], epochs=150, batch_size=32, verbose=2) # 对测试集进行预测 yhat1, yhat2 = model.predict(X_test) # 计算回归模型的误差 error = mean_absolute_error(y_test, yhat1) print('MAE: %.3f' % error) # 评估分类模型的准确率 yhat2 = argmax(yhat2, axis=-1).astype('int') acc = accuracy_score(y_test_class, yhat2) print('Accuracy: %.3f' % acc) |
运行示例将准备数据集、拟合模型并报告模型误差的估计。
注意:由于算法或评估程序的随机性,或数值精度的差异,您的结果可能会有所不同。可以尝试运行示例几次并比较平均结果。
创建了多输出模型的图,清晰地显示了连接到模型第二个隐藏层的回归(左)和分类(右)输出层。

组合回归和分类预测的多输出模型图
在这种情况下,我们可以看到该模型达到了大约 1.495(环)的合理误差,并且与之前的准确率相似,约为 25.6%。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
... 纪元 145/150 88/88 - 0s - loss: 6.5707 - dense_2_loss: 4.5396 - dense_3_loss: 2.0311 纪元 146/150 88/88 - 0s - loss: 6.5753 - dense_2_loss: 4.5466 - dense_3_loss: 2.0287 第 147 周期/150 88/88 - 0s - loss: 6.5970 - dense_2_loss: 4.5723 - dense_3_loss: 2.0247 第 148 周期/150 88/88 - 0s - loss: 6.5640 - dense_2_loss: 4.5389 - dense_3_loss: 2.0251 第 149 周期/150 88/88 - 0s - loss: 6.6053 - dense_2_loss: 4.5827 - dense_3_loss: 2.0226 第 150 周期/150 88/88 - 0s - loss: 6.5754 - dense_2_loss: 4.5524 - dense_3_loss: 2.0230 MAE: 1.495 Accuracy: 0.256 |
进一步阅读
如果您想深入了解,本节提供了更多关于该主题的资源。
教程
总结
在本教程中,您了解了如何开发用于组合回归和分类预测的神经网络。
具体来说,你学到了:
- 某些预测问题要求为每个输入示例预测数值和类别标签值。
- 如何为需要多个输出的问题开发单独的回归和分类模型。
- 如何开发和评估一个能够同时进行回归和分类预测的神经网络模型。
你有什么问题吗?
在下面的评论中提出你的问题,我会尽力回答。
您好,在医疗保健领域是否有神经网络可以解决回归和分类问题的例子?
当然。您可以在 scholar.google.com 上搜索。
嗨,jason
您能否举一个使用微阵列基因表达数据集的分类模型示例?
感谢您的建议。
嗨,Jason,
这个模型可以在多输出数据上执行吗?
谢谢
也许这会是一个更合适的模型
https://machinelearning.org.cn/multi-output-regression-models-with-python/
谢谢,
我会去检查的。
不客气。
嗨,Jason,
是否可以对“组合回归和分类模型”使用序贯方法?(例如回归和分类模型示例)。
y_values 可以是一个 numpy 数组 array([y, y_class])
最后一个 Dense 层的单位将等于 2。
但那样的话,最后一层的激活函数会是什么?
compile 函数中的 loss 属性又会是什么?
非常感谢
我看不出为什么不。
您可能需要对模型进行较大的更改。
嗨,Jason,
非常有趣的教程!特别是熟悉 Keras 的 API 模型。谢谢。
无论如何,我认为两个问题最好分开分析。
我分享我的代码实验。
- 简单地使用模型自身的 evaluate() 方法来获取指标。“mae”用于完整模型的回归部分,“accuracy”用于分类部分。
在此之前,我必须在 compilation model 方法中添加“metrics”参数,使其等于[‘mae’, ‘accuracy’]。
唯一令人困惑的是,当您获得 model.evaluate() 的输出时,您会得到“mae”和“accuracy”的所有交叉组合,即使是分类器和回归器的相反层也是如此。
所以我决定在模型创建时为输出层命名,以便更好地识别正确的层!
谢谢。
嗯,也许 evaluate() 不是处理如此复杂模型的合适工具。
我认为代码需要一些修订
1) 名称应为
dataframe
而不是dataset
2) 我们应该使用
iloc
以索引格式访问dataframe
>>> X, y = dataframe.iloc[:, 1:-1], dataframe.iloc[:, -1]
>>> X, y = X.astype(‘float’), y.astype(‘float’)
>>> n_features = X.shape[1]
我更喜欢直接处理 numpy 数组。
您好 Jason,您的博客很棒。这正是我想要的。它运行良好,但我需要稍作修改,您能给我最好的建议吗?
我有一个图像数据集的分类和回归问题。我的回归依赖于分类,也就是说,例如:如果 Class=1,那么回归预测应该等于 0。我该如何强制我的 ML 模型在不构建不同分类模型的情况下预测为零?
非常感谢。
谢谢!
也许你可以将模型按顺序链接起来,也许是手动链接。
谢谢 Jason,如果模型是按顺序链接的,能否一起训练这两个模型?
嗨,Jason,
我有一个场景,我需要首先根据最后 10 个序列预测单个时间序列值序列,然后根据预测值序列,我需要检查该单个序列属于 7 个类别中的哪个类别。
谢谢
我建议测试一套模型,以发现哪些模型对您的数据集效果好或最好。
您能提供一个例子或简要说明您所说的“一套模型”是什么意思吗?
谢谢
抱歉,我的意思是许多不同的模型类型或配置。
谢谢,明白了 😉
嗨,Jason,
感谢您关于组合回归和分类神经网络模型的富有见地的文章。我有一些关于模型的问题。
1.该模型是否捕捉了两个输出变量之间的依赖关系,还是我们假设它们彼此独立?
2.在给出的示例中,似乎对同一输出变量进行了分类,并使用同一输出变量进行回归。我们可以使用两个不同的输出变量,一个用于回归,另一个用于分类,然后运行模型吗?
模型不应假设(1),但它会学习它。请记住,网络模型是非线性的。在这种情况下,依赖关系不像线性依赖关系那样简单。对于(2),我看不出有什么不同。请注意,有 y 和 y_class,后者是前者的转换结果。
你好 Adrian,
感谢您的回复。在我正在处理的模型中,我有 2 个相互依赖的变量,它们是输出。一个变量是数值变量,另一个变量是类别变量。其余变量是输入。
我尝试运行组合模型,发现模型的回归部分运行良好,返回的输出与仅回归的神经网络模型(前面提到的第二个类别输出变量是此模型的输入)几乎相同。
但是,在分类方面,我得到的数字非常小(数量级为 10^-5),而不是类标签(6 个类别)。您是否有任何见解可以提供帮助?否则,我们可以通过 LinkedIn 或电子邮件联系吗?
当我尝试按原样运行此页面上的代码时,回归部分给出了良好的预测。但分类部分给出的预测数量级为 10^-5 甚至更低。回归和分类的损失函数值与网页上显示的完全相同。我是否需要为分类部分做其他事情?
不是我的情况。您可以在打印准确率后尝试添加这两行代码,以便并排比较输出
import pandas as pd
print(pd.DataFrame({“y”:y_test.ravel(), “yhat”:yhat1.ravel(), “y_cls”: y_test_class.ravel(), “yhat_cls”:yhat2.ravel()}))
感谢您的见解 Adrian。代码现在运行正常。
为了获得一般性见解,您能否详细说明一下模型如何预测 2 个输出变量?假设我们有输入 x1……x7 和输出变量 y1 和 y2。对于预测 y1,模型是使用 x1……x7 作为输入,还是使用包括 y2 在内的 x1……x7 作为输入?类似地,它如何为 y2 进行?
我可以使用此技术来预测跨多个季度(时间序列)的数据吗?如果可以,我该如何修改它?
通常我们不会在输入中有 y1 和 y2,因为如果您称之为输出,那就意味着我们不应该提前知道它。但对于时间序列,您可以包含 y1 和 y2 的滞后版本。例如,要预测下一季度的 GDP,您可以使用本季度的 GDP、股市表现、今天的失业率等。
您好 Jason,感谢您的示例。
我的问题与 Loss 相关,将不同的函数组合起来计算 Loss 是否有问题?
为了计算神经网络的权重,如果同时使用不同的损失函数会受到什么影响?或者神经网络是否会简单地调整权重以最小化总体输出误差?
您可以定义自己的损失函数,但您只使用一个损失函数来训练神经网络(否则,梯度下降将无法工作)。您可以使用不同的损失函数来跟踪部分训练网络的性能,例如在验证步骤中。
如果您要训练模型,则训练应只有一个损失函数。这是训练将要最小化的损失。但是,对于验证,您可以使用许多不同的函数。
这是解决方案中省略的一个非常重要的细微差别。快速粗略的方法是转换回归目标,这样在组合损失时至少可以在同一数量级上,另一个粗略的方法可能是重缩放
model. compile
调用中的损失。一个稍好的方法是使用回调并在每个 epoch 更新权重。目前,我正在进一步研究这个问题。感谢您非常有趣的帖子。您能解释一下在训练阶段如何更新密集层(hidden1 层)的权重吗?
您好 Ngoc-Tuan Do…权重和偏差在训练过程中通过反向传播进行调整,反向传播利用一种梯度下降形式进行优化。以下内容可能对您感兴趣
https://machinelearning.org.cn/a-gentle-introduction-to-the-challenge-of-training-deep-learning-neural-network-models/
在上面的示例中,您可以执行一个回归,一个分类,但以类似的方式获得多个输出。
(分类的标签在很多情况下存在偏差,但在多输出的情况下,如何进行分层采样?
嗨,Jason,
我有一个关于分类部分的问题 – 最后我们得到的准确率是:0.256。这是否太低了,我们该如何提高它?如果我正确理解了这篇文章,这是结合两个模型的方法,它并没有提高准确率,而是节省了一个通道。
您好 Anthony……本教程旨在举例说明如何处理该技术,但模型并未得到优化。
嘿 James!
首先,非常感谢您的工作!您已经用您的所有教程帮了我很多。
关于两个输出层(回归和分类)以及 keras 序贯 API
我能否以某种方式将其与 ImageDataGenerator 结合使用?
看起来
iterator_train = datagen.flow(
x = x_train,
y = [y_train_reg, y_train_class],
batch_size=batch_size,
seed = datagen_seed
)
不起作用:/
谢谢!
您好 Marian……感谢您的反馈和支持!请澄清或描述您的模型“为何不起作用”。这将使我们能够更好地帮助您。
当然!
所以,我构建了一个具有两个输出层的网络。一个输出层有 3 个神经元,具有 relu 激活和 mse 作为回归损失,第二个输出层有 1 个神经元用于分类(损失为 binary_crossentropy)。
这就是网络的结尾样子
x = keras.layers.Dense(256, activation=”relu”)(x)
x = keras.layers.Dropout(0.5)(x)
out_reg = keras.layers.Dense(3, activation=last_layer_activation_function_reg)(x)
out_clas = keras.layers.Dense(1, activation=last_layer_activation_function_clas)(x)
构建模型效果很好,在没有 ImageDataGenerator 的情况下进行训练也效果很好。
当尝试使用具有两个标签向量 y_train_reg 和 y_train_clas(来自 Keras 的 ImageDataGenerator)的模型进行训练时,会出现错误
# image augmentation
horizontal_flip = True
vertical_flip = True
rotation_angle = 5
brightness_range = None
zoom_range = [1.0, 1.5]
shear_range = 0.2
datagen = ImageDataGenerator(
horizontal_flip=horizontal_flip,
vertical_flip=vertical_flip,
rotation_range=rotation_angle,
#brightness_range=brightness_range,
zoom_range=zoom_range,
shear_range=shear_range
)
iterator_train = datagen.flow(
x = x_train,
y = [y_train_reg, y_train_class], <————————————– HERE
batch_size=batch_size,
seed = datagen_seed
)
错误消息
iterator_train = datagen.flow(
File "C:\Users\Anwender\AppData\Local\Programs\Python\Python38\lib\site-packages\keras\preprocessing\image.py", line 884, in flow
return NumpyArrayIterator(
File "C:\Users\Anwender\AppData\Local\Programs\Python\Python38\lib\site-packages\keras\preprocessing\image.py", line 463, in __init__
super(NumpyArrayIterator, self).__init__(
File "C:\Users\Anwender\AppData\Local\Programs\Python\Python38\lib\site-packages\keras_preprocessing\image\numpy_array_iterator.py", line 89, in __init__
(np.asarray(x).shape, np.asarray(y).shape))
File "C:\Users\Anwender\AppData\Local\Programs\Python\Python38\lib\site-packages\numpy\core\_asarray.py", line 83, in asarray
返回数组(a, dtype, copy=False, order=order)
ValueError: could not broadcast input array from shape (5449,3) into shape (5449)
您能否举一个使用微阵列基因表达数据集的分类模型示例?
感谢您的建议!以下是我们当前内容的完整列表。
https://machinelearning.org.cn/start-here/
你好 Jamesh,
非常感谢您的工作,您能帮我理解一下,如何结合 2 个分类器和 1 个回归器吗?我想要三个输出。
您好 Hari……以下资源是您查询的绝佳起点
https://machinelearning.org.cn/ensemble-machine-learning-with-python-7-day-mini-course/
嗨 James,
您能否写一写如何优化这些模型以获得更好的结果?
您好 Saeideh……您可能会对以下资源感兴趣
https://machinelearning.org.cn/combined-algorithm-selection-and-hyperparameter-optimization/
嗨 James,
感谢您的工作。能否通过预设权重来告诉模型哪个输出层更重要?(在优化任务的意义上)。
您好 Stefan……非常欢迎!您可能会对以下资源感兴趣
https://machinelearning.org.cn/weight-initialization-for-deep-learning-neural-networks/
您好。在我的情况下,我有两个不同的目标变量。一个是二元的(分类),另一个是连续的(回归)。在定义我的 X 和 y 时,我是否需要这样做
X = df.drop(columns=[‘y_1’, ‘y_2’], axis=1)?
y_clas = df[‘y_1’]
y_reg = df[‘y_2’]?
如果是这样,我该如何以及在哪里将这些输入到网络中?
您好 Wonder……是的,在为二元分类和回归任务定义特征矩阵 (X) 和目标变量 (y) 时,您的方法是正确的。
1. **定义 X 和 y:**
–
X
:您的特征矩阵通常包含您将用于进行预测的所有预测变量/特征。–
y_clas
:这将是您的二元分类目标变量。–
y_reg
:这将是您的连续回归目标变量。因此,您的代码片段如下所示
python
X = df.drop(columns=['y_1', 'y_2'], axis=1)
y_clas = df['y_1']
y_reg = df['y_2']
2. **训练模型:**
– 对于二元分类任务,您将使用
X
和y_clas
训练一个分类器(例如,逻辑回归、决策树、神经网络)。– 对于回归任务,您将使用
X
和y_reg
训练一个回归模型(例如,线性回归、随机森林回归、神经网络)。以下是如何使用 Python 的 TensorFlow 和 Keras 为每个任务训练神经网络的简化示例
python
# Binary Classification Model
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
# Define and compile the model
model_clas = Sequential()
model_clas.add(Dense(64, activation='relu', input_shape=(X.shape[1],)))
model_clas.add(Dense(1, activation='sigmoid')) # Assuming binary classification
model_clas.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
# 训练模型
model_clas.fit(X, y_clas, epochs=10, batch_size=32, validation_split=0.2)
# Regression Model
# Define and compile the model
model_reg = Sequential()
model_reg.add(Dense(64, activation='relu', input_shape=(X.shape[1],)))
model_reg.add(Dense(1)) # Output layer for regression
model_reg.compile(optimizer='adam', loss='mean_squared_error')
# Train the model
model_reg.fit(X, y_reg, epochs=10, batch_size=32, validation_split=0.2)
在这些示例中,
X
是特征矩阵,包含除目标变量y_1
和y_2
之外的所有预测变量。y_clas
用于训练二元分类模型,y_reg
用于训练回归模型。请确保根据您的具体问题和数据调整架构、激活函数、损失函数和其他超参数。
你好,
有人能帮我理解一下,为什么当我运行 Jupyter labs 中的代码时,epoch 的输出数据行没有像这样分离输出层损失吗?
纪元 145/150
88/88 – 0s – loss: 6.5707 – dense_2_loss: 4.5396 – dense_3_loss: 2.0311
它只是输出
纪元 145/150
88/88 – 0s – loss: 6.5707
您好 Jordan……您尝试过在 Google Colab 中运行您的代码吗?只是好奇您是否会遇到任何不同。
你好,这个方法可以叫做多任务吗?
您好 struggling……是的,您所指的方法确实可以称为多任务。在神经网络的背景下,多任务是指训练一个模型同时执行多个任务。这些任务可以是不同类型的,例如分类和回归。
例如,在多任务神经网络中,您可能有一个输出层用于分类(例如,预测类别标签),另一个输出层用于回归(例如,预测连续值)。该模型学习早期层的共享表示,然后分支以处理特定任务,从而允许它利用任务之间的共性,同时仍然专注于每个任务。
多任务处理可能是有益的,因为它通常可以提高泛化能力,尤其是在任务相关的情况下。该模型可以从两个任务的组合信号中学习,与分别训练分类和回归模型相比,可能提高每个任务的性能。
好的,我明白了。谢谢您的回复