Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function handle formats in Octave

A function handles in Octave is defined as the example below.

f = @sin;

From now on, calling function f(x) has the same effect as calling sin(x). So far so good. My problem starts with the function below from one of my programming assignments.

function sim = gaussianKernel(x1, x2, sigma)

The line above represents the header of the function gaussianKernel. This takes three variables as input. However, the call below messes up my mind because it only passes two variables and then three while referring to gaussianKernel.

model = svmTrain(X, y, C, @(x1, x2) gaussianKernel(x1, x2, sigma));

Shouldn't that be simply model = svmTrain(X, y, C, @gaussianKernel(x1, x2, sigma));? What is the difference?

like image 875
André Gomes Avatar asked Mar 09 '23 05:03

André Gomes


2 Answers

You didn't provide the surrounding code, but my guess is that the variable sigma is defined in the code before calling model = svmTrain(X, y, C, @(x1, x2) gaussianKernel(x1, x2, sigma));. It is an example of a parametrized anonymous function that captures the values of variables in the current scope. This is also known as a closure. It looks like Matlab has better documentation for this very useful programming pattern.

The function handle @gaussianKernel(x1, x2, sigma) would be equivalent to @gaussianKernel. Using model = svmTrain(X, y, C, @gaussianKernel(x1, x2, sigma)); might not work in this case if the fourth argument of svmTrain is required to be a function with two input arguments.

like image 129
horchler Avatar answered Mar 10 '23 20:03

horchler


The sigma variable is already defined somewhere else in the code. Therefore, svmTrain pulls that value out of the existing scope.

The purpose of creating the anonymous function @(x1, x2) gaussianKernel(x1, x2, sigma) is to make a function that takes in two arguments instead of three. If you look at the code in svmTrain, it takes in a parameter kernelFunction and only calls it with two arguments. svmTrain itself is not concerned with the value of sigma and in fact only knows that the kernelFunction it is passed should only have two arguments.

An alternate approach would have been to define a new function:

function sim = gKwithoutSigma(x1, x2)
    sim = gaussianKernel(x1, x2, sigma)
endfunction

Note that this would have to be defined somewhere within the script calling svmTrain in the first place. Then, you could call svmTrain as:

model = svmTrain(X, y, C, @gKwithoutSigma(x1, x2))

Using the anonymous parametrized function prevents you from having to write the extra code for gKwithoutSigma.

like image 24
djsavvy Avatar answered Mar 10 '23 18:03

djsavvy