在机器学习领域,对数几率回归是一种广泛使用的分类算法。本文将探讨在新闻组数据集上,使用L1正则化和L2正则化的对数几率回归模型的性能对比。新闻组数据集是一个大型的文本数据集,包含了多个类别的新闻文章。目标是使用这些模型来对文档进行分类,以确定它们属于哪个类别。
在本研究中,采用了两种不同的正则化技术:L1和L2。L1正则化通过将不重要特征的权重缩减至零,有助于提取每个类别的强判别词汇。如果目标是获取最佳的预测准确性,使用不产生稀疏性的L2惩罚可能更为合适。此外,一种更传统(可能也是更好的)方式是先使用单变量特征选择,然后应用传统的(L2惩罚的)对数几率回归模型。
使用了20newsgroup数据集,训练样本数为4500,特征数为130107,类别数为20。模型采用一对多(One versus Rest)的策略,使用saga求解器。对模型进行了1到3个epoch的训练,并记录了测试准确率和每个类别的非零系数百分比。结果显示,使用L1正则化的模型在测试集上的准确率为0.5960,而非零系数的百分比在各个类别之间有所不同。
相比之下,采用L2正则化的多项式对数几率回归模型在5个epoch的训练后,测试准确率达到了0.6440。非零系数的百分比同样在各个类别之间有所差异。L2正则化的模型运行时间稍短,为1.22秒,而L1正则化的模型运行时间为1.55秒。
通过比较这两种模型,可以得出结论:在新闻组数据集上,L2正则化的多项式对数几率回归模型在分类准确率上表现更好,且训练速度更快。这可能是因为L2正则化能够更好地处理大型数据集,并且能够更有效地利用所有特征进行学习。
import timeit
import warnings
import matplotlib.pyplot as plt
import numpy as np
from sklearn.datasets import fetch_20newsgroups_vectorized
from sklearn.exceptions import ConvergenceWarning
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.multiclass import OneVsRestClassifier
# 忽略收敛警告
warnings.filterwarnings("ignore", category=ConvergenceWarning, module="sklearn")
# 设置求解器和样本数量
solver = "saga"
n_samples = 5000
# 加载数据集
X, y = fetch_20newsgroups_vectorized(subset="all", return_X_y=True)
X = X[:n_samples]
y = y[:n_samples]
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42, stratify=y, test_size=0.1)
# 获取训练样本数、特征数和类别数
train_samples, n_features = X_train.shape
n_classes = np.unique(y).shape[0]
# 输出数据集信息
print("Dataset 20newsgroup, train_samples=%i, n_features=%i, n_classes=%i" % (train_samples, n_features, n_classes))
# 定义模型参数
models = {
"ovr": {"name": "One versus Rest", "iters": [1, 2, 3]},
"multinomial": {"name": "Multinomial", "iters": [1, 2, 5]},
}
# 训练和评估模型
for model in models:
model_params = models[model]
accuracies = [1 / n_classes] # 初始化准确率
times = [0] # 初始化时间
densities = [1] # 初始化非零系数百分比
# 训练模型
for this_max_iter in model_params["iters"]:
print("[model=%s, solver=%s] Number of epochs: %s" % (model_params["name"], solver, this_max_iter))
clf = LogisticRegression(solver=solver, penalty="l1", max_iter=this_max_iter, random_state=42)
if model == "ovr":
clf = OneVsRestClassifier(clf)
t1 = timeit.default_timer()
clf.fit(X_train, y_train)
train_time = timeit.default_timer() - t1
y_pred = clf.predict(X_test)
accuracy = np.sum(y_pred == y_test) / y_test.shape[0]
if model == "ovr":
coef = np.concatenate([est.coef_ for est in clf.estimators_])
else:
coef = clf.coef_
density = np.mean(coef != 0, axis=1) * 100
accuracies.append(accuracy)
densities.append(density)
times.append(train_time)
# 保存模型结果
models[model]["times"] = times
models[model]["densities"] = densities
models[model]["accuracies"] = accuracies
# 输出模型结果
print("Test accuracy for model %s: %.4f" % (model, accuracies[-1]))
print("%% non-zero coefficients for model %s, per class:\n%s" % (model, densities[-1]))
print("Run time (%i epochs) for model %s: %.2f" % (model_params["iters"][-1], model, times[-1]))
# 绘制模型性能图
fig = plt.figure()
ax = fig.add_subplot(111)
for model in models:
name = models[model]["name"]
times = models[model]["times"]
accuracies = models[model]["accuracies"]
ax.plot(times, accuracies, marker="o", label="Model: %s" % name)
ax.set_xlabel("Train time (s)")
ax.set_ylabel("Test accuracy")
ax.legend()
fig.suptitle("Multinomial vs One-vs-Rest Logistic L1\nDataset 20newsgroups")
fig.tight_layout()
fig.subplots_adjust(top=0.85)
plt.show()
以上代码展示了如何在新闻组数据集上使用L1和L2正则化的对数几率回归模型进行文档分类。代码首先加载数据集,然后划分训练集和测试集。接着,定义了两种模型的参数,并分别训练和评估了这两种模型。最后,代码绘制了模型性能的图表,以直观地展示不同模型的性能对比。
通过实验,发现在新闻组数据集上,使用L2正则化的多项式对数几率回归模型在分类准确率和训练速度上都优于使用L1正则化的模型。这表明在处理大型数据集时,L2正则化可能是一个更好的选择。然而,如果目标是提取每个类别的强判别词汇,L1正则化仍然是一个有价值的工具。