Настраиваемый трансформер word2vec на панде и использование его в FeatureUnion - PullRequest
0 голосов
/ 06 июня 2018

Для приведенного ниже pandas DataFrame df я хочу преобразовать столбец type в OneHotEncoding и преобразовать столбец word в его векторное представление, используя словарь word2vec.Затем я хочу объединить два преобразованных вектора со столбцом 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 (Часть 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 класс, но не знаю, как это исправить.Пожалуйста, помогите.

1 Ответ

0 голосов
/ 06 июня 2018

Эта ошибка связана с тем, что FeatureUnion ожидает двухмерный массив от каждой из его частей.

Теперь первые две части вашего FeatureUnion: - 'numericals' и 'categoricals' правильныеотправка двумерных данных формы (n_samples, n_features).

n_samples = 3 в данных вашего примера.n_features будет зависеть от отдельных частей (например, OneHotEncoder изменит их во 2-й части, но в первой части будет 1).

Но третья часть 'word2vec' возвращает объект pandas.Series с 1форма (3,).FeatureUnion принимает эту форму (1, 3) по умолчанию и, следовательно, жалуется, что она не соответствует другим блокам.

Так что вам нужно исправить эту форму.

Теперь, даже если вы просто делаетеa 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)])

И после этого конвейер будет работать.

...