Кръстосаното валидиране е широко използвана техника в машинното обучение за оценка на производителността на модел и избор на хиперпараметри. Това включва разделяне на наличните данни на няколко гънки, обучение на модела върху някои от гънките и оценката му върху останалите гънки. Този процес се повтаря многократно, като се използват различни комбинации от гънки за обучение и оценка, за да се получи стабилна оценка на производителността на модела.

В този урок ще разгледаме основите на използването на кръстосано валидиране в Python, включително как да го внедрим ръчно и как да използваме вградените функции за кръстосано валидиране на scikit-learn. Ще обсъдим също различни стратегии за кръстосано валидиране и как да използваме кръстосано валидиране за избор на модел и настройка на хиперпараметър.

Внедряване на кръстосано валидиране ръчно

За да приложите ръчно кръстосано валидиране в Python, можете да използвате класа model_selection.KFold от scikit-learn. Този клас предоставя итератор, който дава обучаващи/тестови разделяния на данните за даден брой сгъвания.

Ето пример за използване на KFold за извършване на k-кратно кръстосано валидиране на набор от данни за класификация:

import numpy as np
from sklearn.model_selection import KFold
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_breast_cancer

# Load the breast cancer dataset from scikit-learn
data = load_breast_cancer()
X = data['data']
y = data['target']

# Define the model
model = LogisticRegression()

# Define the cross-validation iterator
kfold = KFold(n_splits=5, shuffle=True, random_state=42)

# Initialize an array to store the evaluation scores
scores = []

# Loop over the folds
for train_index, test_index in kfold.split(X):
    # Get the training and test data for this fold
    X_train, X_test = X[train_index], X[test_index]
    y_train, y_test = y[train_index], y[test_index]

    # Fit the model to the training data and evaluate on the test data
    model.fit(X_train, y_train)
    score = model.score(X_test, y_test)
    scores.append(score)

# Print the mean and standard deviation of the evaluation scores
print(f'Mean score: {np.mean(scores):.2f}')
print(f'Standard deviation: {np.std(scores):.2f}')

Този код зарежда набора от данни за рак на гърдата от scikit-learn, дефинира модел на логистична регресия и след това дефинира итератор за 5-кратно кръстосано валидиране, използвайки KFold. След това кодът преминава през гънките, като използва данните за обучение, за да пасне на модела, и данните от теста, за да оцени модела. Резултатите за оценка се съхраняват в масив и след това средната стойност и стандартното отклонение се отпечатват на конзолата.

Използване на функциите за кръстосано валидиране на scikit-learn

Scikit-learn предоставя редица удобни функции за извършване на кръстосано валидиране, което може да бъде по-ефективно и по-лесно за използване, отколкото ръчното им прилагане. Тези функции включват:

  • model_selection.cross_val_score: Тази функция извършва к-кратно кръстосано валидиране на модел и връща оценките за оценка за всяко сгъване.
import numpy as np
from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_breast_cancer

# Load the breast cancer dataset from scikit-learn
data = load_breast_cancer()
X = data['data']
y = data['target']

# Define the model
model = LogisticRegression()

# Perform k-fold cross-validation
scores = cross_val_score(model, X, y, cv=5)

# Print the mean and standard deviation of the evaluation scores
print(f'Mean score: {np.mean(scores):.2f}')
print(f'Standard deviation: {np.std(scores):.2f}')

Този код е еквивалентен на предишния пример, но използва cross_val_score за извършване на k-кратно кръстосано валидиране и връща директно оценките за оценка.

  • model_selection.cross_val_predict: Тази функция извършва k-кратно кръстосано валидиране и връща предвидените етикети за всяка проба.
import numpy as np
from sklearn.model_selection import cross_val_predict
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_breast_cancer

# Load the breast cancer dataset from scikit-learn
data = load_breast_cancer()
X = data['data']
y = data['target']

# Define the model
model = LogisticRegression()

# Perform k-fold cross-validation and get the predicted labels for each sample
predictions = cross_val_predict(model, X, y, cv=5)

# Print the mean and standard deviation of the predicted labels
print(f'Mean prediction: {np.mean(predictions):.2f}')
print(f'Standard deviation: {np.std(predictions):.2f}')

Този код е подобен на предишния пример, но използва cross_val_predict, за да получи предвидените етикети за всяка проба вместо оценките за оценка.

  • model_selection.GridSearchCV: Тази функция извършва изчерпателно търсене върху определена решетка с хиперпараметри, използвайки k-кратно кръстосано валидиране. Той връща най-добрите хиперпараметри въз основа на производителността на модела върху данните за валидиране.
import numpy as np
from sklearn.model_selection import GridSearchCV
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_breast_cancer

# Load the breast cancer dataset from scikit-learn
data = load_breast_cancer()
X = data['data']
y = data['target']

# Define the model and the hyperparameter grid
model = LogisticRegression()
param_grid = {'C': [0.1, 1, 10, 100]}

# Use grid search with k-fold cross-validation to tune the hyperparameters
grid_search = GridSearchCV(model, param_grid, cv=5)
grid_search.fit(X, y)

Избор на броя на гънките

Броят на сгъванията в k-кратното кръстосано валидиране е важен хиперпараметър, който може да повлияе на производителността на модела и надеждността на оценките за оценка. По-големият брой сгъвания ще осигури по-точна оценка на производителността на модела, но също така ще бъде по-бавно за изчисляване.

Често срещан избор е да използвате 5 или 10 сгъвания, които постигат добър баланс между точност и скорост.

Възможно е също така да се използва стратифицирано k-кратно кръстосано валидиране, което гарантира, че пропорциите на различните класове в гънките са същите като в оригиналния набор от данни. Това може да бъде полезно за небалансирани набори от данни, където един клас е много по-често срещан от останалите.

Различни стратегии за кръстосано валидиране

В допълнение към k-кратното кръстосано валидиране, има няколко други стратегии за кръстосано валидиране, които могат да бъдат полезни в различни ситуации.

  • Кръстосано валидиране с изключване с един навън (LOOCV): Това е специален случай на кръстосано валидиране с k-кратно, където k е равно на размера на набора за обучение. Това означава, че една извадка се използва като набор за валидиране, докато останалите данни се използват за обучение. LOOCV може да бъде много точен, но също така е много бавен за изчисляване, особено за големи масиви от данни.
  • Стратифицирано кръстосано валидиране на k-кратно: Както бе споменато по-рано, това е вариант на кръстосано валидиране на k-кратно, който гарантира, че пропорциите на различните класове в гънките са същите като в оригиналния набор от данни. Това може да бъде полезно за небалансирани набори от данни, където един клас е много по-често срещан от останалите.
  • Кръстосано валидиране с разбъркано разделяне: Това е вариант на кръстосано валидиране с k-кратно, при което данните се разбъркват, преди да бъдат разделени на гънки. Това може да бъде полезно, ако данните имат някакъв вид подреждане или ако редът на извадките е важен.
  • Кръстосано валидиране на времеви серии: Това е вариант на k-кратно кръстосано валидиране, който е специално проектиран за данни от времеви редове. Това включва разделяне на данните на фиксиран брой гънки, но разделянето се извършва на базата на време, а не на случаен принцип. Това може да бъде полезно, ако данните имат времеви зависимости, които трябва да бъдат запазени в гънките.

Използване на кръстосано валидиране за избор на модел и настройка на хиперпараметър

Едно от основните приложения на кръстосаното валидиране е за избор на модел и настройка на хиперпараметър. Чрез използване на кръстосано валидиране можете да оцените ефективността на различни модели и различни комбинации от хиперпараметри върху едни и същи данни и да изберете модела и хиперпараметрите, които се представят най-добре.

За да използвате кръстосано валидиране за избор на модел и настройка на хиперпараметър, можете да използвате функцията GridSearchCV на scikit-learn. Тази функция извършва изчерпателно търсене върху определена решетка с хиперпараметри, използвайки k-кратно кръстосано валидиране, и връща най-добрите хиперпараметри въз основа на производителността на модела върху данните за валидиране.

Ето пример за използване на GridSearchCV за настройка на хиперпараметрите на логистичен регресионен модел:

import numpy as np
from sklearn.model_selection import GridSearchCV
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_breast_cancer

# Load the breast cancer dataset from scikit-learn
data = load_breast_cancer()
X = data['data']
y = data['target']

# Define the model and the hyperparameter grid
model = LogisticRegression()
param_grid = {'C': [0.1, 1, 10, 100], 'penalty': ['l1', 'l2']}

# Use grid search with k-fold cross-validation to tune the hyperparameters
grid_search = GridSearchCV(model, param_grid, cv=5)
grid_search.fit(X, y)

# Print the best hyperparameters
print(f'Best hyperparameters: {grid_search.best_params_}')

# Print the mean and standard deviation of the evaluation scores for the best model
scores = grid_search.cv_results_['mean_test_score']
stds = grid_search.cv_results_['std_test_score']
for mean, std, params in zip(scores, stds, grid_search.cv_results_['params']):
  print(f'{mean:.3f} (+/-{std * 2:.3f}) for {params}')

Този код дефинира логистичен регресионен модел и мрежа от хиперпараметри за търсене. След това използва `GridSearchCV`, за да извърши изчерпателно търсене в мрежата с хиперпараметри, използвайки k-кратно кръстосано валидиране. След това се отпечатват най-добрите хиперпараметри, заедно със средната стойност и стандартното отклонение на оценките за най-добрия модел.

Заключение

В този урок разгледахме основите на използването на кръстосано валидиране в машинно обучение с помощта на Python. Разгледахме как да приложим ръчно кръстосано валидиране и как да използваме вградените функции за кръстосано валидиране на scikit-learn. Обсъдихме също различни стратегии за кръстосано валидиране и как да използваме кръстосано валидиране за избор на модел и настройка на хиперпараметри.

Надявам се, че този урок е предоставил добро въведение в използването на кръстосано валидиране в машинното обучение.