alp*_*pal 5 python pandas scikit-learn
如果我排除自定义转换器,则GridSearchCV可以正常运行,但是会出错。这是一个伪数据集:
import pandas
import numpy
from sklearn_pandas import DataFrameMapper
from sklearn_pandas import cross_val_score
from sklearn.pipeline import Pipeline
from sklearn.grid_search import GridSearchCV
from sklearn.base import TransformerMixin
from sklearn.preprocessing import LabelBinarizer
from sklearn.ensemble import RandomForestClassifier
import sklearn_pandas
from sklearn.preprocessing import MinMaxScaler
df = pandas.DataFrame({"Letter":["a","b","c","d","a","b","c","d","a","b","c","d","a","b","c","d"],
"Number":[1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4],
"Label":["G","G","B","B","G","G","B","B","G","G","B","B","G","G","B","B"]})
class MyTransformer(TransformerMixin):
def transform(self, x, **transform_args):
x["Number"] = x["Number"].apply(lambda row: row*2)
return x
def fit(self, x, y=None, **fit_args):
return self
x_train = df
y_train = x_train.pop("Label")
mapper = DataFrameMapper([
("Number", MinMaxScaler()),
("Letter", LabelBinarizer()),
])
pipe = Pipeline([
("custom", MyTransformer()),
("mapper", mapper),
("classifier", RandomForestClassifier()),
])
param_grid = {"classifier__min_samples_split":[10,20], "classifier__n_estimators":[2,3,4]}
model_grid = sklearn_pandas.GridSearchCV(pipe, param_grid, verbose=2, scoring="accuracy")
model_grid.fit(x_train, y_train)
Run Code Online (Sandbox Code Playgroud)
错误是
list indices must be integers, not str
Run Code Online (Sandbox Code Playgroud)
当管道中有自定义转换器时,如何使GridSearchCV工作?
我知道这个答案来得相当晚,但我在 sklearn 和BaseSearchCV衍生类中遇到了同样的行为。这个问题实际上似乎源于_PartitionIteratorsklearn cross_validation 模块中的类,因为它假设TransformerMixin管道中每个类发出的所有内容都将类似于数组,因此它会生成用于索引传入的索引切片Xargs 以类似数组的方式。方法如下__iter__:
def __iter__(self):
ind = np.arange(self.n)
for test_index in self._iter_test_masks():
train_index = np.logical_not(test_index)
train_index = ind[train_index]
test_index = ind[test_index]
yield train_index, test_index
Run Code Online (Sandbox Code Playgroud)
网格BaseSearchCV搜索元类调用 cross_validation 的_fit_and_score,它使用名为 的方法safe_split。这是相关行:
X_subset = [X[idx] for idx in indices]
Run Code Online (Sandbox Code Playgroud)
如果 X 是您从transform函数中发出的 pandas 数据框,这绝对会产生意外的结果。
我发现有两种方法可以解决这个问题:
确保从变压器返回一个数组:
return x.as_matrix()
Run Code Online (Sandbox Code Playgroud)这是一个黑客行为。如果变压器管道要求下一个变压器的输入是 DataFrame,就像我的情况一样,您可以编写一个实用程序脚本,该脚本本质上与 sklearn 模块相同,但包含一些在以下方法grid_search中调用的巧妙验证方法_fit班上BaseSearchCV:
def _validate_X(X):
"""Returns X if X isn't a pandas frame, otherwise
the underlying matrix in the frame. """
return X if not isinstance(X, pd.DataFrame) else X.as_matrix()
def _validate_y(y):
"""Returns y if y isn't a series, otherwise the array"""
if y is None:
return y
# if it's a series
elif isinstance(y, pd.Series):
return np.array(y.tolist())
# if it's a dataframe:
elif isinstance(y, pd.DataFrame):
# check it's X dims
if y.shape[1] > 1:
raise ValueError('matrix provided as y')
return y[y.columns[0]].tolist()
# bail and let the sklearn function handle validation
return y
Run Code Online (Sandbox Code Playgroud)作为示例,这是我的“自定义 grid_search 模块”。
| 归档时间: |
|
| 查看次数: |
1036 次 |
| 最近记录: |