我想知道是否可以通过接受输入数据切割的调用来运行分类器(例如RandomForestClassifier,GradientBoostingClassifier)。
为使问题更清楚,我们要运行
gbcl = GradientBoostingClassifier(n_estimators=100,
learning_rate=1.0,
max_depth=5,
random_state=1).fit(X_train, y_train)
但仅使用X_train[:,3] > 0
的事件。
除了创建新的输入数组之外,还有其他方法吗?
答案 0 :(得分:2)
在scikit-learn的上下文中,您必须创建一个新数据,例如X_train_new = X_train[X_train[:,3] > 0]
,y_train_new = y_train[X_train[:,3] > 0]
,或者,如果要避免“用杂散数组填充代码”,则传递切片的数据直接使用fit方法:
model.fit(X_train[X_train[:, 3] > 0], y_train[X_train[:, 3] > 0])
或
b = (X_train[:, 3] > 0)
model.fit(X_train[b], y_train[b])
答案 1 :(得分:1)
不可能使用标准的sklearn
功能,但是您可以创建一个可以轻松完成所需操作的类(我同意它更具可读性)。
我个人会选择这样的东西:
class SlicingClassifier:
"""Create classifiers of slice data.
Parameters
----------
classifier : sklearn-compatible classifier
Classifier with sklearn-compatible interface. Needs fit method.
slices : array-like[bool] or generator
List of Boolean numpy arrays able to slice features and targets.
Can be a generator returning slices.
"""
def __init__(self, classifier, slices):
self.classifier_ = classifier
self.slices_ = slices
self.models_ = []
def fit(self, X, y):
for index_slice in self.slices_:
self.models_.append(self.classifier_.fit(X[index_slice], y[index_slice]))
return self
# You may want to make this a list, but it's more memory-efficient as gen
def predict(self, X):
for model in self.models_:
yield model.predict(X)
如果需要,您可以轻松地使用多个分类器扩展此方法,使用不同的predict
方法fit_transform
,使API与sklearn
兼容,依此类推。
如果只关心每个数据子集的预测,那么(从内存的角度来看)好的加法可以像函数fit_transform
一样生成:
def fit_transform_generator(self, X, y):
for index_slice in self.slices_:
yield self.classifier_.fit_transform(X[index_slice], y[index_slice])
示例调用将遵循这些原则,并将使您免于切片数组的丑陋临时创建。
classifier = SlicingClassifier(
GradientBoostingClassifier(
n_estimators=100, learning_rate=1.0, max_depth=5, random_state=1
),
# Go with your slices however you want, could use generator
# function as well, even better IMO
slices=[X > 0, (X ** 3) > X, X[:, 3] != 0],
)
classifier.fit(X, y)
predictions = classifier.predict(X)
那些切片不会复制数组,它们使用视图和引用,因此不需要额外的内存(对原始X
进行切片的数组除外)。
您也可以使用生成器对象,而不是像List
那样传递切片(对于许多切片索引,您应该使用此方法)。
提供示例以消除混乱:
def slices_generator(X, stop, start=0, step=1):
for i in range(start, stop, step):
yield X < i
classifier = SlicingClassifier(
GradientBoostingClassifier(
n_estimators=100, learning_rate=1.0, max_depth=5, random_state=1
),
slices=slices_generator(X, 1000),
)