在我的数据集中,我有一些连续变量和虚拟变量。为了使用glmnet进行分析,我希望对连续变量进行标准化,但不对虚拟变量进行标准化。
我目前通过首先定义一个仅包含值[0,1]的列的虚拟向量,然后对所有非虚拟列使用scale
命令来手动执行此操作。问题是,这不是很优雅。
但是glmnet有一个内置的standardize
参数。默认情况下,它会标准化虚拟变量吗?如果是这样,是否有一种优雅的方法告诉glmnet的standardize
参数跳过虚拟变量?
在我的数据集中,我有一些连续变量和虚拟变量。为了使用glmnet进行分析,我希望对连续变量进行标准化,但不对虚拟变量进行标准化。
我目前通过首先定义一个仅包含值[0,1]的列的虚拟向量,然后对所有非虚拟列使用scale
命令来手动执行此操作。问题是,这不是很优雅。
但是glmnet有一个内置的standardize
参数。默认情况下,它会标准化虚拟变量吗?如果是这样,是否有一种优雅的方法告诉glmnet的standardize
参数跳过虚拟变量?
简而言之,是的 - 这将标准化虚拟变量,但这么做有原因。 glmnet
函数将矩阵作为其 X
参数的输入,而不是数据框,因此它不会对您可能拥有的 data.frame
参数的 factor
列进行区分。如果您查看 R 函数,glmnet 将 standardize
参数在内部编码为
isd = as.integer(standardize)
将R中的布尔值转换为0或1整数,以供内部FORTRAN函数(如elnet、lognet等)使用。
如果您进一步检查FORTRAN代码(固定宽度-老派!),您会看到以下代码块:
subroutine standard1 (no,ni,x,y,w,isd,intr,ju,xm,xs,ym,ys,xv,jerr) 989
real x(no,ni),y(no),w(no),xm(ni),xs(ni),xv(ni) 989
integer ju(ni) 990
real, dimension (:), allocatable :: v
allocate(v(1:no),stat=jerr) 993
if(jerr.ne.0) return 994
w=w/sum(w) 994
v=sqrt(w) 995
if(intr .ne. 0)goto 10651 995
ym=0.0 995
y=v*y 996
ys=sqrt(dot_product(y,y)-dot_product(v,y)**2) 996
y=y/ys 997
10660 do 10661 j=1,ni 997
if(ju(j).eq.0)goto 10661 997
xm(j)=0.0 997
x(:,j)=v*x(:,j) 998
xv(j)=dot_product(x(:,j),x(:,j)) 999
if(isd .eq. 0)goto 10681 999
xbq=dot_product(v,x(:,j))**2 999
vc=xv(j)-xbq 1000
xs(j)=sqrt(vc) 1000
x(:,j)=x(:,j)/xs(j) 1000
xv(j)=1.0+xbq/vc 1001
goto 10691 1002
看一下标记为1000的行——这基本上是将标准化公式应用于X
矩阵。
从统计学角度来看,人们通常不会对分类变量进行标准化以保留估计回归系数的可��释性。然而,正如Tibshirani在这里指出的那样,“套索法要求对回归器进行初始标准化,使惩罚方案对所有回归器都公平。对于分类回归器,可以使用虚拟变量对回归器进行编码,然后对虚拟变量进行标准化”——因此,虽然这会导致连续和分类变量之间的任意缩放,但是这是为了实现平等的惩罚处理。
glmnet
不知道关于虚拟变量的任何信息,因为它没有公式接口(因此不会涉及model.frame
和model.matrix
)。如果您想让它们被特别处理,您需要自己处理。