共计 1730 个字符,预计需要花费 5 分钟才能阅读完成。
背景痛点
在机器学习的实际应用中,类别不平衡问题非常常见。比如在医疗诊断中,患病样本往往远少于健康样本;在金融风控中,欺诈交易的比例通常极低。这种不平衡会导致传统逻辑回归模型倾向于预测多数类,虽然整体准确率看起来很高,但对少数类的识别能力却很差。

- 准确率陷阱:在 99% 负样本和 1% 正样本的数据中,即使模型全部预测为负样本,也能达到 99% 的准确率,但这显然没有实际价值
- AUC 指标意义:AUC(ROC 曲线下面积)能更好地评估模型在不平衡数据上的表现,因为它同时考虑了真正例率和假正例率
技术对比
传统逻辑回归使用交叉熵损失函数,目标是最大化样本被正确分类的概率。而面积逻辑回归 (AR) 则直接优化 AUC 指标,通过调整决策边界来最大化 ROC 曲线下面积。
损失函数对比
-
传统逻辑回归:
$$L = -\frac{1}{N}\sum_{i=1}^N [y_i\log(p_i) + (1-y_i)\log(1-p_i)]$$ -
面积逻辑回归:
$$L = 1 – \text{AUC} = \frac{1}{|P||N|}\sum_{i\in P}\sum_{j\in N} I(f(x_i) \leq f(x_j))$$
其中 P 是正样本集合,N 是负样本集合,$f(x)$ 是模型预测值。
代码实现
下面是用 Python 和 numpy 实现 AR 核心算法的代码:
import numpy as np
from sklearn.datasets import make_classification
# 生成不平衡数据
X, y = make_classification(n_samples=1000, n_classes=2, weights=[0.9, 0.1], random_state=42)
# Sigmoid 函数
def sigmoid(x):
return 1 / (1 + np.exp(-x))
# AR 模型实现
class AreaRegression:
def __init__(self, learning_rate=0.01, max_iter=1000):
self.lr = learning_rate
self.max_iter = max_iter
def fit(self, X, y):
n_samples, n_features = X.shape
self.w = np.zeros(n_features)
for iter in range(self.max_iter):
# 计算当前预测概率
y_pred = sigmoid(X.dot(self.w))
# 计算梯度
grad = np.zeros(n_features)
pos_indices = np.where(y == 1)[0]
neg_indices = np.where(y == 0)[0]
for i in pos_indices:
for j in neg_indices:
if y_pred[i] <= y_pred[j]:
grad += (X[j] - X[i]) * sigmoid(self.w.dot(X[j] - X[i]))
# 学习率衰减
current_lr = self.lr / (1 + 0.1 * iter)
# 更新权重
self.w += current_lr * grad / (len(pos_indices) * len(neg_indices))
def predict_proba(self, X):
return sigmoid(X.dot(self.w))
生产建议
在实际应用中,使用 AR 模型时需要注意以下几点:
- 数据预处理:
- 特征标准化对 AR 很重要,因为梯度计算涉及特征值的差异
-
对于稀疏特征,建议使用 L1 正则化防止过拟合
-
超参数设置:
- 批量大小:在小数据集上可以使用全批量,大数据集建议使用 mini-batch
-
学习率:通常从 0.01 开始尝试,配合学习率衰减策略
-
评估指标:
- 除了 AUC,还应该关注 G -mean(几何平均)和 F1-score
- 对于极度不平衡数据,可以考虑 Precision-Recall 曲线
延伸思考
AR 模型虽然在类别不平衡问题上表现优异,但在某些场景下也会遇到挑战:
- 当特征维度极高时,成对比较的计算量会变得非常大
- 对于非线性可分的数据,可能需要引入核方法
建议有 GPU 资源的读者可以尝试用 PyTorch 实现 AR 模型,利用矩阵运算并行化的优势加速训练过程。另外,也可以探索将 AR 与深度学习模型结合,处理更复杂的分类任务。
正文完
