3

В моей схеме классификации есть несколько шагов, в том числе:Помещенные индивидуальные функции в трубопроводе Sklearn

  1. поражал (Synthetic меньшинства над дискретизация Техника)
  2. критериев Фишера для выбора функции
  3. стандартизации (Z- счет нормализации)
  4. SVC (Support Vector Классификатор)

Основные параметры должны быть настроены в СХ eme выше - процентиль (2.) и гиперпараметры для SVC (4.), и я хочу пройти поиск сетки для настройки.

Текущее решение создает «частичный» трубопровода, включая стадии 3 и 4 в схеме clf = Pipeline([('normal',preprocessing.StandardScaler()),('svc',svm.SVC(class_weight='auto'))]) и разбивает схему на две части:

1) Настройте процентиль функций, чтобы через поиск первой сетки

skf = StratifiedKFold(y) 
for train_ind, test_ind in skf: 
    X_train, X_test, y_train, y_test = X[train_ind], X[test_ind], y[train_ind], y[test_ind] 
    # SMOTE synthesizes the training data (we want to keep test data intact) 
    X_train, y_train = SMOTE(X_train, y_train) 
    for percentile in percentiles: 
     # Fisher returns the indices of the selected features specified by the parameter 'percentile' 
     selected_ind = Fisher(X_train, y_train, percentile) 
     X_train_selected, X_test_selected = X_train[selected_ind,:], X_test[selected_ind, :] 
     model = clf.fit(X_train_selected, y_train) 
     y_predict = model.predict(X_test_selected) 
     f1 = f1_score(y_predict, y_test) 

Оценки f1 будут сохранены, а затем будут усреднены по всем складкам разметки для всех процентилей, и возвращается процентиль с лучшим результатом CV. Цель ставить «процентиль для цикла» в качестве внутреннего цикла - это обеспечить справедливую конкуренцию, поскольку у нас есть одни и те же данные тренировки (включая синтезированные данные) во всех складчатых разделах для всех процентилей.

2) После определения процентиль, настройтесь на гиперпараметры по второй категории сетки

skf = StratifiedKFold(y) 
for train_ind, test_ind in skf: 
    X_train, X_test, y_train, y_test = X[train_ind], X[test_ind], y[train_ind], y[test_ind] 
    # SMOTE synthesizes the training data (we want to keep test data intact) 
    X_train, y_train = SMOTE(X_train, y_train) 
    for parameters in parameter_comb: 
     # Select the features based on the tuned percentile 
     selected_ind = Fisher(X_train, y_train, best_percentile) 
     X_train_selected, X_test_selected = X_train[selected_ind,:], X_test[selected_ind, :] 
     clf.set_params(svc__C=parameters['C'], svc__gamma=parameters['gamma']) 
     model = clf.fit(X_train_selected, y_train) 
     y_predict = model.predict(X_test_selected) 
     f1 = f1_score(y_predict, y_test) 

Это делается в очень похожим образом, за исключением того, мы настроить hyperparamter для SVC, а не процентиль возможностей для выбора.

Мои вопросы:

I) В данном решении, я вовлекают только 3. и 4. в clf и сделать 1. и 2. своего рода «вручную» в двух вложенных циклов, как описано выше. Есть ли способ включить все четыре этапа в конвейер и выполнить весь процесс сразу?

II) Если это нормально, чтобы держать первый вложенный цикл, то это возможно (и как) для упрощения следующего вложенного цикла с использованием одного трубопровода

clf_all = Pipeline([('smote', SMOTE()), 
        ('fisher', Fisher(percentile=best_percentile)) 
        ('normal',preprocessing.StandardScaler()), 
        ('svc',svm.SVC(class_weight='auto'))]) 

и просто использовать GridSearchCV(clf_all, parameter_comb) для настройки?

Обратите внимание, что как SMOTE, так и Fisher (критерии ранжирования) должны выполняться только для учебных данных в каждой складчатой ​​перегородке.

Это было бы так оценено за любые комментарии.

РЕДАКТИРОВАТЬSMOTE и Fisher показаны ниже:

def Fscore(X, y, percentile=None): 
    X_pos, X_neg = X[y==1], X[y==0] 
    X_mean = X.mean(axis=0) 
    X_pos_mean, X_neg_mean = X_pos.mean(axis=0), X_neg.mean(axis=0) 
    deno = (1.0/(shape(X_pos)[0]-1))*X_pos.var(axis=0) +(1.0/(shape(X_neg[0]-1))*X_neg.var(axis=0) 
    num = (X_pos_mean - X_mean)**2 + (X_neg_mean - X_mean)**2 
    F = num/deno 
    sort_F = argsort(F)[::-1] 
    n_feature = (float(percentile)/100)*shape(X)[1] 
    ind_feature = sort_F[:ceil(n_feature)] 
    return(ind_feature) 

SMOTE от https://github.com/blacklab/nyan/blob/master/shared_modules/smote.py, он возвращает данные, синтезированные. Я изменил его, чтобы вернуть исходные исходные данные, собранные вместе с синтезированными данными, вместе с его метками и синтезированными.

def smote(X, y): 
n_pos = sum(y==1), sum(y==0) 
n_syn = (n_neg-n_pos)/float(n_pos) 
X_pos = X[y==1] 
X_syn = SMOTE(X_pos, int(round(n_syn))*100, 5) 
y_syn = np.ones(shape(X_syn)[0]) 
X, y = np.vstack([X, X_syn]), np.concatenate([y, y_syn]) 
return(X, y) 

ответ

1

Я не знаю, где ваши SMOTE() и Fisher() функции приходят, но ответ да, вы определенно можете это сделать. Для этого вам нужно будет написать класс обертки вокруг этих функций. Самый простой способ это унаследовать sklearn в BaseEstimator и TransformerMixin классы, увидеть это для примера: http://scikit-learn.org/stable/auto_examples/hetero_feature_union.html

Если это не делает смысл для вас, разместить информацию о по меньшей мере, одной из ваших функций (библиотека это происходит из или ваш код, если вы написали его сами), и мы можем идти оттуда.

EDIT:

Я извиняюсь, я не смотрел на ваших функций достаточно близко, чтобы понять, что они превращают вашу цель в дополнение к вашей подготовки данных (т.е. как X и Y). Трубопровод не поддерживает преобразования в вашу цель, поэтому вы будете делать их раньше, чем раньше. Для вашей справки, вот как это будет выглядеть, чтобы написать свой собственный класс для вашего процесса Fisher, который будет работать, если сама функция не должна влиять на вашу целевую переменную.

>>> from sklearn.base import BaseEstimator, TransformerMixin 
>>> from sklearn.preprocessing import StandardScaler 
>>> from sklearn.svm import SVC 
>>> from sklearn.pipeline import Pipeline 
>>> from sklearn.grid_search import GridSearchCV 
>>> from sklearn.datasets import load_iris 
>>> 
>>> class Fisher(BaseEstimator, TransformerMixin): 
...  def __init__(self,percentile=0.95): 
...    self.percentile = percentile 
...  def fit(self, X, y): 
...    from numpy import shape, argsort, ceil 
...    X_pos, X_neg = X[y==1], X[y==0] 
...    X_mean = X.mean(axis=0) 
...    X_pos_mean, X_neg_mean = X_pos.mean(axis=0), X_neg.mean(axis=0) 
...    deno = (1.0/(shape(X_pos)[0]-1))*X_pos.var(axis=0) + (1.0/(shape(X_neg)[0]-1))*X_neg.var(axis=0) 
...    num = (X_pos_mean - X_mean)**2 + (X_neg_mean - X_mean)**2 
...    F = num/deno 
...    sort_F = argsort(F)[::-1] 
...    n_feature = (float(self.percentile)/100)*shape(X)[1] 
...    self.ind_feature = sort_F[:ceil(n_feature)] 
...    return self 
...  def transform(self, x): 
...    return x[self.ind_feature,:] 
... 
>>> 
>>> data = load_iris() 
>>> 
>>> pipeline = Pipeline([ 
...  ('fisher', Fisher()), 
...  ('normal',StandardScaler()), 
...  ('svm',SVC(class_weight='auto')) 
... ]) 
>>> 
>>> grid = { 
...  'fisher__percentile':[0.75,0.50], 
...  'svm__C':[1,2] 
... } 
>>> 
>>> model = GridSearchCV(estimator = pipeline, param_grid=grid, cv=2) 
>>> model.fit(data.data,data.target) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/Users/dmcgarry/anaconda/lib/python2.7/site-packages/sklearn/grid_search.py", line 596, in fit 
    return self._fit(X, y, ParameterGrid(self.param_grid)) 
    File "/Users/dmcgarry/anaconda/lib/python2.7/site-packages/sklearn/grid_search.py", line 378, in _fit 
    for parameters in parameter_iterable 
    File "/Users/dmcgarry/anaconda/lib/python2.7/site-packages/sklearn/externals/joblib/parallel.py", line 653, in __call__ 
    self.dispatch(function, args, kwargs) 
    File "/Users/dmcgarry/anaconda/lib/python2.7/site-packages/sklearn/externals/joblib/parallel.py", line 400, in dispatch 
    job = ImmediateApply(func, args, kwargs) 
    File "/Users/dmcgarry/anaconda/lib/python2.7/site-packages/sklearn/externals/joblib/parallel.py", line 138, in __init__ 
    self.results = func(*args, **kwargs) 
    File "/Users/dmcgarry/anaconda/lib/python2.7/site-packages/sklearn/cross_validation.py", line 1239, in _fit_and_score 
    estimator.fit(X_train, y_train, **fit_params) 
    File "/Users/dmcgarry/anaconda/lib/python2.7/site-packages/sklearn/pipeline.py", line 130, in fit 
    self.steps[-1][-1].fit(Xt, y, **fit_params) 
    File "/Users/dmcgarry/anaconda/lib/python2.7/site-packages/sklearn/svm/base.py", line 149, in fit 
    (X.shape[0], y.shape[0])) 
ValueError: X and y have incompatible shapes. 
X has 1 samples, but y has 75. 
+0

Спасибо, я включил обе функции в ОП. – Francis

+0

См. Редактирование, извините за прыжок с пистолета, но я не думаю, что это возможно, так как ваши функции должны применяться к вашей цели. – David

+0

Извините за поздний ответ. Мне интересно, что вы имели в виду под «процессом Фишера, который работал бы, если бы сама функция не влияла на вашу целевую переменную». Счет Фишера здесь принимает цели (т. Е. Y) в качестве входных данных и преобразует x в качестве вывода, что мне кажется, что оно не преобразует y. – Francis

Смежные вопросы