python - 将 Keras 集成到 SKLearn 管道?
问题描述
我有一个 sklearn 管道对异构数据类型(布尔、分类、数字、文本)执行特征工程,并想尝试使用神经网络作为我的学习算法来拟合模型。我在输入数据的形状方面遇到了一些问题。
我想知道我正在尝试做的事情是否可能,或者我是否应该尝试不同的方法?
我尝试了几种不同的方法,但收到以下错误:
Error when checking input: expected dense_22_input to have shape (11,) but got array with shape (30513,)
=> 我有 11 个输入特征......所以我尝试将我的 X 和 y 转换为数组,现在得到这个错误ValueError: Specifying the columns using strings is only supported for pandas DataFrames
=> 我认为这是因为ColumnTransformer()
我指定列名的位置
print(X_train_OS.shape)
print(y_train_OS.shape)
(22354, 11)
(22354,)
from keras.models import Sequential
from keras.layers import Dense
from keras.wrappers.scikit_learn import KerasClassifier
from keras.utils import to_categorical # OHE
X_train_predictors = df_train_OS.drop("label", axis=1)
X_train_predictors = X_train_predictors.values
y_train_target = to_categorical(df_train_OS["label"])
y_test_predictors = test_set.drop("label", axis=1)
y_test_predictors = y_test_predictors.values
y_test_target = to_categorical(test_set["label"])
print(X_train_predictors.shape)
print(y_train_target.shape)
(22354, 11)
(22354, 2)
def keras_classifier_wrapper():
clf = Sequential()
clf.add(Dense(32, input_dim=11, activation='relu'))
clf.add(Dense(2, activation='softmax'))
clf.compile(loss='categorical_crossentropy', optimizer='adam', metrics=["accuracy"])
return clf
TOKENS_ALPHANUMERIC_HYPHEN = "[A-Za-z0-9\-]+(?=\\s+)"
boolTransformer = Pipeline(steps=[
('bool', PandasDataFrameSelector(BOOL_FEATURES))])
catTransformer = Pipeline(steps=[
('cat_imputer', SimpleImputer(strategy='constant', fill_value='missing')),
('cat_ohe', OneHotEncoder(handle_unknown='ignore'))])
numTransformer = Pipeline(steps=[
('num_imputer', SimpleImputer(strategy='constant', fill_value=0)),
('num_scaler', StandardScaler())])
textTransformer_0 = Pipeline(steps=[
('text_bow', CountVectorizer(lowercase=True,\
token_pattern=TOKENS_ALPHANUMERIC_HYPHEN,\
stop_words=stopwords))])
textTransformer_1 = Pipeline(steps=[
('text_bow', CountVectorizer(lowercase=True,\
token_pattern=TOKENS_ALPHANUMERIC_HYPHEN,\
stop_words=stopwords))])
FE = ColumnTransformer(
transformers=[
('bool', boolTransformer, BOOL_FEATURES),
('cat', catTransformer, CAT_FEATURES),
('num', numTransformer, NUM_FEATURES),
('text0', textTransformer_0, TEXT_FEATURES[0]),
('text1', textTransformer_1, TEXT_FEATURES[1])])
clf = KerasClassifier(keras_classifier_wrapper, epochs=100, batch_size=500, verbose=0)
PL = Pipeline(steps=[('feature_engineer', FE),
('keras_clf', clf)])
PL.fit(X_train_predictors, y_train_target)
#PL.fit(X_train_OS, y_train_OS)
我想我理解这里的问题,但不知道如何解决它。如果无法将 sklearn ColumnTransformer+Pipeline 集成到 Keras 模型中,Keras 是否有一个很好的方法来处理固定数据类型给特征工程师?谢谢!
解决方案
看起来您正在通过各种列转换器传递 11 列原始数据,并且维度的数量正在扩展到 30,513(在对文本进行计数矢量化、一种热编码等之后)。您的神经网络架构设置为仅接受 11 个输入特征,但正在传递您(现在已转换)的 30,513 个特征,这就是错误 1 所解释的内容。
因此,您需要修改input_dim
神经网络以匹配特征提取管道中创建的特征数量。
您可以做的一件事是使用SelectKBest在它们之间添加一个中间步骤,并将其设置为 20,000 之类的值,以便您确切知道最终将有多少特征传递给分类器。
这是谷歌机器学习网站上的一个很好的指南和流程图——链接——查看流程图——在这里你可以看到他们在训练模型之前在管道中有一个“选择前 k 个特征”步骤。
因此,请尝试将代码的这些部分更新为:
def keras_classifier_wrapper():
clf = Sequential()
clf.add(Dense(32, input_dim=20000, activation='relu'))
clf.add(Dense(2, activation='softmax'))
clf.compile(loss='categorical_crossentropy', optimizer='adam', metrics=["accuracy"])
return clf
和
from sklearn.feature_selection import SelectKBest
select_best_features = SelectKBest(k=20000)
PL = Pipeline(steps=[('feature_engineer', FE),
('select_k_best', select_best_features),
('keras_clf', clf)])
推荐阅读
- c++ - 用字符串中的正斜杠替换反斜杠(std::replace 适用于 Windows,但不适用于 linux)
- mysql - Having problems with complex query (Laravel Eloquent)
- javascript - 如何进入嵌套对象结构中的每个对象?
- php - 更新 woocommerce 产品时使用大量 php 内存
- c# - 从 Xamarin 条目外的物理激光扫描仪捕获输入
- mysql - 如何从 typeorm querybuilder 中的返回列中删除前缀
- java - 当未经授权的用户尝试使用未知用户名和密码登录时,spring-security 项目崩溃
- tensorflow - TensorFlow 中的 np.resize 等价物
- dart - List.removeRange() 方法如何以及为什么会影响其他变量?
- java - 重写@PostConstruct 方法时,是否在创建子项时调用父项中的方法?