若将回归函数改为逻辑函数 F ( w ; x ) = 1 1 + e − ( x ⊤ , 1 ) w F(\boldsymbol{w};\boldsymbol{x})=\frac{1}{1+e^{-(\boldsymbol{x}^\top,1)\boldsymbol{w}}} F(w;x)=1+e−(x⊤,1)w1,即可构建逻辑Lasso回归模型。下列代码将逻辑Lasso回归模型实现为逻辑回归模型LogicModel(见博文《最优化方法Python计算:无约束优化应用——逻辑回归模型》)的子类,并与Regression(见博文《最优化方法Python计算:无约束优化应用——线性回归预测器》)联合实现用于预测的逻辑Lasso预测器LLassoRegressor。
import numpy as np #导入numpy
class LogicLassoModel(LogicModel): #逻辑lasso模型
def obj(self,w):
h = lambda x: np.linalg.norm(x, ord = 1)
return super().obj(w) + self.alpha * h(w)
class LLassoRegressor(Regression, LogicLassoModel): #逻辑Lasso回归器
def __init__(self, alpha = 1.0):
self.alpha=alpha
self.tagVal=identity
其中,第2~5行将逻辑Lasso回归模型类LogicLassoModel实现为逻辑回归模型类LogicModel的子类,第3~5行重载目标函数
obj
(
w
)
=
1
2
∥
1
1
+
e
−
(
x
⊤
,
1
)
w
−
y
∥
2
2
+
α
∥
w
∥
1
\text{obj}(\boldsymbol{w})=\frac{1}{2}\left\lVert\frac{1}{1+e^{-(\boldsymbol{x}^\top,1)\boldsymbol{w}}}-\boldsymbol{y}\right\rVert_2^2+\alpha\lVert\boldsymbol{w}\rVert_1
obj(w)=21
1+e−(x⊤,1)w1−y
22+α∥w∥1
第6~9行将逻辑Lasso回归预测器LLassoRegressor实现为Regression和LogicLassoModel的子类。第7~9行的构造函数中初始化正则系数
α
\alpha
α,并将目标值函数设置为恒等函数以适应预测之用。
综合案例
下列代码用共享单车问题数据集SeoulBikeData.csv来自UC Irvine Machine Learning Repository训练并测试逻辑回归预测器LogicRegressor(见博文《最优化方法Python计算:无约束优化应用——逻辑回归模型》)对象,并比较用LLassoRegressor降维前后的模型性能。
import numpy as np #导入numpy
data = np.loadtxt('SeoulBikeData.csv', delimiter=',',
skiprows=1, dtype=object) #读取数据文件
X = np.array(data) #转换为数组
Y = X[:,1].astype(float) #读取标签数据
X = np.delete(X,[0,1],axis=1) #去掉日期、租赁数
X1 = X[:,9] #读取季节列
X1 = np.array([0 if x =='Spring' else #串转换为数值
1 if x=='Summer' else
2 if x=='Autumn' else
3 for x in X1])
X[:, 9] = X1 #修改季节列
X1 = X[:,10] #读取假日列
X1 = np.array([0 if x == 'No Holiday' else #串转换为数值
1 for x in X1])
X[:, 10] = X1 #修改假期列
X1 = X[:, 11] #读取运营列
X1 = np.array([0 if x == 'No' else #串转换为数值
1 for x in X1])
X[:,11] = X1 #修改运营列
X = X.astype(float) #所有数据转换为实数型
m=X.shape[0] #读取样本个数
print('共有%d个数据样本'%m)
print('随机抽取%d个样本作为训练数据。'%(m // 3))
a=np.arange(m) #下标集
np.random.seed(5050)
train = np.random.choice(a, m // 3, replace = False) #随机取得一半作为训练集下标
test = np.setdiff1d(a, train) #测试集下标
print('LOGIC REGRESSION:') #降维前逻辑回归
bikeSharingDemand = LogicRegressor() #构造逻辑回归模型
bikeSharingDemand.fit(X[train], Y[train]) #训练模型
score=bikeSharingDemand.score(X[test], Y[test])
print('系数:',bikeSharingDemand.coef_)
print('截距:%.4f'%bikeSharingDemand.intercept_)
print('对其余%d个样本数据测试,评估分:%.4f'%(m-m//3, score))
print('LOGIC LASSO REGRESSION:') #逻辑Lasso回归
bikeSharingDemand = LLassoRegressor(alpha = 0.6) #构造线性回归模型
bikeSharingDemand.fit(X[train], Y[train]) #训练模型
print('系数:',bikeSharingDemand.coef_)
print('截距:%.4f'%bikeSharingDemand.intercept_)
score=bikeSharingDemand.score(X[test], Y[test])
print('对其余%d个样本数据测试,评估分:%.4f'%(m - m // 3, score))
a = np.where(np.abs(bikeSharingDemand.coef_) < 1e-4)[0]
print('小于1/10000的系数下标:%s'%a)
X = np.delete(X, a, axis = 1)
print('LOGIC REGRESSION:') #降维后逻辑回归
bikeSharingDemand = LogicRegressor()
print('同样%d个样本作为训练数据。'%(m // 3))
bikeSharingDemand.fit(X[train], Y[train])
print('系数:%s'%bikeSharingDemand.coef_)
print('截距:%.4f'%bikeSharingDemand.intercept_)
score = bikeSharingDemand.score(X[test], Y[test])
print('对其余%d个样本数据测试,评估分:%.4f'%(m - m // 3, score))
第2~24行读取并整理数据X和Y。第25~28行随机选择三分之一数据用作训练数据X[train]、Y[train],剩下的作为测试数据X[test]和Y[test]。29~35降维前创建、训练、测试逻辑回归预测器。第36~45行创建、训练、测试逻辑Lasso模型(注意正则系数 α \alpha α设置为0.6),并进行降维操作。第46~53行用降维后数据训练、测试逻辑回归预测器。运行程序,输出
共有8760个数据样本
随机抽取2920个样本作为训练数据。
LOGIC REGRESSION:
训练中...,稍候
89次迭代后完成训练。
系数: [ 2.19358909e+02 1.69582427e+02 -4.01848411e+01 3.12938755e+01
9.17997301e-02 1.22763929e+01 -4.86491468e+02 -1.10305514e+04
-1.16978771e+03 -3.33050747e+02 -6.54678237e+02 3.38508239e+04]
截距:-43959.4834
对其余5840个样本数据测试,评估分:0.5988
LOGIC LASSO REGRESSION:
训练中...,稍候
99次迭代后完成训练。
系数: [ 1.98035101e+02 1.70403733e+02 -4.71826665e+01 7.73857926e-04
1.37950473e-01 -9.32450265e-09 -4.19912290e+02 -1.22042707e+02
1.75170438e-04 -3.48521999e+02 -4.83571040e+02 4.67112360e+03]
截距:-13890.8781
对其余5840个样本数据测试,评估分:0.5593
小于1/10000的系数下标:[3 5 8]
LOGIC REGRESSION:
同样2920个样本作为训练数据。
训练中...,稍候
43次迭代后完成训练。
系数:[ 2.20321834e+02 1.83427746e+02 -3.78221538e+01 1.01597180e-01
-4.95798044e+02 -1.09767282e+04 -3.56825709e+02 -6.21091098e+02
4.18661754e+04]
截距:-52081.3519
对其余5840个样本数据测试,评估分:0.5973
可见降维前后测试评估相差无几(0.5988和0.5973)训练效率却提高一倍(89次迭代和43次迭代)。
写博不易,敬请支持:
如果阅读本文于您有所获,敬请点赞、评论、收藏,谢谢大家的支持!