GridSearchCV + StratifiedKfold в случае TFIDF - PullRequest
1 голос
/ 08 мая 2020

Я работаю над проблемой классификации, когда мне нужно предсказать класс текстовых данных. Мне нужно настроить гиперпараметры для моей модели классификации, для которой я собираюсь использовать GridSearchCV. Мне также нужно сделать StratifiedKFold, потому что мои данные несбалансированы. Я знаю, что GridSearchCV внутренне использует StratifiedKFold, если у нас есть мультиклассовая классификация.

Я прочитал здесь , что в случае TfidfVectorizer мы применяем fit_transform к обучающим данным и преобразуем только в тестовые данные.

Это то, что я сделал ниже, используя StratifiedKFold.

skf = StratifiedKFold(n_splits=5, random_state=5)

for train_index, test_index in skf.split(X, y):
    iteration = iteration+1
    print(f"Iteration number {iteration}")
    X_train, y_train = X.iloc[train_index], y.iloc[train_index]
    X_test, y_test = X.iloc[test_index], y.iloc[test_index]

    train_tfid = tfidf_vectorizer.fit_transform(X_train.values.astype('U'))
    test_tfid = tfidf_vectorizer.transform(X_test.values.astype('U'))

    svc_model = linear_model.SGDClassifier()
    svc_model.fit(train_tfid, y_train.values.ravel())

Точность / f1, которую я получаю, не очень хорошая, поэтому подумал о настройке гиперпараметров с помощью GridSearchCV. В GridSearchCV мы делаем

c_space = np.logspace(-5, 8, 15) 
param_grid = {'C': c_space} 

# Instantiating logistic regression classifier 
logreg = LogisticRegression() 

# Instantiating the GridSearchCV object 
logreg_cv = GridSearchCV(logreg, param_grid, cv = 5) 

logreg_cv.fit(X, y) 

По моему мнению, logreg_cv.fit(X, y) будет внутренне разделить X на X_train, X_test k раз, а затем будет делать прогнозы, чтобы дать нам лучшую оценку.

В моем случае каким должен быть X? Если это X, который сгенерирован после fit_transform, то внутри, когда X разделен на обучение и тестирование, тестовые данные прошли fit_transform, но в идеале они должны преобразовываться только в go.

Меня беспокоит, что в моем случае внутри GridSearchCV как я мог бы контролировать, что fit_transform применяется только для данных обучения, а преобразование применяется к тестовым данным (данные проверки).

, потому что, если он внутренне применяет fit_transform к все данные, то это не лучшая практика.

1 Ответ

1 голос
/ 10 мая 2020

Это как раз то, что нужно для использования Pipeline в GridSearchCV. Сначала создайте конвейер с необходимыми шагами, такими как предварительная обработка данных, выбор функций и модель. Как только вы вызовете GridSearchCV в этом конвейере, он будет обрабатывать данные только на тренировочных свертках, а затем соответствовать модели.

Прочтите здесь , чтобы узнать больше о модуле выбора модели в sklearn.

from sklearn.datasets import fetch_20newsgroups
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.pipeline import Pipeline
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split, GridSearchCV
import numpy as np

cats = ['alt.atheism', 'sci.space']
newsgroups_train = fetch_20newsgroups(subset='train',
                                      remove=('headers', 'footers', 'quotes'),
                                      categories=cats)
X, y = newsgroups_train.data, newsgroups_train.target

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.1, stratify=y)


my_pipeline = Pipeline([
    ('vectorizer', CountVectorizer(stop_words='english')),
    ('clf', LogisticRegression())
])


parameters = {'clf__C': np.logspace(-5, 8, 15)}

grid_search = GridSearchCV(my_pipeline, param_grid=parameters,
                           cv=10, n_jobs=-1, scoring='accuracy')
grid_search.fit(X_train, y_train)

print(grid_search.best_params_)
# {'clf__C': 0.4393970560760795}

grid_search.score(X_test, y_test)
# 0.8981481481481481
...