微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

FeatureTools 创建的特征会构建不一致的模型

如何解决FeatureTools 创建的特征会构建不一致的模型

我有一个不平衡数据集,其中有 2 亿个来自第 0 类的数据和 8000 个来自第 1 类的数据。我采用了两种不同的方法来构建模型。

  1. 随机采样一个比例为 1:4 的新数据集。意味着 0 类的 32000 和 1 类的 8000。然后使用特征工具生成特征(在我的例子中生成 70 个特征)并将数据集拆分为 test_size = 0.2 的训练集和测试集,并对少数类进行分层。使用随机森林算法构建模型并预测测试集。

代码

import ....
df = pd.read_csv(...)
label = df['target']
es = ft.EntitySet(id='maintable')

es = es.entity_from_dataframe(entity_id='maintable',dataframe=df,make_index=True,index='index',time_index='date_info',variable_types={'personal_id': ft.variable_types.Categorical,'category_id': ft.variable_types.Categorical,'name': ft.variable_types.Categorical})

es.normalize_entity(base_entity_id='maintable',new_entity_id='personal_id')
es.normalize_entity(base_entity_id='maintable',new_entity_id='category_id')
es.normalize_entity(base_entity_id='maintable',new_entity_id='name')

fm,features = ft.dfs(entityset=es,target_entity='maintable',max_depth=3)

fm = fm.set_index(label.index)
fm['target'] = label

X = fm[fm.columns.difference(['target'])]
y = fm['target']

X_train,X_test,y_train,y_test = train_test_split(X,y,random_state=42,stratify=y,test_size=0.2)

rf = RandomForestClassifier(random_state=42,n_jobs=-1)
scaler = StandardScaler()

X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)

rf.fit(X_train,y_train)
y_pred = rf.predict(X_test)

#print results
.....
  1. 拆分第 1 类的所有数据,60% 用于训练集,40% 用于测试集。训练集的类比与第一种方法(1:4)相同,但对于测试集,它是 1:200。使用特征工具(重新创建了 70 个特征),使用随机森林算法构建模型并预测测试集。

代码

import ....
df = pd.read_csv(...)
# I merged randomly generated(with java) train and test sets to create features with featuretools. I created a column 'test_data' which takes two binary values (1 for test set 0 for train set) so I can separate train and test set for fitting model and predicting. 
label = df['target','test_data']
es = ft.EntitySet(id='maintable')

es = es.entity_from_dataframe(entity_id='maintable',max_depth=3)

fm = fm.set_index(label.index)
fm['target','test_data'] = label

df_train = fm.loc[fm['test_data'] == 0]
df_test = fm.loc[fm['test_data'] == 1]

#Drop 'test_data' column because I dont need it anymore
df_train = df_train.drop(['test_data'],axis=1)
df_test = df_test.drop(['test_data'],axis=1)

X_train = df_train[df_train.columns.difference(['target'])]
y_train = df_train['target']

X_test = df_test[df_test.columns.difference(['target'])]
y_test = df_test['target']

rf = RandomForestClassifier(random_state=42,y_train)
y_pred = rf.predict(X_test)

#print results

现在对我来说有趣的部分开始了。以下是两种方法的结果。

1.方法 (0类为负,1类为正)

TN:6306

FP:94

TP:1385

FN:215

2.方法

TN:576743

FP:63257

TP:361

FN:2839

一个结果对我来说还不错,但第二个结果很糟糕。这怎么可能?我知道我使用较少的第 1 类数据来训练第二种方法的模型,但它应该没有太大区别。我的意思是这比抛硬币更糟糕。两种方法随机生成子集,我尝试了许多不同的子集,但结果与上述几乎相同。任何形式的帮助表示赞赏。

编辑:我可能有一个想法但不确定...我在第一种方法中使用 train_test_split。因此,训练集和测试集共享一些personal_id,但在第二种方法中,训练集和测试集具有完全不同的personal_id。当模型遇到在它无法正确预测并决定将其标记为多数类之前没有看到的personal_id 时。如果是这种情况,那么正在为给定的分类变量(过度拟合)创建特征。同样,当它遇到任何分类列的不同值时,它只会感到困惑。我怎样才能克服这样的问题?

Edit2:我测试了上面提到的想法并得到了奇怪的结果。首先,我从数据集中删除了personal_id 列,但最终得到了更好的模型。然后我测试了我的第二种方法,个人 ID 出现在训练集中也应该出现在测试集中。我以为我会得到更好的模型,但它比以前更糟。我真的很困惑...

解决方法

我同意该模型可能过度拟合并且无法概括给定新的个人 ID。我建议将标签与截止时间一起传递,以获得更结构化的训练和测试集。我将通过一个使用此数据的快速示例进行说明。

    index     name  personal_id category_id   date_info  target
0       0   Samuel            3           C  2021-07-15       0
1       1   Samuel            3           C  2021-07-15       0
2       2   Samuel            3           C  2021-07-15       0
3       3   Samuel            3           C  2021-07-15       0
4       4  Rosanne            2           C  2021-05-11       0
..    ...      ...          ...         ...         ...     ...
95     95    Donia            1           C  2020-09-27       1
96     96    Donia            1           C  2020-09-27       1
97     97  Fleming            1           A  2021-06-15       1
98     98     Fred            1           C  2021-02-28       0
99     99  Giacomo            1           A  2021-06-19       1

[100 rows x 6 columns]

首先,根据还包括目标列的时间索引创建截止时间。确保从原始数据中删除目标列。

target = df[['date_info','index','target']]
df.drop(columns='target',inplace=True)

然后,您可以像往常一样构造实体集。

import featuretools as ft

es = ft.EntitySet(id='maintable')
es = es.entity_from_dataframe(
    entity_id='maintable',dataframe=df,index='index',time_index='date_info',variable_types={
        'personal_id': ft.variable_types.Categorical,'category_id': ft.variable_types.Categorical,'name': ft.variable_types.Categorical
    },)
es.normalize_entity(base_entity_id='maintable',new_entity_id='personal_id',index='personal_id',new_entity_id='category_id',index='category_id')
es.normalize_entity(base_entity_id='maintable',new_entity_id='name',index='name')

现在,在 DFS 调用中,您可以传入目标截止时间。这种方法不会使用目标列来构建特征,并确保目标列与特征矩阵保持对齐。

fm,fd = ft.dfs(entityset=es,target_entity='maintable',max_depth=3,cutoff_time=target)
       personal_id category_id     name  DAY(date_info)  ...  name.NUM_UNIQUE(maintable.MONTH(date_info))  name.NUM_UNIQUE(maintable.WEEKDAY(date_info))  name.NUM_UNIQUE(maintable.YEAR(date_info))  target
index                                                    ...
59               1           C     Fred              28  ...                                            1                                              1                                           1       0
35               1           A  Giacomo              19  ...                                            1                                              1                                           1       1
82               3           B  Laverna              17  ...                                            1                                              1                                           1       0
25               2           C  Rosanne              11  ...                                            1                                              1                                           1       0
23               1           A  Giacomo              19  ...                                            1                                              1                                           1       1

然后,您可以将特征矩阵拆分为训练集和测试集。

from sklearn.model_selection import train_test_split

X_train,X_test = train_test_split(fm,test_size=.2,shuffle=False)
y_train,y_test = X_train.pop('target'),X_test.pop('target')

对于 AutoML,您可以使用 EvalML 找到最佳 ML 管道并绘制混淆矩阵。

from evalml import AutoMLSearch
from evalml.model_understanding.graphs import graph_confusion_matrix

automl = AutoMLSearch(
    X_train=X_train,y_train=y_train,problem_type='binary',allowed_model_families=['random_forest'],)
automl.search()
y_pred = automl.best_pipeline.predict(X_test)
graph_confusion_matrix(y_test,y_pred).show()

enter image description here

您可以在链接页面中找到类似的 machine learning examples。如果您觉得这有帮助,请告诉我。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?