Groupby 在一列 pandas 数据帧上,并使用 GridsearchCv 使用通用 sklearn 管道训练每个组的特征和目标 (X, y)

Posted

技术标签:

【中文标题】Groupby 在一列 pandas 数据帧上,并使用 GridsearchCv 使用通用 sklearn 管道训练每个组的特征和目标 (X, y)【英文标题】:Groupby on one column of pandas dataframe, and train feature and target (X, y) of each group with a common sklearn pipeline using GridsearchCv 【发布时间】:2018-05-22 01:54:13 【问题描述】:

我有一个具有以下结构的熊猫数据框:

    pd.DataFrame("user_id": ['user_id1', 'user_id1', 'user_id1', 'user_id2', 'user_id2'],
      'meeting': ['text1', 'text2', 'text3', 'text4', 'text5'], 'label': ['a,b', 'a', 'a,c', 'x', 'x,y' ])

共有 12 个 user_id。我有如下管道:

    knn_tfidf = Pipeline([('tf_idf', TfidfVectorizer(stop_words='english')),
                 ('model', OneVsRestClassifier(KNeighborsClassifier())])

一个参数网格如下:

    param_grid_1 = 'tf_idf__max_df': (0.25, 0.5, 0.75),
             'tf_idf__ngram_range': [(1, 1), (1, 2), (2,2) (1, 3)],
              'model__estimator_n_neighbors' : [np.range(1,30)]
             

最后是 GridSearchCV:

    Grid_Search_tune = GridSearchCV(knn_tfidf, param_grid_1, cv=2)

我需要为每个用户创建一个具有相应 X 和 y 值的模型。对于一个用户,我可以执行以下操作:

    t = df[df.user_id == 'user_id1']

从 t 中提取 X 和 y。将 y 传递给一个 Multi labelBinarizer(),然后在实例化管道、param_grid 和 GridsearchCV 之后,我可以这样做:

    Grid_Search_tune.fit(X, y)

为每个用户重复 12 次此操作是重复的。所以我遍历了分组的熊猫数据框。这是我所做的:

    g = df.groupby('user_id')

    for names, groups in g:

X = groups.meeting_subject.as_matrix()
labels = [x.split(', ') for x in groups.priority_label.tolist()]
mlb = MultiLabelBinarizer()
y = mlb.fit_transform(labels)

knn_tfidf = Pipeline([('tf_idf', TfidfVectorizer(stop_words='english')),
                     ('model', OneVsRestClassifier(KNeighborsClassifier()))])

param_grid_1 = 'tf_idf__max_df': (0.25, 0.5, 0.75),
                 'tf_idf__ngram_range': [(1, 2), (2,2), (1, 3)], 'model__estimator__n_neighbors': np.arange(1,4)

Grid_Search_tune = GridSearchCV(knn_tfidf, param_grid_1, cv=2)

all_estimators = Grid_Search_tune.fit(X, y)

best_of_all_estimators = Grid_Search_tune.best_estimator_

print(best_of_all_estimators)

这给了我这样的输出:

    user_id1
    Pipeline(memory=None,
 steps=[('tf_idf', TfidfVectorizer(analyzer=u'word', binary=False, decode_error=u'strict',
    dtype=<type 'numpy.int64'>, encoding=u'utf-8', input=u'content',
    lowercase=True, max_df=0.25, max_features=None, min_df=1,
    ngram_range=(2, 2), norm=u'l2', preprocessor=None, smooth_idf=T...tric_params=None, n_jobs=1, n_neighbors=1, p=2,
       weights='uniform'),
      n_jobs=1))])

user_id2

    Pipeline(memory=None,
 steps=[('tf_idf', TfidfVectorizer(analyzer=u'word', binary=False, decode_error=u'strict',
    dtype=<type 'numpy.int64'>, encoding=u'utf-8', input=u'content',
    lowercase=True, max_df=0.25, max_features=None, min_df=1,
    ngram_range=(1, 2), norm=u'l2', preprocessor=None, smooth_idf=T...tric_params=None, n_jobs=1, n_neighbors=1, p=2,
       weights='uniform'),
      n_jobs=1))])

以此类推,直到 user_id12 和相应的管道。我不知道这是否是正确的做法,从这里开始我迷路了。如果我这样做:

    best_of_all_estimators.predict(['some_text_string'])

我得到了所有 12 个模型的预测。如何使用 for 循环变量 'names' 对我的模型进行键控或索引,这样当我这样做时:

    str(raw_input('Choose user_id from above list:'))

假设我选择 user_id3 ,然后

    str(raw_input('Enter text string:'))

我输入“一些随机字符串”。为属于 user_id3 的 X 和 y 训练的模型被拉起,并对该模型进行预测,而不是针对所有模型。此处链接了一个非常相似的问题。 training an ML model on selected parts of a data frame。我是初学者,我真的很挣扎!请,请帮助!提前致谢。

【问题讨论】:

【参考方案1】:

显然 Pipeline 不支持更改样本数量,例如在 groupby 或其他聚合中。

这是一个类似的问题和可能的解决方法。

sklearn: Have an estimator that filters samples

【讨论】:

我已经编辑了这个问题,添加了一些代码,并链接到一个非常相似的问题。除了这里我没有使用 Spark,并且循环对我来说很好。请帮忙!谢谢。

以上是关于Groupby 在一列 pandas 数据帧上,并使用 GridsearchCv 使用通用 sklearn 管道训练每个组的特征和目标 (X, y)的主要内容,如果未能解决你的问题,请参考以下文章

在数据帧上的 pandas groupby 之后循环遍历组

使用 pandas 在数据帧上执行 groupby,按计数排序并获取 python 中的前 2 个计数

在 pandas 数据帧上同时操作 groupby 和 resample?

Python/Pandas - 结合 groupby 平均值和最小值

Pandas groupby 类别,评级,从每个类别中获得最高价值?

如何对一列执行 pandas groupby 操作,但将另一列保留在结果数据框中