【问题标题】:fit or fit_transform if I used StandardScaler on the entire dataset?如果我在整个数据集上使用 StandardScaler,fit 还是 fit_transform?
【发布时间】:2021-04-18 15:21:00
【问题描述】:

我有一个名为 features 的数据框,我按如下方式缩放数据:


col_names=features.columns

scaler=StandardScaler()
scaler.fit(features)
standardized_features=scaler.transform(features)
standardized_features.shape
df=pd.DataFrame(data=standardized_features,columns=col_names)

然后我将训练集和测试集拆分如下:

df_idx = df[df.Date == '1996-12-01'].index[0]
df_targets=df['Label'].values
df_features=df.drop(['Regime','Date','Label'], axis=1)

df_training_features = df.iloc[:df_idx,:].drop(['Regime','Date','Label'], axis=1)
df_validation_features = df.iloc[df_idx:, :].drop(['Regime','Date','Label'], axis=1)

df_training_targets = df['Label'].values
df_training_targets=df_training_targets[:df_idx]

df_validation_targets = df['Label'].values
df_validation_targets=df_validation_targets[df_idx:]

最后我测试了不同的方法:

scoring='f1' 
kfold = model_selection.TimeSeriesSplit(n_splits=5) 
models = []

models.append(('LR', LogisticRegression(C=1e10, class_weight = 'balanced')))
models.append(('KNN', KNeighborsClassifier()))
models.append(('GB', GradientBoostingClassifier(random_state = 42)))
models.append(('ABC', AdaBoostClassifier(random_state = 42)))
models.append(('RF', RandomForestClassifier(class_weight = 'balanced')))
models.append(('XGB', xgb.XGBClassifier(objective='binary:logistic', booster='gbtree')))

results = []
names = []
lb = preprocessing.LabelBinarizer()

for name, model in models:
    cv_results = model_selection.cross_val_score(estimator = model, X = df_training_features, 
                                                 y = lb.fit_transform(df_training_targets), cv=kfold, scoring = scoring)
    
    model.fit(df_training_features, df_training_targets) # train the model

    fpr, tpr, thresholds= metrics.roc_curve(df_training_targets,model.predict_proba(df_training_features)[:,1])
    auc = metrics.roc_auc_score(df_training_targets,model.predict(df_training_features))
    plt.plot(fpr, tpr, label='%s ROC (area = %0.2f)' % (name, auc))
    results.append(cv_results)
    names.append(name)
    msg = "%s: %f (%f)" % (name, cv_results.mean(), cv_results.std())
    print(msg)

我的问题是:

  • 如果最初我使用 StandardScaler 缩放我的数据,那么在最后一部分中我使用 fit_transform 而不是 fit 作为 model_selection.cross_val_score 的 y 参数是否正确?为什么?
  • 对于预测,我是否应该简单地使用 model.predict(df_validation_features)?

【问题讨论】:

    标签: python-3.x scikit-learn cross-validation


    【解决方案1】:

    您必须让 StandScaler 仅包含训练数据。然后,通过这种标准化,您可以转换训练数据 a 和验证数据。

    这样做是为了对所有输入数据保持相同的标准化。想象一下,在您的训练数据中,您有一个属性的下一个值:[0,1,2]。如果您进行简单的标准化(类似于标准化),您将获得类似:[0, 0.5, 1]

    现在想象在您的验证中,您还有 3 个样本,其中一个类别具有下一个值 [0, 1, 100]。如果你适合和改造,你会[0, 0.01, 1]。这是一场灾难,因为模型被训练认为你的 1 是 0.5 缩放的。这就是您使用训练数据信息转换验证数据的原因。

    【讨论】:

    • 非常感谢 Alex,让我看看我是否明白了。基本上我应该反转代码的前两部分,首先我拆分,然后按如下方式应用 SC:scaler.fit(df_training_features)standardized_features=scaler.transform(df_training_features)(我用 df_training_features 替换特征)。第三个和最后一个代码保持不变,然后我使用 fit_transform,对吗?
    • 代替预测,model.predict(scaler.transform(df_validation_features))是否正确?
    • 是的,通过培训,您可以使用 fit_transform 进行简化。使用标注器目标,您应该做同样的事情,从训练数据中拟合并仅使用它来进行转换。预测似乎没问题,但您应该尝试一下。
    • 谢谢!!只有一件事不清楚,但这是我的错......“使用标签器目标,你应该做同样的事情,从训练数据中拟合并只使用它来转换”。在 model_selection.cross_val_score 中,X= df_training_features 已经按照您所说的进行了拟合和变换,Y 没有缩放(因为我只在特征而不是目标上应用 SC)所以为简单起见,我做了 y = lb.fit_transform(df_training_targets),这是正确的?同样在将预测(第二条评论)与验证目标(Y_test)进行比较时,我应该首先将验证目标缩放为 scaler.transform(df_validation_target),对吗?
    • 你在两个问题上都是正确的! :) 很高兴我的评论对你有帮助
    猜你喜欢
    • 2021-06-03
    • 2021-04-19
    • 2016-08-25
    • 2019-05-21
    • 2020-03-24
    • 2020-07-21
    • 2021-05-17
    • 2019-06-08
    • 1970-01-01
    相关资源
    最近更新 更多