Повышаем устойчивость кросс-валидации через сид
Случайными кажутся события, причины которых мы не знаем (Демокрит).
При кросс-валидационной проверке качества модели установка ее случайного инициализатора в целочисленное значение может понизить вариацию в данных. В этом случае на всех сплитах тестируется качество только одной случайной вариации алгоритма. Если же передать объект класса np.random.RandomState, то на каждом fit-е алгоритм будет подбирать разные случайные параметры.
from sklearn.datasets import make_classification
from sklearn.ensemble import RandomForestClassifier
import numpy as np
SEED = 0
RNG = np.random.RandomState(SEED)
X, y = make_classification(n_samples=10000, n_features=5, n_informative=2,
n_redundant=0, class_sep = 2, random_state=SEED, shuffle=True,
flip_y=0.3, n_clusters_per_class=2)
part = int(X.shape[0]*0.8)
model = RandomForestClassifier(random_state=SEED)
display(model.fit(X[:part], y[:part]).predict(X[part:]).sum())
display(model.fit(X[:part], y[:part]).predict(X[part:]).sum())Целочисленный сид создает одинаковые модели и получает равные результаты. Для демонстрационных целей выше выведена сумма предсказаний.
А ниже то же с использованием RNG:
model = RandomForestClassifier(random_state=RNG) display(model.fit(X[:part], y[:part]).predict(X[part:]).sum()) display(model.fit(X[:part], y[:part]).predict(X[part:]).sum())
Такое поведение обусловлено тем, что после первого вызова fit RNG изменяется. Соответственно, так как при кросс-валидационной оценке на каждом fit-е получается немного иная вариация нашего оценщика, итоговое качество будет статистически устойчивее и меньше зависимо от случайных величин.
С учетом этого, результаты кросс-валидации при задании random_state=RNG и целым - random_state=SEED будут отличаться:
from sklearn.model_selection import cross_val_score display(cross_val_score(RandomForestClassifier(random_state=RNG), X, y)) display(cross_val_score(RandomForestClassifier(random_state=SEED), X, y))
Таким образом, чтобы повысить статистическую достоверность кросс-валидации, используйте вместо целочисленного сида объект np.random.RandomState.