我在Sklearn的Pipeline()
类中使用SelectKBest()
来将特征数量从30个减少到最佳的5个。当我训练分类器时,测试结果如预期般因特征选择而有所不同。然而,我在代码中发现了一个错误,但似乎在运行时并未引起实际错误。
当我调用predict()
时,我意识到它仍然将所有30个特征作为输入,好像没有进行特征选择一样。尽管我只在最佳的5个特征上训练了模型。如果只在5个最佳特征上训练SVM,然后给它30个特征来预测类别,肯定会崩溃,对吗?
在我的train_model(df)
函数中,我的代码如下所示:
def train_model(df): x,y = balance_dataset(df) X_train, X_test, y_train, y_test = train_test_split(x, y, test_size = 0.3, random_state = 0) feature_selection = SelectKBest() pipe = Pipeline([('sc', preprocessing.MinMaxScaler()), ('feature_selection', feature_selection), ('SVM', svm.SVC(decision_function_shape = 'ovr', kernel = 'poly'))]) candidate_parameters = [{'SVM__C': [0.01, 0.1, 1], 'SVM__gamma': [0.01, 0.1, 1], 'feature_selection__k': [5]}] clf = GridSearchCV(estimator = pipe, param_grid = candidate_parameters, cv = 5, n_jobs = -1) clf.fit(X_train, y_train ) return clf
然而,当我调用trade()
时会发生以下情况:
def trade(df): clf = train_model(df) for index, row in trading_set.iterrows(): features = row[:-3] #features现在是一个包含30个特征的数组,尽管模型只在5个特征上训练 if trade_balance > 0: trades[index] = trade_balance if clf.predict(features) == 1: #所以这应该崩溃并给出输入形状错误,但它没有 #其余代码不必要#
所以我的问题是,我如何知道模型真的只在5个最佳特征上进行训练?
回答:
你的代码是正确的,没有理由会给你抛出任何错误。你混淆了管道对象和模型本身,后者只是管道的一个组成部分。
在你的例子中,管道接收30个特征,对它们进行缩放,选择5个最佳特征,然后在这些5个最佳特征上训练SVM。因此,你的SVM已经在5个最佳特征上进行了训练,但你仍然需要将所有30个特征传递给你的管道,因为你的管道期望数据以训练时的相同格式输入。