Browse Source

initial commit

Alexander Freytag 9 years ago
commit
3eb1e2a154

+ 80 - 0
initWorkspaceLibLinear.m

@@ -0,0 +1,80 @@
+function initWorkspaceLibLinear
+% function initWorkspaceLibLinear
+% 
+% BRIEF
+%   Add local subfolders and 3rd party libraries to Matlabs work space.
+%
+%   Exemplary call from external position:
+%        LIBLINEARWRAPDIR = '/place/to/this/repository/';
+%        currentDir = pwd;
+%        cd ( LIBLINEARWRAPDIR );
+%        initWorkspaceLibLinear;
+%        cd ( currentDir );
+%    
+% 
+% Author: Alexander Freytag
+
+    %% setup paths in user-specific manner
+
+
+    % currently we do not have any dependencies, but if we would have some,
+    % we would add them here  
+    
+    %% add paths which come with this repository
+    
+    if strcmp( getenv('USER'), 'freytag')
+        LIBLINEARDIR    = '~/code/3rdParty/liblinear-1.93/matlab/';   
+    else
+        fprintf('Unknown user %s and unknown default settings', getenv('USER') ); 
+    end    
+    
+    % add main path
+    b_recursive             = false; 
+    b_overwrite             = true;
+    s_pathMain              = fullfile(pwd);
+    addPathSafely ( s_pathMain, b_recursive, b_overwrite )
+    clear ( 's_pathMain' );    
+    
+    % for addFieldWithDefault.m
+    b_recursive             = true; 
+    b_overwrite             = true;
+    s_pathMisc              = fullfile(pwd, 'misc');
+    addPathSafely ( s_pathMisc, b_recursive, b_overwrite )
+    clear ( 's_pathMisc' );        
+        
+    %% 3rd party, untouched
+    
+    if ( isempty(LIBLINEARDIR) )
+        fprintf('InitPatchDiscovery-WARNING - no LIBLINEARDIR dir found on your machine. Code is available at http://www.csie.ntu.edu.tw/~cjlin/liblinear/ \n');
+    else
+        b_recursive         = true; 
+        b_overwrite         = true;
+        addPathSafely ( LIBLINEARDIR, b_recursive, b_overwrite );        
+    end 
+    
+    %% clean up
+    
+    clear( 'LIBLINEARDIR' );
+end
+
+
+function addPathSafely ( s_path, b_recursive, b_overwrite )
+    if ( ~isempty(strfind(path, [s_path , pathsep])) )
+        if ( b_overwrite )
+            if ( b_recursive )
+                rmpath( genpath( s_path ) );
+            else
+                rmpath( s_path );
+            end
+        else
+            fprintf('initWSLibLinear - %s already in your path but overwriting de-activated.\n', s_path);
+            return;
+        end
+    end
+    
+    if ( b_recursive )
+        addpath( genpath( s_path ) );
+    else
+        addpath( s_path );
+    end
+end

+ 62 - 0
liblinear_test.m

@@ -0,0 +1,62 @@
+function [predicted_label, accuracy, scores] =liblinear_test ( labels_test, feat_test, svmmodel, settings )
+%
+% BRIEF
+%   A simple wrapper to provide testing of 1-vs-all-classification for LIBLINEAR. 
+%   No further settings are adjustable currently.
+% 
+% INPUT
+%  labels_test   -- multi-class labels (#samples x 1)
+%  feat_test     -- features for test images (#samples x # dimensions)
+%  svmmodel      -- cell ( #classes x 1 ), every model entry is obtained via
+%                   svmtrain of the corresponding 1-vs-all-problem
+%  settings      -- struct for configuring the svm classification, e.g., via
+%                   'b_verbose' ...
+% 
+% OUTPUT:
+% 
+%
+% date: 30-04-2014 ( dd-mm-yyyy )
+% author: Alexander Freytag
+
+    if ( nargin < 4 ) 
+        settings = [];
+    end
+    
+    libsvm_options = '';
+    
+    % outputs for training
+    if ( ~ getFieldWithDefault ( settings, 'b_verbose', false ) )
+        libsvm_options = sprintf('%s -q', libsvm_options);
+    end    
+  
+    i_numClasses = size ( svmmodel,1);
+    i_numSamples = size( labels_test,1);
+    
+    b_weightBalancing = getFieldWithDefault ( settings, 'b_weightBalancing', false);
+    
+    if ( ~b_weightBalancing )
+        [predicted_label,~,scores] = predict( labels_test, feat_test, svmmodel, libsvm_options );
+    else
+        scores = zeros( i_numSamples, i_numClasses );
+        
+        % classify with everyone-against-all model    
+        for k=1:i_numClasses
+            yBin              = 2*double( labels_test == svmmodel{k}.uniqueLabel )-1;
+            [~,~,scores(:,k)] = predict( yBin, feat_test, svmmodel{k}, libsvm_options );
+            
+            %Q: Why the sign of predicted labels and decision values are sometimes reversed?
+            %Please see the answer in LIBSVM faq.
+            %To correctly obtain decision values, you need to check the array
+            %label
+            %in the model.
+            scores(:,k)       = scores(:,k) .* repmat( svmmodel{k}.Label(1), [i_numSamples,1] ) ;
+        end 
+
+        %# predict the class with the highest score
+        [~,predicted_label] = max(scores,[],2);        
+    end
+
+    % accuracy
+    accuracy = sum(predicted_label == labels_test) ./ numel(labels_test) ;   
+end
+

+ 36 - 0
liblinear_test_regression.m

@@ -0,0 +1,36 @@
+function [regressionScores, mse ] =liblinear_test_regression ( labels_test, feat_test, svmmodel, settings )
+%
+% BRIEF
+%   A simple wrapper to provide testing of regression for LIBLINEAR.. 
+%   No further settings are adjustable currently.
+% 
+% INPUT
+%  labels_test   -- regression labels (#samples x 1)
+%  feat_test     -- features for test images (#samples x # dimensions)
+%  svmmodel      -- previously trained regression model
+%  settings      -- struct for configuring the svm regression, e.g., via
+%                   'b_verbose' ...
+% 
+% OUTPUT:
+%    regressionScores
+%    mse
+%
+% date: 15-05-2014 ( dd-mm-yyyy )
+% author: Alexander Freytag
+
+    if ( nargin < 4 ) 
+        settings = [];
+    end
+    
+    libsvm_options = '';
+    
+    % outputs for training
+    if ( ~ getFieldWithDefault ( settings, 'b_verbose', false ) )
+        libsvm_options = sprintf('%s -q', libsvm_options);
+    end    
+  
+    i_numSamples = size( labels_test,1);
+    
+    [regressionScores, mse ,~] = predict( labels_test, feat_test, svmmodel, libsvm_options );
+
+end

+ 86 - 0
liblinear_train.m

@@ -0,0 +1,86 @@
+function svmmodel = liblinear_train ( labels, feat, settings )
+%
+% BRIEF
+%   A simple wrapper to provide training of 1-vs-all-classification for LIBLINEAR. No
+%   further settings are adjustable currently.
+% 
+% INPUT
+%  labels   -- multi-class labels (#sample x 1)
+%  feat     -- features for training images (#samples x # dimensions)
+%  settings -- struct for configuring the svm model training, e.g., via
+%              'b_verbose', 'f_svm_C', ...
+% 
+% OUTPUT:
+%  svmmodel -- cell ( #classes x 1 ), every model entry is obtained via
+%              svmtrain of the corresponding 1-vs-all-problem
+%
+% date: 30-04-2014 ( dd-mm-yyyy )
+% author: Alexander Freytag
+
+    if ( nargin < 3 ) 
+        settings = [];
+    end
+    
+    
+    libsvm_options = '';
+    
+    % outputs for training
+    if ( ~ getFieldWithDefault ( settings, 'b_verbose', false ) )
+        libsvm_options = sprintf('%s -q', libsvm_options);
+    end
+    
+    % cost parameter
+    f_svm_C = getFieldWithDefault ( settings, 'f_svm_C', 1);
+    libsvm_options = sprintf('%s -c %f', libsvm_options, f_svm_C);    
+    
+    % do we want to use an offset for the hyperplane?
+    if ( getFieldWithDefault ( settings, 'b_addOffset', false) )
+        libsvm_options = sprintf('%s -B 1', libsvm_options);    
+    end
+    
+    % which solver to use
+    % copied from the liblinear manual:
+%       for multi-class classification
+%          0 -- L2-regularized logistic regression (primal)
+%          1 -- L2-regularized L2-loss support vector classification (dual)
+%          2 -- L2-regularized L2-loss support vector classification (primal)
+%          3 -- L2-regularized L1-loss support vector classification (dual)
+%          4 -- support vector classification by Crammer and Singer
+%          5 -- L1-regularized L2-loss support vector classification
+%          6 -- L1-regularized logistic regression
+%          7 -- L2-regularized logistic regression (dual)    
+    i_svmSolver = getFieldWithDefault ( settings, 'i_svmSolver', 1);
+    libsvm_options = sprintf('%s -s %d', libsvm_options, i_svmSolver);    
+
+    
+    % increase penalty for positive samples according to invers ratio of
+    % their number, i.e., if 1/3 is ratio of positive to negative samples, then
+    % impact of positives is 3 the times of negatives
+    % 
+    b_weightBalancing = getFieldWithDefault ( settings, 'b_weightBalancing', false);
+    
+    
+  
+    uniqueLabels = unique ( labels );
+    i_numClasses = size ( uniqueLabels,1);
+    
+	
+    %# train one-against-all models
+    
+    if ( ~b_weightBalancing)    
+        svmmodel = train( labels, feat, libsvm_options );
+    else
+        svmmodel = cell( i_numClasses,1);
+        for k=1:length(i_classesToRun)
+            yBin        = 2*double( labels == uniqueLabels( k ) )-1;
+            
+            fraction = double(sum(yBin==1))/double(numel(yBin));
+            libsvm_optionsLocal = sprintf('%s -w1 %f', libsvm_options, 1.0/fraction);
+            svmmodel{ k } = train( yBin, feat, libsvm_optionsLocal );
+            
+            %store the unique class label for later evaluations.
+            svmmodel{ k }.uniqueLabel = uniqueLabels( k );
+        end         
+    end
+    
+end

+ 53 - 0
liblinear_train_regression.m

@@ -0,0 +1,53 @@
+function svmmodel = liblinear_train_regression ( labels, feat, settings )
+%
+% BRIEF
+%   A simple wrapper to provide training of regression for LIBLINEAR. No
+%   further settings are adjustable currently.
+% 
+% INPUT
+%  labels   -- labels (#sample x 1)
+%  feat     -- features for training images (#samples x # dimensions)
+%  settings -- struct for configuring the svm model training, e.g., via
+%              'b_verbose', 'f_svm_C', ...
+% 
+% OUTPUT:
+%  svmmodel -- resulting model
+%
+% date: 30-04-2014 ( dd-mm-yyyy )
+% author: Alexander Freytag
+
+    if ( nargin < 3 ) 
+        settings = [];
+    end
+    
+    
+    libsvm_options = '';
+    
+    % outputs for training
+    if ( ~ getFieldWithDefault ( settings, 'b_verbose', false ) )
+        libsvm_options = sprintf('%s -q', libsvm_options);
+    end
+    
+    % cost parameter
+    f_svm_C = getFieldWithDefault ( settings, 'f_svm_C', 1);
+    libsvm_options = sprintf('%s -c %f', libsvm_options, f_svm_C);    
+    
+    % do we want to use an offset for the hyperplane?
+    if ( getFieldWithDefault ( settings, 'b_addOffset', false) )
+        libsvm_options = sprintf('%s -B 1', libsvm_options);    
+    end
+    
+    % which solver to use
+    % copied from the liblinear manual:
+%        for regression
+%             11 -- L2-regularized L2-loss support vector regression (primal)
+%             12 -- L2-regularized L2-loss support vector regression (dual)
+%             13 -- L2-regularized L1-loss support vector regression (dual)   
+    i_svmSolver = getFieldWithDefault ( settings, 'i_svmSolver', 11);
+    libsvm_options = sprintf('%s -s %d', libsvm_options, i_svmSolver);  
+
+    %# train regression model
+    
+    svmmodel = train( labels, feat, libsvm_options );
+    
+end

+ 26 - 0
misc/getFieldWithDefault.m

@@ -0,0 +1,26 @@
+function myOut = getFieldWithDefault ( myStruct, myField, myDefault )
+% function myOut = getFieldWithDefault ( myStruct, myField, myDefault )
+% 
+%  BRIEF:
+%    Get the content of a named field of a struct if existing, or return a
+%    specified default value instead
+%    ...inspired by NICE::Config.gI ('section','name', default )
+% 
+%  INPUT:
+%    myStruct  -- a struct
+%    myField   -- string with desired field name
+%    myDefault -- default value to use if field is non-existing or empty
+% 
+%  OUTPUT:
+%    myOut     -- content of field or default value
+% 
+% 
+% author: Alexander Freytag
+% date  : 04-03-2014 ( dd-mm-yyyy )
+
+    if ( ~isempty(myStruct) && isfield(myStruct, myField) && ~isempty( myStruct.( myField ) ))
+        myOut = myStruct.( myField );
+    else
+        myOut = myDefault;
+    end
+end