Как комбинировать элементы с выводом разных размеров с помощью scikit-learn
Я использую scikit-learn с Pipeline и FeatureUnion для извлечения функций из разных источников. Каждый образец (экземпляр) в моем наборе данных относится к документам различной длины. Моя цель состоит в том, чтобы вычислить верхний tfidf для каждого документа независимо, но я продолжаю получать это сообщение об ошибке:
ValueError: blocks [0 ,:] имеет несовместимые размеры строк. Получили блоки [0,1].shape [0] == 1, ожидаемый 2000.
2000 - размер данных обучения. Это основной код:
book_summary= Pipeline([
('selector', ItemSelector(key='book')),
('tfidf', TfidfVectorizer(analyzer='word', ngram_range(1,3), min_df=1, lowercase=True, stop_words=my_stopword_list, sublinear_tf=True))
])
book_contents= Pipeline([('selector3', book_content_count())])
ppl = Pipeline([
('feats', FeatureUnion([
('book_summary', book_summary),
('book_contents', book_contents)])),
('clf', SVC(kernel='linear', class_weight='balanced') ) # classifier with cross fold 5
])
Я написал два класса для обработки каждой функции конвейера. Моя проблема связана с конвейером book_contents, который в основном касается каждого образца и возвращает матрицу TFidf для каждой книги независимо.
class book_content_count():
def count_contents2(self, bookid):
book = open('C:/TheCorpus/'+str(int(bookid))+'_book.csv', 'r')
book_data = pd.read_csv(book, header=0, delimiter=',', encoding='latin1',error_bad_lines=False,dtype=str)
corpus=(str([user_data['text']]).strip('[]'))
return corpus
def transform(self, data_dict, y=None):
data_dict['bookid'] #from here take the name
text=data_dict['bookid'].apply(self.count_contents2)
vec_pipe= Pipeline([('vec', TfidfVectorizer(min_df = 1,lowercase = False, ngram_range = (1,1), use_idf = True, stop_words='english'))])
Xtr = vec_pipe.fit_transform(text)
return Xtr
def fit(self, x, y=None):
return self
Пример данных (пример):
title Summary bookid
The beauty and the beast is a traditional fairy tale... 10
ocean at the end of the lane is a 2013 novel by British 11
Затем каждый идентификатор будет ссылаться на текстовый файл с фактическим содержимым этих книг
Я попытался toarray
и reshape
функции, но не повезло. Любая идея, как решить эту проблему. Спасибо
Ответы
Ответ 1
Вы можете использовать Neuraxle Feature Union с пользовательским соединителем, который вам нужно будет написать самостоятельно. Joiner - это класс, переданный Neuraxle FeatureUnion для объединения результатов так, как вы ожидали.
1. Импортируйте классы Neuraxle.
from neuraxle.base import NonFittableMixin, BaseStep
from neuraxle.pipeline import Pipeline
from neuraxle.steps.sklearn import SKLearnWrapper
from neuraxle.union import FeatureUnion
2. Определите свой пользовательский класс, унаследовав его от BaseStep:
class BookContentCount(BaseStep):
def transform(self, data_dict, y=None):
transformed = do_things(...) # be sure to use SKLearnWrapper if you wrap sklearn items.
return Xtr
def fit(self, x, y=None):
return self
3. Создайте столяра, чтобы присоединиться к результатам объединения функций так, как вы хотите:
class CustomJoiner(NonFittableMixin, BaseStep):
def __init__(self):
BaseStep.__init__(self)
NonFittableMixin.__init__(self)
# def fit: is inherited from 'NonFittableMixin' and simply returns self.
def transform(self, data_inputs):
# TODO: insert your own concatenation method here.
result = np.concatenate(data_inputs, axis=-1)
return result
4. Наконец, создайте свой конвейер, передав соединителю в FeatureUnion:
book_summary= Pipeline([
('selector', SKLearnWrapper(ItemSelector(key='book'))),
('tfidf', SKLearnWrapper(TfidfVectorizer(analyzer='word', ngram_range(1,3), min_df=1, lowercase=True, stop_words=my_stopword_list, sublinear_tf=True)))
])
p = Pipeline([
('feats', FeatureUnion([
('book_summary', book_summary),
('book_contents', BookContentCount())
],
joiner=CustomJoiner()
)),
('clf', SKLearnWrapper(SVC(kernel='linear', class_weight='balanced')))
])
Примечание: если вы хотите, чтобы ваш конвейер Neuraxle превратился в конвейер scikit-learn, вы можете сделать это p = p.tosklearn()
.