Помогите посчитать значение q2 для Leave-One-Out перекрестной проверки линейной регрессии?
Имеется вот такой код:
import pandas as pd
import numpy as np
import seaborn as sns
%matplotlib inline
import matplotlib.pyplot as plt
Porphs_data = pd.read_excel('I:\\Porphyrins\\26_4-Descs_varI_22-3-20.xlsx', index_col=0)
y = Porphs_data.LogFi
X = Porphs_data.drop(['LogFi'], axis=1)
# Select upper triangle of correlation matrix
upper = corr_matrix.where(np.triu(np.ones(corr_matrix.shape), k=1).astype(np.bool))
# Find index of feature columns with correlation greater than 0.95
to_drop = [column for column in upper.columns if any(upper[column] > 0.95)]
# Drop features
X = X.drop(Porphs_data[to_drop], axis=1)
X_train = X.drop(["(p-Br)4-TPP", "5,10-NO2-etioporphyrin I", "Deuteroporphyrin-IX-DME",
"N-CH3-Octaethylporphyrin", "Porphine"], axis=0)
y_train = y.drop(["(p-Br)4-TPP", "5,10-NO2-etioporphyrin I", "Deuteroporphyrin-IX-DME",
"N-CH3-Octaethylporphyrin", "Porphine"], axis=0)
X_test = X.loc[["(p-Br)4-TPP", "5,15-NO2-etioporphyrin I", "Deuteroporphyrin-IX-DME",
"N-CH3-Octaethylporphyrin", "Porphine"]]
y_test = y.loc[["(p-Br)4-TPP", "5,10-NO2-etioporphyrin I", "Deuteroporphyrin-IX-DME",
"N-CH3-Octaethylporphyrin", "Porphine"]]
from sklearn import linear_model
lm = linear_model.LinearRegression()
lm.fit(X_train, y_train)
Получаем коэффициент детерминации:
from sklearn.metrics import r2_score
y_pred = lm.predict(X_train)
r2_score(y_train, y_pred)
Пытаюсь получить значение q2 для leave-one-out перекрестной проверки:
from sklearn.model_selection import LeaveOneOut
from sklearn.linear_model import LinearRegression
loo_lm = LinearRegression(lm, LeaveOneOut())
loo_lm.fit(X_train, y_train)
loo_lm.score(X_train, y_train)
Но получаю такое же значение как и для коэффициента детерминации для тренировочной выборки.
Другой способ посчитать q2:
from sklearn.model_selection import cross_val_score
cvs=cross_val_score(lm, X_train, y_train, cv=21)
cvs
mean_cross_val_score = cvs.mean()
mean_cross_val_score
выдает ошибку: UndefinedMetricWarning: R^2 score is not well-defined with less than two samples.
Пожалуйста, помогите посчитать q2 для leave-one-out перекрестной проверки!
PS Примеры X и y. Вот X:
Eig02_EA(dm) MATS1e HOMO-LUMO_Gap SpMax4_Bh(p) SAdon
compound
(m-Cl)4-TPP 0.00 -0.040 2.74 3.86 33.6
(o-Cl)4-TPP 0.00 -0.040 2.80 3.86 33.6
(o-F)4-TPP 0.00 -0.026 2.75 3.84 33.6
(p-Cl)4-TPP 0.00 -0.040 2.69 3.86 33.6
Вот y:
compound
(m-Cl)4-TPP 1.908485
(o-Cl)4-TPP 1.924279
(o-F)4-TPP 1.851258
(p-Cl)4-TPP 1.851258
Ответы (3 шт):
Воспользовавшись советами MaxU и CrazyElf, собрал вот такой код:
from sklearn.model_selection import LeaveOneOut
score_list = []
loo = LeaveOneOut()
skipped = 0
for train_index, test_index in loo.split(X):
X_train, X_test = X.iloc[train_index], X.iloc[test_index]
y_train, y_test = y.values[train_index], y.values[test_index]
lm.fit(X_train, y_train)
y_lm = lm.predict(X_test)
skipped += 1
continue
score = score(np.array(y_test)[y_lm], np.array(y_lm)[y_lm])
score_list.append(score)
print(np.mean(score_list))
Однако выдает ошибку
skipped += 1
^
IndentationError: unexpected indent"```
Попробуйте сделать примерно так:
from sklearn.model_selection import LeaveOneOut
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import cross_val_score
lr = LinearRegression()
loo = LeaveOneOut()
cvs=cross_val_score(lr, X_train, y_train, cv=loo)
print(cvs)
print(cvs.mean())
А что касается ошибки
UndefinedMetricWarning: R^2 score is not well-defined with less than two samples.
Вы понимаете, как работает LeaveOneOut в качестве кросс-валидации? Он по очереди откладывает из выборки один сэмпл, тренирует модель на остальной части выборки и потом считает score на этом отложенном сэмпле. При этом метрика sklearn.metrics.r2_score, которая видимо используется в данном случае для вычисления score, считает, что по одному сэмплу её нельзя вычислять. Так что вам надо определиться - либо метод кросс-валидации неправильный, либо метод вычисления score. Они между собой несовместимы.
В итоге на researchgate мне посоветовали вот такой код:
from sklearn import linear_model
from sklearn.model_selection import cross_val_predict
from sklearn.metrics import r2_score as r2
# Assuming you have X_train and y_train in a correct form
lm = linear_model.LinearRegression()
y_pred = cross_val_predict(lm, X_train, y_train, cv=len(X_train))
r2_score = r2(y_pred,y_train)
r2_score
Не знаю, правильно ли это. Но вроде работает.