多输出 Scikeras
Scikeras with multioutput
我尝试创建堆叠回归器以使用 SVR 和神经网络作为估计器来预测多个输出,最终估计器是线性回归。
print(X_train.shape) #(73, 39)
print(y_train.shape) #(73, 13)
print(X_test.shape) #(19, 39)
print(y_test.shape) #(19, 13)
def build_nn():
ann = Sequential()
ann.add(Dense(40, input_dim=X_train.shape[1], activation='relu', name="Hidden_Layer_1"))
ann.add(Dense(y_train.shape[1], activation='sigmoid', name='Output_Layer'))
ann.compile( loss='mse', optimizer= 'adam', metrics = 'mse')
return ann
keras_reg = KerasRegressor(model = build_nn,optimizer="adam",optimizer__learning_rate=0.001,epochs=100,verbose=0)
stacker = StackingRegressor(estimators=[('svr',SVR()),('ann',keras_reg)], final_estimator= LinearRegression())
reg = MultiOutputRegressor(estimator=stacker)
model = reg.fit(X_train,y_train)
我可以 'fit' 模型。但是,我在尝试预测时遇到了以下问题。
prediction = reg.predict(X_test)
ValueError: all the input array dimensions for the concatenation axis must match exactly, but along dimension 0, the array at index 0 has size 19 and the array at index 1 has size 247
我想重点如下。一方面,NN 模型本身确实支持 multi-output 回归任务,定义一个类似于您构建的输出层(即具有多个节点)的输出层可能会得到解决等于输出的数量(不过,关于你的构造,我会用 activation=None
指定线性激活而不是 sigmoid 激活)。
def build_nn():
ann = Sequential()
ann.add(Dense(40, input_dim=X_train.shape[1], activation='relu', name="Hidden_Layer_1"))
ann.add(Dense(y_train.shape[1], name='Output_Layer'))
ann.compile(loss='mse', optimizer= 'adam', metrics = 'mse')
return ann
另一方面,在这里,您试图通过在 [=14] 上调用 MultiOutputRegressor
构造函数来解决 multi-output 回归任务=] 实例,即通过为每个输出显式训练一个回归模型,回归模型是多个回归模型的组合。
这个问题是由于 StackingRegressor
基本估计器的预测的串联,特别是它们的不同形状。确实:
- 如您在 https://github.com/scikit-learn/scikit-learn/blob/7e1e6d09bcc2eaeba98f7e737aac2ac782f0e5f1/sklearn/multioutput.py#L234
中所见,StackingRegressor
需要 MultiOutputRegressor
实例的预测
- 反过来,在
StackingRegressor
中,每个单独估计器的预测被堆叠在一起,并用作 final_estimator
的输入来计算预测。 .predict()
在 https://github.com/scikit-learn/scikit-learn/blob/7e1e6d09bcc2eaeba98f7e737aac2ac782f0e5f1/sklearn/ensemble/_stacking.py#L267 中对 final_estimator
调用(特别是,您可以看到它正在将 转换后的 X 作为输入)。
- 转换后的 X 是
StackingRegressor
基 estimators
的预测串联的结果,正如您在 [=42= 中看到的那样].
这就是说,在 StackingRegressor
基础 estimators
中,您有一个 SVR()
模型,其设计无法原生解决 multi-output 回归任务和一个 KerasRegressor
神经网络,按照您的定义,它意味着能够在不委托的情况下解决 multi-output 回归任务至 MultiOutputRegressor
。因此,_concatenate_predictions
中发生的是 dimensionally-inconsistent 预测来自 SVR()
(形状为 (19,)=(n_samples,)
的一维数组最终重塑为 (19,1) 数组)和 KerasRegressor
(形状为 (19,13)=(n_samples,n_outputs)
的二维数组最终变平并重塑为 (19*13,1)=(247,1) 数组)。这反映了这样一个事实,即让你的神经网络输出层的节点数量等于输出数量不能适应 StackingRegressor
与另一个基础估计器,它应该通过 MultiOutputRegressor
必须扩展才能能够解决 multi-output 回归任务。
因此,对我来说,如果你想保持相同的“架构”,你应该让你的神经网络有一个只有一个节点的输出层,这样它的预测就可以与 SVR
模型并可供 StackingRegressor
final_estimator
访问并最终委托给 MultiOutputRegressor
.
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split
import tensorflow as tf
import tensorflow.keras
from tensorflow.keras.layers import Dense
from tensorflow.keras.models import Sequential
from scikeras.wrappers import KerasRegressor
from sklearn.ensemble import StackingRegressor
from sklearn.multioutput import MultiOutputRegressor
from sklearn.linear_model import LinearRegression
from sklearn.svm import SVR
X, y = make_regression(n_samples=92, n_features=39, n_informative=39, n_targets=13, random_state=42)
print(X.shape, y.shape)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
print(X_train.shape, y_train.shape, X_test.shape, y_test.shape)
def build_nn():
ann = Sequential()
ann.add(Dense(40, input_dim=X_train.shape[1], activation='relu', name="Hidden_Layer_1"))
ann.add(Dense(1, name='Output_Layer'))
ann.compile(loss='mse', optimizer= 'adam', metrics = 'mse')
return ann
keras_reg = KerasRegressor(model = build_nn, optimizer="adam",
optimizer__learning_rate=0.001, epochs=100, verbose=0)
stacker = StackingRegressor(estimators=[('svr', SVR()), ('ann', keras_reg)], final_estimator = LinearRegression())
reg = MultiOutputRegressor(estimator=stacker)
reg.fit(X_train,y_train)
predictions = reg.predict(X_test)
我尝试创建堆叠回归器以使用 SVR 和神经网络作为估计器来预测多个输出,最终估计器是线性回归。
print(X_train.shape) #(73, 39)
print(y_train.shape) #(73, 13)
print(X_test.shape) #(19, 39)
print(y_test.shape) #(19, 13)
def build_nn():
ann = Sequential()
ann.add(Dense(40, input_dim=X_train.shape[1], activation='relu', name="Hidden_Layer_1"))
ann.add(Dense(y_train.shape[1], activation='sigmoid', name='Output_Layer'))
ann.compile( loss='mse', optimizer= 'adam', metrics = 'mse')
return ann
keras_reg = KerasRegressor(model = build_nn,optimizer="adam",optimizer__learning_rate=0.001,epochs=100,verbose=0)
stacker = StackingRegressor(estimators=[('svr',SVR()),('ann',keras_reg)], final_estimator= LinearRegression())
reg = MultiOutputRegressor(estimator=stacker)
model = reg.fit(X_train,y_train)
我可以 'fit' 模型。但是,我在尝试预测时遇到了以下问题。
prediction = reg.predict(X_test)
ValueError: all the input array dimensions for the concatenation axis must match exactly, but along dimension 0, the array at index 0 has size 19 and the array at index 1 has size 247
我想重点如下。一方面,NN 模型本身确实支持 multi-output 回归任务,定义一个类似于您构建的输出层(即具有多个节点)的输出层可能会得到解决等于输出的数量(不过,关于你的构造,我会用 activation=None
指定线性激活而不是 sigmoid 激活)。
def build_nn():
ann = Sequential()
ann.add(Dense(40, input_dim=X_train.shape[1], activation='relu', name="Hidden_Layer_1"))
ann.add(Dense(y_train.shape[1], name='Output_Layer'))
ann.compile(loss='mse', optimizer= 'adam', metrics = 'mse')
return ann
另一方面,在这里,您试图通过在 [=14] 上调用 MultiOutputRegressor
构造函数来解决 multi-output 回归任务=] 实例,即通过为每个输出显式训练一个回归模型,回归模型是多个回归模型的组合。
这个问题是由于 StackingRegressor
基本估计器的预测的串联,特别是它们的不同形状。确实:
- 如您在 https://github.com/scikit-learn/scikit-learn/blob/7e1e6d09bcc2eaeba98f7e737aac2ac782f0e5f1/sklearn/multioutput.py#L234 中所见,
- 反过来,在
StackingRegressor
中,每个单独估计器的预测被堆叠在一起,并用作final_estimator
的输入来计算预测。.predict()
在 https://github.com/scikit-learn/scikit-learn/blob/7e1e6d09bcc2eaeba98f7e737aac2ac782f0e5f1/sklearn/ensemble/_stacking.py#L267 中对final_estimator
调用(特别是,您可以看到它正在将 转换后的 X 作为输入)。 - 转换后的 X 是
StackingRegressor
基estimators
的预测串联的结果,正如您在 [=42= 中看到的那样].
StackingRegressor
需要 MultiOutputRegressor
实例的预测
这就是说,在 StackingRegressor
基础 estimators
中,您有一个 SVR()
模型,其设计无法原生解决 multi-output 回归任务和一个 KerasRegressor
神经网络,按照您的定义,它意味着能够在不委托的情况下解决 multi-output 回归任务至 MultiOutputRegressor
。因此,_concatenate_predictions
中发生的是 dimensionally-inconsistent 预测来自 SVR()
(形状为 (19,)=(n_samples,)
的一维数组最终重塑为 (19,1) 数组)和 KerasRegressor
(形状为 (19,13)=(n_samples,n_outputs)
的二维数组最终变平并重塑为 (19*13,1)=(247,1) 数组)。这反映了这样一个事实,即让你的神经网络输出层的节点数量等于输出数量不能适应 StackingRegressor
与另一个基础估计器,它应该通过 MultiOutputRegressor
必须扩展才能能够解决 multi-output 回归任务。
因此,对我来说,如果你想保持相同的“架构”,你应该让你的神经网络有一个只有一个节点的输出层,这样它的预测就可以与 SVR
模型并可供 StackingRegressor
final_estimator
访问并最终委托给 MultiOutputRegressor
.
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split
import tensorflow as tf
import tensorflow.keras
from tensorflow.keras.layers import Dense
from tensorflow.keras.models import Sequential
from scikeras.wrappers import KerasRegressor
from sklearn.ensemble import StackingRegressor
from sklearn.multioutput import MultiOutputRegressor
from sklearn.linear_model import LinearRegression
from sklearn.svm import SVR
X, y = make_regression(n_samples=92, n_features=39, n_informative=39, n_targets=13, random_state=42)
print(X.shape, y.shape)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
print(X_train.shape, y_train.shape, X_test.shape, y_test.shape)
def build_nn():
ann = Sequential()
ann.add(Dense(40, input_dim=X_train.shape[1], activation='relu', name="Hidden_Layer_1"))
ann.add(Dense(1, name='Output_Layer'))
ann.compile(loss='mse', optimizer= 'adam', metrics = 'mse')
return ann
keras_reg = KerasRegressor(model = build_nn, optimizer="adam",
optimizer__learning_rate=0.001, epochs=100, verbose=0)
stacker = StackingRegressor(estimators=[('svr', SVR()), ('ann', keras_reg)], final_estimator = LinearRegression())
reg = MultiOutputRegressor(estimator=stacker)
reg.fit(X_train,y_train)
predictions = reg.predict(X_test)