Frank Wolfe Method and Projected Gradient Descent Method

We consider \((X_i,Y_i)\), and i=1,2,…,n, and \(X_i\in R^d\), and \(Y_i \in R\). We assume that \((X_i,Y_i)\) satisfies the following linear model.

\[Y_i=X_i^T\beta+\sigma_i\] Where \(\sigma_i\) is drawn from standard normal distribution. We can use optimaization method to solve above problem.

\[min_\beta\sum_{i=1}^n(Y_i-X_i^T\beta)^2\] \[s.t. \space ||\beta||_1<=r\]

The first part is Frank wolfe method to solve optimization problem.

Frank_Wolfe<-function(x,y,maxiter,r)
{
  n<-nrow(x)
  d<-ncol(x)
  theta=matrix(rep(0,d),d,1) 
  iter<-0
  theta_trace=matrix(rep(0,d*maxiter),maxiter,d)
  
   
while(iter<maxiter){
    iter<-iter+1
    y_k=matrix(rep(0,d),d,1) 
    grad=2*t(-x)%*%(y-x%*%theta) #d*n*n*1=d*1
    #A=matrix(sign_func(grad),nrow=1,byrow=T)
    #lp.sol<-lp(direction="min",objective.in=grad,const.mat=A,const.dir="<=",const.rhs=r,compute.sens=1)
    #y_k=lp.sol$solution
    #y_k[which.min(grad)]=r
    if (abs(min(grad))>=abs(max(grad))){
      y_k[which.min(grad)]=1
    }else if(abs(min(grad))<abs(max(grad))){
      y_k[which.max(grad)]=-1
    }
    step=2/(iter+2)
    theta_new=(1-step)*theta+step*y_k
    theta_trace[iter,]=theta_new
    theta=theta_new
    
}
      return(theta_trace)
}

The second part is projected gradient descent method.

L1_ball_pro function is to compute the projection of L1 norm.

L1_ball_pro=function(h,r){
  temp1=sort(abs(h),decreasing=TRUE)
  temp2=cumsum(temp1)-r
  temp3=temp1-temp2/c(1:length(temp1))
  p=length(temp3[temp3>0])
  t=(sum(temp1[1:p])-r)/p
  h_abs=abs(h)-t
  h_abs[(h_abs)<0]=0
  theta_new=sign(h)*h_abs
  return(theta_new)
}

Projected_desc<-function(x,y,maxiter,r)
{
  n<-nrow(x)
  d<-ncol(x)
  theta=matrix(rep(0,d),d,1) 
  iter<-0
  theta_trace=matrix(rep(0,d*maxiter),maxiter,d)
  
   
while(iter<maxiter){
    iter<-iter+1
    grad=2*t(x)%*%(x%*%theta-y) #d*n*n*1=d*1
    grad=grad/n
    step=1/100000
    h=theta-step*grad
    theta_trace[iter,]=theta
    if (sum(abs(h))>r){
      theta_new=L1_ball_pro(h,r)
    }else if(sum(abs(h))<=r){
      theta_new=h
    }
    theta_trace[iter,]=theta_new
    theta=theta_new
}
    return(theta_trace)
}

By using fat data set in faraway library, I use two features as predictor

The first part is Frank Wolfe method.

y=as.matrix(fat$siri)
x=as.matrix(fat[,4:5])
t1<-Sys.time()
out_1=Frank_Wolfe(x,y,5000,1)
t2<-Sys.time()
time_1=t2-t1
tail(out_1)
##               [,1]       [,2]
## [4995,] 0.07511176 0.09004490
## [4996,] 0.07508170 0.09040903
## [4997,] 0.07505166 0.09077294
## [4998,] 0.07502164 0.09033663
## [4999,] 0.07499164 0.09070042
## [5000,] 0.07496166 0.09026431

Then, I use projected gradient descent method

y=as.matrix(fat$siri)
x=as.matrix(fat[,4:5])
t1<-Sys.time()
out_2=Projected_desc(x,y,5000,1)
t2<-Sys.time()
tail(out_2)
##               [,1]       [,2]
## [4995,] 0.07960534 0.08935974
## [4996,] 0.07960534 0.08935974
## [4997,] 0.07960534 0.08935974
## [4998,] 0.07960534 0.08935974
## [4999,] 0.07960534 0.08935974
## [5000,] 0.07960534 0.08935974
time_2=t2-t1

I use lm function output as standard coefficients.

lm(y~0+x)
## 
## Call:
## lm(formula = y ~ 0 + x)
## 
## Coefficients:
##    xage  xweight  
## 0.07961  0.08936

Then, plot these two output by using MSE.

output_1=sqrt(rowSums((out_1-c(0.07961,0.08936))^2))
output_2=sqrt(rowSums((out_2-c(0.07961,0.08936))^2))
plot(output_1,col=1,pch=20)
lines(output_2,col=2)
legend("topright", legend=c("Frank Wolfe method", "projected gradient descent"),
       col=c(1,2), lty=1:1, cex=0.8)

We can notice that, projected gradient descent method seems to have a faster.

And we can check running time, projected method has a smaller running time.

time_1
## Time difference of 0.151875 secs
time_2
## Time difference of 0.0999341 secs