2015-07-10 3 views
1

Используя информацию, описанную в этом вопросе, Combining random forest models in scikit learn , я попытался объединить несколько случайных лесных классификаторов в единый классификатор с использованием python2.7.10 и sklearn 0.16.1, но получить это исключение в в некоторых случаях:Неожиданное исключение при объединении случайных лесных деревьев

Traceback (most recent call last): 
     File "sktest.py", line 50, in <module> 
     predict(rf) 
     File "sktest.py", line 46, in predict 
     Y = rf.predict(X) 
     File "/python-2.7.10/lib/python2.7/site-packages/sklearn/ensemble/forest.py", line 462, in predict 
     proba = self.predict_proba(X) 
     File "/python-2.7.10/lib/python2.7/site-packages/sklearn/ensemble/forest.py", line 520, in predict_proba 
     proba += all_proba[j] 
    ValueError: non-broadcastable output operand with shape (39,1) doesn't match the broadcast shape (39,2) 

приложения для создания ряда случайных лесных классификаторов на многих процессорах и объединить эти объекты в единый классификатор доступного для всех процессоров.

Код ошибки для создания этого исключения приведен ниже, он создает 5 классификаторов со случайным числом массивов из 10 функций. Если yfrac изменен на 0.5, код не даст исключения. Является ли это допустимым методом объединения объектов классификатора? Кроме того, это же исключение создается при использовании warm_start для добавления деревьев к существующему RandomForestClassifier, когда n_estimators увеличиваются, а данные добавляются через fit.

from sklearn.ensemble import RandomForestClassifier 
from sklearn.cross_validation import train_test_split 
from numpy import zeros,random,logical_or,where,array 

random.seed(1) 

def generate_rf(X_train, y_train, X_test, y_test, numTrees=50): 
    rf = RandomForestClassifier(n_estimators=numTrees, n_jobs=-1) 
    rf.fit(X_train, y_train) 
    print "rf score ", rf.score(X_test, y_test) 
    return rf 

def combine_rfs(rf_a, rf_b): 
    rf_a.estimators_ += rf_b.estimators_ 
    rf_a.n_estimators = len(rf_a.estimators_) 
    return rf_a 

def make_data(ndata, yfrac=0.5): 
    nx = int(random.uniform(10,100)) 

    X = zeros((nx,ndata)) 
    Y = zeros(nx) 

    for n in range(ndata): 
    rnA = random.random()*10**(random.random()*5) 
    X[:,n] = random.uniform(-rnA,rnA, nx) 
    Y = logical_or(Y,where(X[:,n] > yfrac*rnA, 1.,0.)) 

    return X, Y 

def train(ntrain=5, ndata=10, test_frac=0.2, yfrac=0.5): 
    rfs = [] 
    for u in range(ntrain): 
    X, Y = make_data(ndata, yfrac=yfrac) 

    X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=test_frac) 

    #Train the random forest and add to list 
    rfs.append(generate_rf(X_train, Y_train, X_test, Y_test)) 

    # Combine the block classifiers into a single classifier 
    return reduce(combine_rfs, rfs) 

def predict(rf, ndata=10): 
    X, Y = make_data(ndata) 
    Y = rf.predict(X) 

if __name__ == "__main__": 
    rf = train(yfrac = 0.42) 
    predict(rf) 

ответ

2

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

def train(ntrain=5, ndata=10, test_frac=0.2, yfrac=0.5): 
    rfs = [] 
    for u in range(ntrain): 
    X, Y = make_data(ndata, yfrac=yfrac) 

    X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=test_frac) 

    assert Y_train.sum() != 0 
    assert Y_train.sum() != len(Y_train) 
    #Train the random forest and add to list 
    rfs.append(generate_rf(X_train, Y_train, X_test, Y_test)) 

    # Combine the block classifiers into a single classifier 
    return reduce(combine_rfs, rfs) 

Используйте генератор StratifiedShuffleSplit кросс-проверки, а не train_test_split, и проверить, чтобы убедиться, что каждый получает RF оба (все) классов в обучающем наборе.

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