我正在尝试使用LogisticRegressionCV
将Logistic回归模型拟合到简单的1D数据集。非常奇怪的是,当给出选择时,似乎选择了一个很小的C
值,这迫使我的模型选择了一个很小的theta,从而导致了一个无用的模型。
我尝试查看模型提供的scores_
,但它们没有任何意义。例如,当我告诉它使用5个C
值选择进行三重交叉验证时,它会给我:
{1: array([
[0.47058824, 0.47058824, 0.47058824, 0.47058824, 0.47058824],
[1. , 1. , 1. , 1. , 1. ],
[0.63636364, 0.63636364, 0.63636364, 0.63636364, 0.63636364]])}
数据集不是线性可分离的,但是无论我给它尝试了哪个C
值,它都声称获得了100%的精度。
下面的示例代码:
import numpy as np
from sklearn.linear_model import LogisticRegressionCV
from sklearn.linear_model import LogisticRegression
def gen_y(x):
p1 = np.clip(x + 0.5, 0, 1)
v = np.random.uniform(0, 1)
if v < p1:
return 1
return 0
np.random.seed(6)
x_data = np.sort(np.random.normal(0, 0.3, 100))
y_data = np.array([gen_y(x) for x in x_data])
regularized_logistic_regression_model = LogisticRegressionCV(
Cs = np.array([10**-8, 10**-4, 1, 10**4, 10**8]), fit_intercept = False, cv = 3)
regularized_logistic_regression_model.fit(x_data.reshape(-1, 1), y_data)
print(regularized_logistic_regression_model.C_) # yields 10^-8
print(regularized_logistic_regression_model.coef_) # yields incredibly tiny value
print(regularized_logistic_regression_model.scores_) # yields nonsensical scores
两个基本错误:
另外:相当小的数据集。
截距大大提高了逻辑回归的表达能力,尤其是在只有一个特征的问题中,例如此处。其default setting为True
是有原因的-除非您确切地知道自己在做什么,否则最好不要与它们混合使用。像这样在简单的单变量情况下省略截距很容易理解:它迫使回归线穿过原点(0,0)-huge约束。
在这种人工数据集的情况下,混洗尤其重要,因为在某些情况下,这些值会被排序(如此处所述)。原因是,虽然ML模型可以很好地进行插值,但是它们是extremely bad at extrapolating(预测值超出其训练范围);并使用排序的数据,您的每个验证CV折叠都会尝试使用相应训练折叠之外的数据进行预测(毫无疑问,它做得不好)。
因此,只需对数据进行混排,并使用这些数据和`fit_intercept = True,我们得到:
from sklearn.utils import shuffle
x_s, y_s = shuffle(x_data, y_data, random_state=0)
regularized_logistic_regression_model = LogisticRegressionCV(
Cs = np.array([10**-8, 10**-4, 1, 10**4, 10**8]), fit_intercept = True, cv = 3)
regularized_logistic_regression_model.fit(x_s.reshape(-1, 1), y_s)
print(regularized_logistic_regression_model.C_)
print(regularized_logistic_regression_model.coef_)
print(regularized_logistic_regression_model.scores_)
结果:
[10000.]
[[4.57770177]]
{1: array([[0.61764706, 0.61764706, 0.70588235, 0.67647059, 0.67647059],
[0.60606061, 0.60606061, 0.78787879, 0.84848485, 0.84848485],
[0.60606061, 0.60606061, 0.57575758, 0.72727273, 0.72727273]])}
比您所报告的要明智得多。
添加更多数据(300个样本,而不是100个样本,得到)
[1.]
[[3.57243675]]
{1: array([[0.52, 0.52, 0.72, 0.72, 0.72],
[0.52, 0.52, 0.68, 0.67, 0.67],
[0.51, 0.51, 0.67, 0.66, 0.66]])}
最后一点:尽管通常强烈建议进行混洗,但在这里(根据定义,是人工随机数据),如果您将初始数据保持原样(即不对它们进行排序),则可以避免使用它:
x_data = np.random.normal(0, 0.3, 100) # no sorting
我将保留对此的验证作为练习。