gpt4 book ai didi

python - 使用 Iris 数据集在 Python 中重现 LASSO/Logistic 回归结果

转载 作者:太空狗 更新时间:2023-10-30 00:59:14 24 4
gpt4 key购买 nike

我正在尝试在 Python 中重现以下 R 结果。在这种特殊情况下,R 预测技能低于 Python 技能,但根据我的经验通常情况并非如此(因此我想在 Python 中重现结果),因此请忽略此处的细节。

目的是预测花的种类('versicolor' 0 或 'virginica' 1)。我们有 100 个标记样本,每个样本包含 4 个花特征:萼片长度、萼片宽度、花瓣长度、花瓣宽度。我将数据分成训练集(60% 的数据)和测试集(40% 的数据)。对训练集应用 10 折交叉验证来搜索最优的 lambda(优化的参数是 scikit-learn 中的“C”)。

我正在使用 glmnet在 R 中,alpha 设置为 1(用于 LASSO 惩罚),对于 python,scikit-learn 的 LogisticRegressionCV函数与“liblinear”求解器(唯一可以与 L1 惩罚一起使用的求解器)。交叉验证中使用的评分指标在两种语言之间是相同的。然而,模型结果不知何故不同(每个特征的截距和系数差异很大)。

R 代码

library(glmnet)
library(datasets)
data(iris)

y <- as.numeric(iris[,5])
X <- iris[y!=1, 1:4]
y <- y[y!=1]-2

n_sample = NROW(X)

w = .6
X_train = X[0:(w * n_sample),] # (60, 4)
y_train = y[0:(w * n_sample)] # (60,)
X_test = X[((w * n_sample)+1):n_sample,] # (40, 4)
y_test = y[((w * n_sample)+1):n_sample] # (40,)

# set alpha=1 for LASSO and alpha=0 for ridge regression
# use class for logistic regression
set.seed(0)
model_lambda <- cv.glmnet(as.matrix(X_train), as.factor(y_train),
nfolds = 10, alpha=1, family="binomial", type.measure="class")

best_s <- model_lambda$lambda.1se
pred <- as.numeric(predict(model_lambda, newx=as.matrix(X_test), type="class" , s=best_s))

# best lambda
print(best_s)
# 0.04136537

# fraction correct
print(sum(y_test==pred)/NROW(pred))
# 0.75

# model coefficients
print(coef(model_lambda, s=best_s))
#(Intercept) -14.680479
#Sepal.Length 0
#Sepal.Width 0
#Petal.Length 1.181747
#Petal.Width 4.592025

Python 代码

from sklearn import datasets
from sklearn.linear_model import LogisticRegressionCV
from sklearn.preprocessing import StandardScaler
import numpy as np

iris = datasets.load_iris()
X = iris.data
y = iris.target
X = X[y != 0] # four features. Disregard one of the 3 species.
y = y[y != 0]-1 # two species: 'versicolor' (0), 'virginica' (1). Disregard one of the 3 species.

n_sample = len(X)

w = .6
X_train = X[:int(w * n_sample)] # (60, 4)
y_train = y[:int(w * n_sample)] # (60,)
X_test = X[int(w * n_sample):] # (40, 4)
y_test = y[int(w * n_sample):] # (40,)

X_train_fit = StandardScaler().fit(X_train)
X_train_transformed = X_train_fit.transform(X_train)

clf = LogisticRegressionCV(n_jobs=2, penalty='l1', solver='liblinear', cv=10, scoring = ‘accuracy’, random_state=0)
clf.fit(X_train_transformed, y_train)

print clf.score(X_train_fit.transform(X_test), y_test) # score is 0.775
print clf.intercept_ #-1.83569557
print clf.coef_ # [ 0, 0, 0.65930981, 1.17808155] (sepal length, sepal width, petal length, petal width)
print clf.C_ # optimal lambda: 0.35938137

最佳答案

上面的例子有几点不同:

  1. 系数的尺度

    • glmnet ( https://cran.r-project.org/web/packages/glmnet/glmnet.pdf ) 对数据进行标准化,“系数始终按原始比例返回”。因此,您在调用 glmnet 之前没有缩放数据。
    • Python 代码将数据标准化,然后适合该标准化数据。本例中的系数采用标准化比例,而不是原始比例。这使得示例之间的系数不可比较。
  2. LogisticRegressionCV 默认使用 stratifiedfolds。 glmnet 使用 k-fold。

  3. 他们正在拟合不同的方程。请注意,scikit-learn 逻辑适合 ( http://scikit-learn.org/stable/modules/linear_model.html#logistic-regression ) 与逻辑方面的正则化。 glmnet 对惩罚进行正则化。

  4. 选择要尝试的正则化强度 - glmnet 默认为要尝试的 100 个 lambda。 scikit LogisticRegressionCV 默认为 10。由于 scikit 求解的方程,范围在 1e-4 和 1e4 ( http://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegressionCV.html#sklearn.linear_model.LogisticRegressionCV ) 之间。

  5. 容忍度不同。在我遇到的一些问题中,收紧公差会显着改变系数。

    • glmnet 默认 thresh 为 1e-7
    • LogisticRegressionCV 默认 tol 为 1e-4
    • 即使使它们相同,它们也可能测量的不是同一件事。我不知道 liblinear 措施是什么。 glmnet - “每个内部坐标下降循环都会继续,直到任何系数更新后目标的最大变化小于零偏差的阈值。”

您可能想尝试打印正则化路径以查看它们是否非常相似,只是停在不同的强度上。然后你可以研究原因。

即使更改了您可以更改的内容(并非以上所有内容),您也可能无法获得相同的系数或结果。尽管您在不同的软件中解决相同的问题,但软件解决问题的方式可能会有所不同。我们看到不同的尺度、不同的方程、不同的默认值、不同的求解器等。

关于python - 使用 Iris 数据集在 Python 中重现 LASSO/Logistic 回归结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43581850/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com