作为一名曾经研究过人工神经网络的菜鸟,前两天刚听说有岭回归估计和LASSO估计,统计学老师也布置了作业,然,在不甚理解的情况下,用Python写了一下,也不知是否正确。不合适的地方请不吝赐教。
作业如下:
x,y已知,分别用岭估计和LASSO估计,估计
的值,并使用MSE评估估计结果。
个人理解:
在完全没有数据的情况下,很显然,需要随机生成一些数据。在年少的时候就知道,若已知
和
值,给定一个x就会有个y生成。
所以
第一步:肯定是要生成一批y,将
作为真实值,用来与接下来估计出的值进行比较。第二步,应该是在给定x,y的条件下,使用岭估计和LASSO估计来得到
的估计值。
(额,好像说的像废话)
对于岭估计和LASSO估计,是由岭回归和LASSO方法来的。
关于岭回归和LASSO的理论知识,可以参看如下链接:
机器学习-第3周,岭回归和lasso (个人觉着,讲的挺好的)
接下来,在了解了理论知识的皮毛,开始实现代码。
(这样其实不好,要深入了解理论知识后,才好开始写代码。因为如果一开始想的问题不对,可能会造成代码的全盘推翻。)
说一下我实现代码的整个思路:
# 问题描述:模型 y=x*b+a 。给定x,y估计b。
# 整体思路:
# 0. 初始化,设置全局参数:n为数据总量,dim为维度
# 1。随机生成n*dim维的x,dim*1维的系数b和a,求出y值
# 2. 随机生成模型参数Lambda,确定回归模型,得到模型系数B和Lambda的图像
# 3. 通过验证,确定最优回归模型的Lambda值
# 4. 基于最优的Lamma建模,并给定x,y 确定系数_B
# 5. 评估真实系数b和模型系数B的MSE
代码片段如下:(整个代码会在后面提供链接)
1.初始化 随机生成n*dim维的x,dim*1维的系数b和a,求出y值,返回x,y,b
def ini_data(n,dim):
'''
初始化数据
:param n: 数据总量
:param dim: 参数维度
:return: x,y,b(系数)
'''
x = np.random.uniform(-100,100,(n,dim))
b = np.random.rand(dim)
a = np.random.rand(n)
y=np.matmul(x,b)+a
return x,y,b
2. 岭回归模型
def reg_model_Ridge(x,y,alphas,dim):
'''
;岭回归估计
:param x:
:param y:
:param alphas: 随机生成多个模型参数Lambda
:param dim:维度
:return: ridge_B 最优模型的系数
'''
model_coff=[]
for alpha in alphas:
ridge = Ridge(alpha=alpha,normalize=True)
ridge.fit(x,y)
model_coff.append(ridge.coef_)
# if dim<=10:
#plot_data(alphas, model_coff, 'Log Alpha', 'Cofficients', 'alpha系数与岭回归系数的关系 ,dim='+str(dim))
# 交叉验证,找到模型最优的Lambda值
ridge_cv= RidgeCV(alphas=alphas,normalize=True,scoring="neg_mean_absolute_error", cv=5)
ridge_cv.fit(x,y)
ridge_best_lambda = ridge_cv.alpha_
# 建立最优模型
ridge = Ridge(alpha=ridge_best_lambda,normalize=True)
ridge.fit(x,y)
# 得到最优模型的系数
ridge_B = ridge.coef_
return ridge_B
3.LASSO模型
def reg_model_LASSO(x,y,alphas,dim):
'''
;LASSO 回归
:param x:
:param y:
:param alphas: 随机生成多个模型参数Lambda
:param dim:维度
:return: lasso_B 最优模型的系数
'''
model_coff=[]
for alpha in alphas:
lasso = Lasso(alpha=alpha,normalize=True)
lasso.fit(x,y)
model_coff.append(lasso.coef_)
# if dim <= 10:
#plot_data(alphas, model_coff, 'Log Alpha', 'Cofficients', 'alpha系数与LASSO系数的关系 ,dim='+str(dim))
# 交叉验证,找到模型最优的Lambda值
lasso_cv= LassoCV(alphas=alphas,normalize=True,max_iter=1000, cv=5)
lasso_cv.fit(x,y)
ridge_best_lambda = lasso_cv.alpha_
# 建立最优模型
lasso = Lasso(alpha=ridge_best_lambda,normalize=True)
lasso.fit(x,y)
# 得到最优模型的系数
lasso_B = lasso.coef_
return lasso_B
说明:
岭回归和LASSO回归在Python包sklearn.linear_model中已经写好了,而且还有相对应的交叉验证的模型。
两块代码整体上是一样的,首先,生成一批的alpha值,可以画出alpha值和模型系数中间的关系(为什么?这个我现在也不甚了解,希望大神可以指点一二)。然后,通过校验模型,来确定最优模型的alpha值。最后,基于最优的alpha值建立模型,得到最优模型的系数(也就是估计出来的
值)
注明几点:
(1)我们需要随机生成一批模型的alpha变量,因为很多时候,我们需要通过实验来选择最佳的alpha值,给指定一个具体的alpha值,就会建成一个新的模型。
(2)在模型的调用上,沿用了训练神经网络的方式,像.fit()函数,用来向模型中喂入数据。可以通过“.”来获得模型中的参数值。
(3)岭回归校验方法(RidgeCV)中,有个scoring参数,而LASSO校验中没有。
(4)在运行中,如果scoring="mean_absolute_error"会出错,要改为scoring="neg_mean_absolute_error"。
5. 运行代码 (作业要求对数据对个维度进行比较,所以用了for循环)
def run_fun():
n =500 # data length
dims = [10,50,100,200]
for dim in dims:
# alphas = 10 ** np.random.uniform(-5,5,dim)
alphas = 10 ** np.linspace(-5, 5, dim)
x, y, b=ini_data(n,dim)
ridge_B=reg_model_Ridge(x,y,alphas,dim)
RMSE = np.sqrt(mean_squared_error(ridge_B, b))
print("----------维度:", dim, ",---------")
print("岭回归 MSE :",RMSE)
lasso_B=reg_model_LASSO(x,y,alphas,dim)
LMSE = np.sqrt(mean_squared_error(lasso_B, b))
print("LASSO MSE :", LMSE)
run_fun()
6.结束了,就这样。
代码链接:
运行的结果是这样子的: