Scikit-learn 逻辑 回归 类库 使用 小结 - 刘建平 Pinard - 博客 园

之前 在 逻辑 回归 原理 小结 这篇 文章 中, 对 逻辑 回归 的 原理 做 了 小结. 这里 接着 对 scikit-learn 中 逻辑 回归 类库 的 我 的 使用 经验 做 一个 总结. 重点 讲述 调 参 中 要 注意 的 事项.

在 scikit-learn 中, 与 逻辑 回归 的 的 主要 是 这 3 个 类. LogisticRegression, LogisticRegressionCV 和 logistic_regression_path. Log中 LogisticRegression 和 LogisticRegressionCV 的 主要 区别 是 LogisticRegressionCV 使用 了 交叉 验证 来 正 则 则 C. 而 LogisticRegression 需要 自己 每次除了 一个 正 则 化 系数. 除了 交叉 验证, 以及 选择 正 则 化 系数 C 以外, LogisticRegression 和 LogisticRegressionCV 的 使用 方法 基本 相同.

logistic_regression_path 类 则 比较 特殊, 它 拟合 数据 后, 不能 直接 来做 预测, 只能 为 拟合 数据 选择 合适 逻辑 回归 的 系数 和 正 则 化 系数. 主要 是 用 在 模型 选择 的 时候. 一般 情况 用 不到 这个类, 所以 后面 不再 讲述 logistic_regression_path 类.

此外, scikit-learn 里面 有 个 容易 让人 误解 的 类 RandomizedLogisticRegression, 虽然 名字 里 有 逻辑 回归 的 词, 但是 主要 是 用 L1 正 则 化 的 逻辑 回归 来做 特征 选择 的, 属于 维度 规约 的 算法 类, 不 属于我们 常 说 的 分类 算法 的 范畴.

后面 的 讲解 主要 围绕 regressione logistica 和 LogisticRegressionCV 中 的 重要 参数 的 选择 来 来 展开, 这些 参数 的 意义 在 这 两个 类 中 都是 一样 的.

Regressione logistica 和 LogisticRegressionCV 默认 就 带 了 正 则 化 项 .penalty 参数 可选择 的 值为 "l1" 和 "L2". 分别 对应 L1 的 正 则 化 和 L2 的 正 则 化, 默认 是 L2 的 正 则 化.

在 调 参 时 如果 我们 主要 的 目的 只是 为了 解决 过 拟合, 一般 pena 选择 L2 正 则 化 就够 了. 但是 如果 选择 L2 正 则 化 发现 还是 过 拟合, 即 预测 效果 差 的 时候, 就 可以 考虑 L1 正 则化. 另外, 如果 模型 的 特征 非常 多, 我们 希望 一些 不重要 的 特征 系数 归零, 从而 让 模型 系数 稀疏 化 的 话, 也 可以 使用 L1 正 则 化.

pena 参数 的 选择 会 影响 我们 损失 函数 优化 的 的. 即 参数 solver 的 选择, 如果 是 L2 正 则 化, 那么 4 种 可选 的 算法 {'newton-cg', 'lbfgs', 'liblinear','sag'} 都 可以 选择. 但是 如果 penalità 是 L1 正 则 化 的 话, 就 只能 选择 'liblinear' 了. 这 是 因为 L1 正 则 化 的 损失 不是 连续 可 的 的, 而 {'newton-cg', ' LBFGS', 'sag'} 这 三种 优化 算法 时 都 需要 损失 函数 的 一 阶 或者 二阶 连续 导 数. 而 'liblinear' 并 没有 这个 依赖.

具体使用了这4个算法有什么不同以及有什么影响我们下一节讲。

risolutore 参数 决定 了 我们 对 逻辑 回归 损失 函数 的 优化 方法, 有 4 种 算法 可以 选择, 分别 是:

a) liblinear: 使用 了 开源 的 liblinear 库 实现, 内部 使用 了 坐标 轴 下降 法 来 迭代 优化 函数 函数.

b) lbfgs: 拟 牛顿 法 的 一种, 利用 损失 函数 二阶 导 数 矩阵 即 海森 矩阵 来 迭代 优化 函数 函数.

c) newton-cg: 也是 牛顿 法 家族 的 一种, 利用 损失 函数 二阶 导 数 矩阵 即 海森 矩阵 来 迭代 优化 函数 函数.

d) sag: 即 随机 平均 梯度 下降, 是 梯度 下降 法 的 变种, 和 普通 梯度 的 的 的 的 是 每次 仅仅 仅仅 的 的 的 样本 适合 适合, 适合 于 样本 数据 的 的 时候.

New 上面 的 描述 可以 看出, newton-cg, lbfgs 和 sag 这 三种 优化 时 时 时 的 的 的 的 的 阶 二阶 因此, 因此 不能 用于 没有 连续 的 的 L1 正 则 化, 只能 用于L2 正 则 化. 而 liblinear 通吃 L1 正 则 化 和 L2 正 则 化.

同时, sag 每次 仅仅 使用 了 部分 样本 进行 梯度 迭代, 所以 当 样本 量少 的 时候 不要 选择 它, 而 如果 样本 量 非常 大, 比如 大于 10 万, abbassamento 是 第一 选择. 但是 sag 不能 用于 L1 正 则化, 所以 当 你 有 大量 的 样本, 又 需要 L1 正 则 化 的 话 就要 自己 做 取舍 了. 要么 通过 对 样本 采样 来 降低 样本 量, 要么 回到 L2 正 则 化.

从 上面 的 描述, 大家 可能 觉得, 既然 newton-cg, lbfgs 和 sag 这么 多 限制, 如果 不是 大 样本, 我们 选择 liblinear 不 就 行 了 嘛! 错, 因为 liblinear 也 有 自己 的 弱点! 我们 知道, 逻辑 回归 有 二元 逻辑 回归 和 多元 逻辑 回归. 对于 多元 逻辑 回归 常见 的 有 uno-contro-riposo (SSC) 和 molti-vs-molti (MVM) 两种. 而 MVM 一般 比 Ovr 分类 相对 准确 一些. 郁闷 的 是 liblinear 只支持 OVR, 不 支持 MVM, 这样 如果 我们 需要 相对 精确 的 多元 逻辑 回归 时, 就 不能 选择 了 liblinear. 也 意味着 如果 我们 需要 相对 精确 的 多元 逻辑 回归 不能 使用 L1 正 则 化 了.

具体 OVR 和 MVM 有 什么 不同 我们 下一节 讲.

multi_class 参数 决定 了 我们 分类 的 选择, 有 ovr 和 multinomiale 两个 值 可以 选择, 默认 是 ovr.

ovr 即 前面 提到 的 uno-contro-riposo (OVR), 而 multinomiale 即 前面 提到 的 molti-vs-molti (MVM). 如果 是 二元 逻辑 回归, ovr 和 multinomiale 并 没有 任何 区别, 区别 主要 在 多元逻辑 回归 上.

OVR 的 思想 很 简单, 无论 你 是 多少 元 逻辑 回归, 我们 都 可以 看做 二元 逻辑 回归. 具体 做法 是, 对于 第 K 类 的 分类 决策, 我们 把 所有 第 K 类 的 样本 作为 正 例, 除了 第K 类 样本 以外 的 所有 样本 都 作为 负 例, 然后 在 上面 做 二元 逻辑 回归, 得到 第 K 类 的 分类 模型. 其他 类 的 分类 模型 获得 以此类推.

而 MVM 则 相对 复杂, 这里 举 MVM 的 特例 one-vs-one (OvO) 作 讲解. 如果 模型 有 T 类, 我们 每次 在 所有 的 T 类 样本 里面 选择 两类 样本 出来, 不妨 记 为 T1 类 和T2 类, 把 所有 的 输出 为 T1 T2 和 的 样本 放在 一起, 把 T1 作为 正 例, T2 作为 负 例, 进行 二元 逻辑 回归, 得到 模型 参数. 我们 一共 需要 T (T1) / 2 次分类.

从 上面 的 描述 可以 看出 OVR 相对 简单, 但 分类 效果 相对 略差 (这里 指 大多数 样本 分布 情况, 某些 样本 分布 下 OVR 可能 更好). 而 MVM 分类 相对 精确, 但是 分类 速度 没有 OVR 快.

了 选择 了 ovr, 则 4 种 损失 的 的 优化 方法 liblinear, newton-cg, lbfgs 和 sag 都 可以 选择. 但是 如果 选择 了 multinomiale, 则 只能 选择 newton-cg, lbfgs 和 sag 了.

class_weight 参数 用于 标示 分类 模型 中 各种类型 的 权 重, 可以 不 输入, 即 不 考虑 权 重, 或者 说 所有 类型 的 权 重 一样. 如果 选择 输入 的 话, 可以 选择 equilibrata 让 类库 自己 计算 类型 权 重, 或者 我们 自己输入 各个 的 的 权 重, 比如 对于 0,1 的 二元 模型, 我们 可以 定义 class_weight = {0: 0.9, 1: 0.1}, 这样 类型 0 的 权 重 为 90%, 而 类型 1 的 权 重 为 10%.

如果 class_weight 选择 equilibrata, 那么 类库 会 根据 训练 样本 量 来 计算 权 重. 某种 类型 样本 量 越 多, 则 权 重 越 低, 样本 量 越 少, 则 权 重 越高.

那么 class_weight 有 什么 作用 呢 在 分类 模型 中, 我们 经常 会 遇到 两类 问题?:

第一种是误分类的代价很高。比如对合法用户和非法用户进行分类,将非法用户分类为合法用户的代价很高,我们宁愿将合法用户分类为非法用户,这时可以人工再甄别,但是却不愿将非法用户分类为合法用户。这时,我们可以适当提高非法用户的权重。

第二种 是 样本 是 高度 失衡 的, 比如 我们 有 合法 用户 和 非法 用户 的 二元 样本 数据 10000 条, 里面 合法 用户 有 9995 条, 非法 用户 只有 5 条, 如果 我们 不 考虑 权 重, 则 我们 可以 将 所有的 测试 集 都 预测 为 合法 用户, 这样 预测 准确 率 理论上 有 99,95%, 但是 却 没有 任何 意义. 这时, 我们 可以 选择 equilibrata, 让 类库 自动 提高 非法 用户 样本 的 权 重.

提高了某种分类的权重,相比不考虑权重,会有更多的样本分类划分到高权重的类别,从而可以解决上面两类问题。

当然, 对于 第二种 样本 的 的 情况, 我们 还 可以 用 下一节 的 的 参数 sample: sample_weight, 而不 使用 class_weight.sample_weight 在 下一节 讲.

上 一 节 我们 提到 了 样本 不 失衡 的 问题, 由于 样本 不平衡, 导致 样本 不是 总体 样本 的 无 偏 估计, 从而 可能 导致 我们 的 模型 预测 能力 下降. 遇到 这种 情况, 我们 可以 通过 调节 样本 权 重 来尝试 解决 这个 问题. 调节 样本 权 重 的 方法 有 两种, 第 一种 是 在 class_weight 使用 equilibrata. 第二种 是 在 调用 forma 函数 时, 通过 sample_weight 来 自己 调节 每个 样本 权 重.

在 scikit-learn 做 逻辑 回归 时, 如果 上面 两种 方法 都 用到 了, 那么 样本 的 真正 权 重 是 class_weight * sample_weight.

就是 就是 scikit-learn 中 逻辑 回归 类库 调 的 的 一个 小结, 还 有些 参数 正 正 则 参数 C (交叉 验证 就是 Cs), 迭代 次数 max_iter 等, 由于 和 其它 的 算法 类库 并 没有 同 不同, 这里 不多 累 述 了.

(欢迎 转载, 转载 请 注明 出处. 欢迎 沟通 交流: [email protected])


Recenti documenti: