【问题标题】:Custom word2vec Transformer on pandas dataframe and using it in FeatureUnionpandas 数据帧上的自定义 word2vec Transformer 并在 FeatureUnion 中使用它
【发布时间】:2018-11-15 14:37:25
【问题描述】:

对于下面的pandas DataFrame df,我想将type 列转换为OneHotEncoding,并使用字典word2vecword 列转换为其向量表示。然后我想将两个转换后的向量与count 列连接起来,形成最终的分类特征。

>>> df
       word type  count
0     apple    A      4
1       cat    B      3
2  mountain    C      1 

>>> df.dtypes
word       object
type     category
count       int64

>>> word2vec
{'apple': [0.1, -0.2, 0.3], 'cat': [0.2, 0.2, 0.3], 'mountain': [0.4, -0.2, 0.3]}

我定义了自定义的Transformer,并使用FeatureUnion 连接功能。

from sklearn.base import BaseEstimator, TransformerMixin
from sklearn.pipeline import Pipeline, FeatureUnion
from sklearn.preprocessing import OneHotEncoder

class w2vTransformer(TransformerMixin):

    def __init__(self,word2vec):
        self.word2vec = word2vec

    def fit(self,x, y=None):
        return self

    def wv(self, w):
        return self.word2vec[w] if w in self.word2vec else [0, 0, 0]

    def transform(self, X, y=None):
         return df['word'].apply(self.wv)

pipeline = Pipeline([
    ('features', FeatureUnion(transformer_list=[
        # Part 1: get integer column
        ('numericals', Pipeline([
            ('selector', TypeSelector(np.number)),
        ])),

        # Part 2: get category column and its onehotencoding
        ('categoricals', Pipeline([
            ('selector', TypeSelector('category')),
            ('labeler', StringIndexer()),
            ('encoder', OneHotEncoder(handle_unknown='ignore')),
        ])), 

        # Part 3: transform word to its embedding
        ('word2vec', Pipeline([
            ('w2v', w2vTransformer(word2vec)),
        ]))
    ])),
])

当我运行pipeline.fit_transform(df) 时,我得到了错误:blocks[0,:] has incompatible row dimensions. Got blocks[0,2].shape[0] == 1, expected 3.

但是,如果我从管道中删除 word2vec Transformer(第 3 部分),则管道(第 1 部分 1 + 第 2 部分)工作正常。

>>> pipeline_no_word2vec.fit_transform(df).todense()
matrix([[4., 1., 0., 0.],
        [3., 0., 1., 0.],
        [1., 0., 0., 1.]])

如果我只保留管道中的 w2v 变压器,它也可以工作。

>>> pipeline_only_word2vec.fit_transform(df)
array([list([0.1, -0.2, 0.3]), list([0.2, 0.2, 0.3]),
       list([0.4, -0.2, 0.3])], dtype=object)

我的猜测是我的w2vTransformer 班级有问题,但不知道如何解决。请帮忙。

【问题讨论】:

    标签: pandas scikit-learn pipeline word2vec


    【解决方案1】:

    这个错误是由于 FeatureUnion 期望它的每个部分都有一个二维数组。

    现在您的 FeatureUnion 的前两部分:- 'numericals''categoricals' 正在正确发送形状的二维数据(n_samples,n_features)。

    n_samples = 3 在您的示例数据中。 n_features 将取决于各个部分(例如 OneHotEncoder 将在第二部分更改它们,但在第一部分将是 1)。

    但是第三部分 'word2vec' 返回一个 pandas.Series 对象,它具有一维形状 (3,)。 FeatureUnion 默认采用形状 (1, 3),因此抱怨它与其他块不匹配。

    所以你需要纠正那个形状。

    现在,即使您只是在最后执行 reshape() 并将其更改为 shape (3,1),您的代码也不会运行,因为该数组的内部内容是您的 word2vec 字典中的列表,而不是正确转换为二维数组。相反,它会变成一个列表数组。

    更改 w2vTransformer 以纠正错误:

    class w2vTransformer(TransformerMixin):
        ...
        ...
        def transform(self, X, y=None):
            return np.array([np.array(vv) for vv in X['word'].apply(self.wv)])
    

    然后管道将工作。

    【讨论】:

      猜你喜欢
      • 2018-04-26
      • 2023-01-07
      • 2021-06-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-16
      • 2016-06-18
      • 2018-03-13
      相关资源
      最近更新 更多