blob: fb5dc8b5bfd17c1e0909749a7e87dd02d74e5c15 [file]
#-------------------------------------------------------------
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
#-------------------------------------------------------------
# 50k Dataset w/ 4-fold CV w/ 2 classes
# Total time: 3.7473180000000004 sec.
# Number of executed MR Jobs: 0.
# hadoop jar SystemDS.jar -f CV_MultiClassSVM.dml -args itau/svm/X_50k_10 itau/svm/y_50k 4 0 2 0.001 1.0 100
# 100k Dataset w/ 4-fold CV w/ 2 classes
# Total time: 206.549618 sec.
# Number of executed MR Jobs: 16.
# hadoop jar SystemDS.jar -f CV_MultiClassSVM.dml -args itau/svm/X_100k_500 itau/svm/y_100k 4 0 2 0.001 1.0 100
X = read( $1 );
y = read( $2 );
m = nrow( X );
n = ncol( X );
k = $3;
#parameters for model training
intercept = $4
num_classes = $5
epsilon = $6
lambda = $7
maxiter = $8
#CV
P = Rand(rows=m, cols=1, min=0.0, max=1.0, pdf = "uniform");
P = round(0.5+P*k);
ones = matrix(1, rows=1, cols=n);
onem = matrix(1, rows=1, cols=1);
stats = matrix(0, rows=k, cols=1); #k-folds x 1-stats
parfor( i in 1:k )
{
#prepare train/test fold projections
vPxi = (P == i); # Select 1/k fraction of the rows
mPxi = (vPxi %*% ones); # for the i-th fold TEST set
#nvPxi = (P != i);
#nmPxi = (nvPxi %*% ones); #note: inefficient for sparse data
#create train/test folds
Xi = X * mPxi; # Create the TEST set with 1/k of all the rows
yi = y * vPxi; # Create the labels for the TEST set
nXi = X - Xi; # Create the TRAINING set with (k-1)/k of the rows
nyi = y - yi; # Create the labels for the TRAINING set
Xyi = cbind(Xi,yi); #keep alignment on removeEmpty
Xyi = removeEmpty( target=Xyi, margin="rows" );
Xi = Xyi[ , 1:n];
yi = Xyi[ , n+1];
nXyi = cbind(nXi,nyi); #keep alignment on removeEmpty
nXyi = removeEmpty( target=nXyi, margin="rows" );
nXi = nXyi[ , 1:n];
nyi = nXyi[ , n+1];
#train multiclass SVM model per fold, use the TRAINING set
wi = multiClassSVM( nXi, nyi, intercept, num_classes, epsilon, lambda, maxiter)
#score multiclass SVM model per fold, use the TEST set
out_correct_pct = scoreMultiClassSVM( Xi, yi, wi, intercept);
stats[i,1] = out_correct_pct * onem;
}
# print output of stats
z = printFoldStatistics( stats );
################################################################################
printFoldStatistics = function( Matrix[double] stats)
return( Integer err)
{
mean_correct_pct = mean( stats[,1])
print (" Mean Correct Percentage of the " + nrow( stats) + " Folds: " + mean_correct_pct);
err = 0
}
################################################################################
scoreMultiClassSVM = function( Matrix[double] X, Matrix[double] y, Matrix[double] W, Integer intercept)
return (Double out_correct_pct)
{
Nt = nrow(X);
num_classes = ncol(W)
b = Rand( rows=1, cols=num_classes, min=0, max=0, pdf="uniform")
n = ncol(X);
if (intercept == 1)
{
b = W[n+1,]
}
ones = Rand( rows=Nt, cols=1, min=1, max=1, pdf="uniform")
scores = X %*% W[1:n,] + ones %*% b;
predicted_y = rowIndexMax( scores);
correct_percentage = sum((predicted_y - y) == 0) / Nt * 100;
out_correct_pct = correct_percentage;
}
################################################################################
multiClassSVM = function (Matrix[double] X, Matrix[double] Y, Integer intercept, Integer num_classes, Double epsilon, Double lambda, Integer max_iterations)
return (Matrix[double] ret_W)
{
check_X = sum(X)
if(check_X == 0){
print("X has no non-zeros")
} else {
num_samples = nrow(X)
num_features = ncol(X)
if (intercept == 1) {
ones = Rand( rows=num_samples, cols=1, min=1, max=1, pdf="uniform");
X = cbind( X, ones);
}
iter_class = 1
Y_local = 2 * (Y == iter_class) - 1
w_class = Rand( rows=num_features, cols=1, min=0, max=0, pdf="uniform")
if (intercept == 1) {
zero_matrix = Rand( rows=1, cols=1, min=0.0, max=0.0);
w_class = t( cbind( t( w_class), zero_matrix));
}
g_old = t(X) %*% Y_local
s = g_old
iter = 0
continue = 1
while(continue == 1) {
# minimizing primal obj along direction s
step_sz = 0
Xd = X %*% s
wd = lambda * sum(w_class * s)
dd = lambda * sum(s * s)
continue1 = 1
while(continue1 == 1){
tmp_w = w_class + step_sz*s
out = 1 - Y_local * (X %*% tmp_w)
sv = (out > 0)
out = out * sv
g = wd + step_sz*dd - sum(out * Y_local * Xd)
h = dd + sum(Xd * sv * Xd)
step_sz = step_sz - g/h
if (g*g/h < 0.0000000001){
continue1 = 0
}
}
#update weights
w_class = w_class + step_sz*s
out = 1 - Y_local * (X %*% w_class)
sv = (out > 0)
out = sv * out
obj = 0.5 * sum(out * out) + lambda/2 * sum(w_class * w_class)
g_new = t(X) %*% (out * Y_local) - lambda * w_class
tmp = sum(s * g_old)
train_acc = sum((Y_local*(X%*%w_class)) >= 0)/num_samples*100
print("For class " + iter_class + " iteration " + iter + " training accuracy: " + train_acc)
if((step_sz*tmp < epsilon*obj) | (iter >= max_iterations-1)){
continue = 0
}
#non-linear CG step
be = sum(g_new * g_new)/sum(g_old * g_old)
s = be * s + g_new
g_old = g_new
iter = iter + 1
}
w = w_class
iter_class = iter_class + 1
while(iter_class <= num_classes){
Y_local = 2 * (Y == iter_class) - 1
# w_class = Rand(rows=num_features, cols=1, min=0, max=0, pdf="uniform")
w_class = Rand(rows=ncol(X), cols=1, min=0, max=0, pdf="uniform")
if (intercept == 1) {
zero_matrix = Rand(rows=1, cols=1, min=0.0, max=0.0);
w_class = t(cbind(t(w_class), zero_matrix));
}
g_old = t(X) %*% Y_local
s = g_old
iter = 0
continue = 1
while(continue == 1) {
# minimizing primal obj along direction s
step_sz = 0
Xd = X %*% s
wd = lambda * sum(w_class * s)
dd = lambda * sum(s * s)
continue1 = 1
while(continue1 == 1){
tmp_w = w_class + step_sz*s
out = 1 - Y_local * (X %*% tmp_w)
sv = (out > 0)
out = out * sv
g = wd + step_sz*dd - sum(out * Y_local * Xd)
h = dd + sum(Xd * sv * Xd)
step_sz = step_sz - g/h
if (g*g/h < 0.0000000001){
continue1 = 0
}
}
#update weights
w_class = w_class + step_sz*s
out = 1 - Y_local * (X %*% w_class)
sv = (out > 0)
out = sv * out
obj = 0.5 * sum(out * out) + lambda/2 * sum(w_class * w_class)
g_new = t(X) %*% (out * Y_local) - lambda * w_class
tmp = sum(s * g_old)
train_acc = sum((Y_local*(X%*%w_class)) >= 0)/num_samples*100
print("For class " + iter_class + " iteration " + iter + " training accuracy: " + train_acc)
if((step_sz*tmp < epsilon*obj) | (iter >= max_iterations-1)){
continue = 0
}
#non-linear CG step
be = sum(g_new * g_new)/sum(g_old * g_old)
s = be * s + g_new
g_old = g_new
iter = iter + 1
}
w = cbind(w, w_class)
iter_class = iter_class + 1
}
ret_W = w
}
}