error in array of struct matlab - matlab

I want to train data on various labels using svm and want svm model as array of struct. I am doing like this but getting the error:
Subscripted assignment between dissimilar structures.
Please help me out
model = repmat(struct(),size);
for i=1:size
model(i) = svmtrain(train_data,labels(:,i),'Options', options);
end

A structure array in MATLAB can only contain structures with identical fields. By first creating an array of empty structures1 and then trying to fill it with SVMStruct structures, you try to create a mixed array with some empty structures, and some SVMStruct structures. This is not possible, thus MATLAB complains about "dissimilar structures" (not-equal structures: empty vs. SVMStruct).
To allocate an array of structs, you will have to specify all fields during initialization and fill them all with initial values - which is rather inconvenient in this case. A very simple alternative is to drop this initialization, and run your loop the other way around2,3:
for ii=sizeOfLabels:-1:1
model(ii) = svmtrain(train_data,labels(:,ii),'Options', options);
end
That way, for ii=sizeOfLabels, e.g. ii=100, MATLAB will call model(100)=..., while model doesn't exist yet. It will then allocate all space needed for 100 SVMStructs and fill the first 99 instances with empty values. That way you pre-allocate the memory, without having to worry about initializing the values.
1Note: if e.g. size=5, calling repmat(struct(),size) will create a 5-by-5 matrix of empty structs. To create a 1-by-5 array of structs, call repmat(struct(),1,size).
2Don't use size as a variable name, as this is a function. If you do that, you can't use the size function anymore.
3i and j denote the imaginary unit in MATLAB. Using them as a variable slows the code down and is error-prone. Use e.g. k or ii for loops instead.

Related

Simulink: Use Enumeration As Index

I feel like this is something that'd be absurdly easy in C# but is impossible in Simulink. I am trying to use an enumerated value as an array index. The trick is: I have an array that is sized for the number of elements in the enumeration, but their values are non-contiguous. So I want the defined enumeration and Simulink code to read the value at A(4). Obviously, it will instead read A(999). Any way to get the behavior I'm looking for?
classdef Example < Simulink.IntEnumType
enumeration
value1 (1)
value2 (2)
value13 (13)
value999 (999)
end
end
// Below in Simulink; reputation is not good enough to post images.
A = Data Store Memory
A.InitialValue = uint16(zeros(1, length(enumeration('Example'))))
// Do a Data Store Read with Indexing enabled; Index Option = Index vector (dialog)
A(Example.value999)
After a weekend of experimentation, I came up with a working solution: using a Simulink Function to call a MATLAB function that searches for the correct index using the "find" command. In my particular instance, I was assigning the data to Data Store Memory, so I was able to just pass the enumeration index and a new value to these blocks, but you could just as easily have a single input block that spits out the requested index. (My reputation is still too low to post pictures, so hopefully my textual descriptions will suffice.)
Data Store Memory 'A': Data type = uint16, Dimensions = length(enumeration('RegisterList'))
Simulink Function: SetValueA(ExampleEnum, NewValue)
--> MATLAB Function: SetA_Val(ExampleEnum, NewValue)
--> function SetModbusRegister(RegisterListEnum, NewValue)
global A;
if(isa(ExampleEnum, 'Example'))
A(find(enumeration('Example') == ExampleEnum, 1)) = NewValue;
end
From there, you use the Function Caller blocks in Simulink with the "Function prototype" filled in with "SetValueA(ExampleEnum,NewValue)" anywhere you wish to set this data. The logic would get more complicated if you wished to use vectors and write multiple values at once, but this is at least a starting point. It should just be a matter of modifying the Simulink and MATLAB functions to allow vector inputs and looping through those inputs in the MATLAB function.
EDIT 1
Slight update: If your MATLAB function is set up such that you cannot use variable-length vectors in it, just replace the "find" function with the "ismember" function. Using a scalar in ismember always returns a scalar, and the MATLAB compiler won't complain about it.

Is it possible to create a sub-array without using additional memory on Matlab?

Well, I am trying to implement an algorithm on Matlab. It requires the usage of a slice of an high dimensional array inside a for loop. When I try to use the logical indexing, Matlab creates an additional copy of that slice and since my array is huge, it takes a lot of time.
slice = x(startInd:endInd);
What I am trying to do is to use that slice without copying it. I just need the slice data to input a linear operator. I won't update that part during the iterations.
To do so, I tried to write a Mex file whose output is a double
type array and whose size is equal to the intended slice data size.
plhs[0] = mxCreateUninitNumericMatrix(0, 0, mxDOUBLE_CLASS,mxREAL); % initialize but do not allocate any additional memory
ptr1 = mxGetPr(prhs[0]); % get the pointer of the input data
Then set the pointer of the output to the starting index of the input data.
mxSetPr(plhs[0], ptr1+startInd);
mxSetM(plhs[0], 1);
mxSetN(plhs[0], (endInd-startInd)); % Update the dimensions as intended
When I set the starting index to be zero, it just works fine. When I try to give
other values than 0, Mex file compiles with no error but Matlab crashes when the Mex function is called.
slice = mex_slicer(x, startInd, endInd);
What might be the problem here?
The way you assign the data pointer to the array, it means that MATLAB will attempt to free that memory when the array is deleted or has something else assigned to it. Attempting to call free using a pointer that was not obtained by malloc will cause a crash.
Unfortunately, MATLAB does not support "views", arrays that point at parts of a different array. So there is no way to do what you want to do.
An alternative solution would be to:
store your data differently, so that it doesn't take as much time to index (e.g. in smaller arrays)?
perform all your computations in C or C++ inside a MEX-file, where you can very simply point at sub-ranges of a larger data block.
See this FEX submission on creating MATLAB variables that "point" to the interior data of an existing variable. You can either do it as a shared data copy which is designed to be safe (but incurs some additional overhead), or as an unprotected direct reference (faster but risks crashing MATLAB if you don't clear it properly).
https://www.mathworks.com/matlabcentral/fileexchange/65842-sharedchild-creates-a-shared-data-copy-of-a-contiguous-subsection-of-an-existing-variable

how to store and retrieve multiple decision trees in matlab

I have a for loop that generates a single decision tree each time and later on in the program I need to apply all the decision trees to the testing data (the decision trees are NOT combined in an ensemble). I tried to store them in an array of structures but when I am applying them to the test data I have the following error:
(Undefined function 'predict' for input arguments of type 'struct'.).
I know that the tree generated is an object but how you can store and retrieve multiple objects in MATLAB?
Usually the arrays of objects would do (the only thing is that the class needs a default constructor in order to allocate the space).
So, the safest way is to use a cell array. The code would be something along the lines of:
%'"N" is the size of your problem'
dtrees = cell(1,N);
for k = 1:N
%'Create the decision tree "obj"'
%'...'
dtrees{k} = obj;
end;
%'...'
%'Later iterate in the cell array'
for k = 1:N
obj = dtrees{k};
%'Now do stuff with "obj"'
%'...'
end;
You use cell arrays.
http://uk.mathworks.com/help/matlab/matlab_prog/create-a-cell-array.html
they can store pretty much whatever.

Preallocating a structure with variables of different names, size and type

I am going to use an algorithm in a for loop as an iteration loop. I know that some of the calculations can be done once and the their results can be used as necessary inputs for the algorithm in the for loop so in this way there is no need to calculate the same things in each iteration. To do so, I calculate them once and put them in a structure.
I use structure since I have many variables to be kept to be used in the for loop and their name and size are different. I put them in the structure with the same name for example:
out.A = A;
out.myvector = myvector;
out.s = s;
out.Hx_l = Hx_l;
and so on. some of them are matrices, some of them cubes or variables with a forth dimension and some of them are cells.
Is there any way to preallocate this kind of structure?
You could initialise the structure the following way:
out = struct('A',[],'myvector',[],'s',[],'Hx',[]);
When you assign the variables afterwards, the structure fields will be already created. Usually the contents are not initialised upfront. Quoting Loren:
How important is it to initialize the contents of the struct. Of
course it depends on your specifics, but since each field is its own
MATLAB array, there is not necessarily a need to initialize them all
up front. The key however is to try to not grow either the struct
itself or any of its contents incrementally.

What is the syntax for declaring a global 2-dimensional array in MATLAB?

What is the syntax for declaring a global 2-dimensional array in MATLAB?
I want the array to be blank, or uninitialized. That is, I want to be able to initialize it to some value later on using a for-loop. All the examples I have come across so far consist of initializing the array when it is declared. I find this rather tedious because my array might have to be a large one.
Thanks.
Declare a variable as global first before using it:
global my_glob_var;
MATLAB doesn't really support the concept of 'uninitialised' variables, but you can create an array of NaNs (not a number) to indicate that each value hasn't been assigned yet. The arguments to the nan function indicate the size of the NaN array you wish to create:
my_glob_var = nan(200, 200)
There are other similar functions in case you wish to initialise arrays of zeros, ones, Inf etc.
Then inside the functions you want to use it in, declare it as global again:
function my_function
global my_glob_var % allows this function to use the global variable
my_glob_var % outputs the variable to command
As an aside, you note that you will "initialise it to some value later using a for-loop". Depending on how you are initialising the array, there may be a vectorised way to achieve this (i.e. without using a for-loop). Vectorised operations are usually much quicker in MATLAB.