Adding elements to a MLMultiArray - swift

I have a CoreML model (created using TF and converted to CoreML). For it
input is: MultiArray (Double 1 x 40 x 3)
output is: MultiArray (Double)
I will be getting these [a,b,c] tuples and need to collect 40 of them before sending into to the model for prediction. I am looking through the MLMultiArray documentation and am stuck. May be because of I am new to Swift.
I have a variable called modelInput that I want to initialize and then as the tuples come in, add them to the modelInput variable.
modelInput = MLMultiArray(shape:[1,40,3], dataType:MLMultiArrayDataType.double))
The modelInput.count is 120 after this call. So I am guessing an empty array is created.
However now I want to add the tuples as they come in. I am not sure how to do this.
For this I have a currCount variable which is updated after every call. The following code however gives me an error.
"Value of type 'UnsafeMutableRawPointer' has no subscripts"
var currPtr : UnsafeMutableRawPointer = modelInput.dataPointer + currCount
currPtr[0] = a
currPtr[1] = b
currPtr[2] = c
currCount = currCount + 3
How do I update the multiArray?
Is my approach even correct? Is this the correct way to create a multi array for the prediction input?
I would also like to print the contents of the MLMultiArray. There doesn't appear to be any helper functions to do that though.

You can use pointers, but you have to change the raw pointer into a typed one. For example:
let ptr = UnsafeMutablePointer<Float>(OpaquePointer(multiArray.dataPointer))
ptr[0] = a
ptr[1] = b
ptr[2] = c

I figured it out. I have to this --
modelInput[currCount+0] = NSNumber(floatLiteral: a)
modelInput[currCount+1] = NSNumber(floatLiteral: b)
modelInput[currCount+2] = NSNumber(floatLiteral: c)
I cannot use the raw pointer to access elements.

Related

How to create a struct or type from a dictionary in Julia?

I have imported a bunch of data from a .mat file (MATLAB format) and they come as dictionarys, but it's kind of anoying using them, so I wanted to pass it for a struct. I know I can do this:
using MAT
struct model
trans
means
vars
end
vars = matread("data.mat")
hmm1=model(vars["hmm1"]["trans"],vars["hmm1"]["means"],vars["hmm1"]["vars"])
Is there a way to do this without typing every key of the dictionay?
There's probably no way to avoid directly accessing the relevant keys of your dictionary. However, you can simplify your life a little by making a custom Model constructor that takes in a Dict:
using MAT
struct Model
trans
means
vars
end
function Model(d::Dict)
h = d["hmm1"]
Model(h["trans"], h["means"], h["vars"])
end
d = matread("data.mat")
Model(d)
If you're only worried about the dot-access syntax à la hmm1.means, you could instead use a NamedTuple:
julia> vars = Dict("hmm1"=>Dict("trans"=>1, "means"=>2, "vars"=>3)) ;
julia> hmm1 = (; (Symbol(k) => v for (k,v) in vars["hmm1"])...)
(trans = 1, vars = 3, means = 2)
julia> hmm1.means
2
(Taken and adapted from Julia discourse: How to make a named tuple from a dictionary?.)

Create array of tf objects in Matlab

If I wanted to create an array of specified class I would use an approach like this. So creating an array of int looks like this:
Aint = int16.empty(5,0);
Aint(1) = 3;
And it works fine. Now I want to create an array of tf class objects. My approach was similar:
L = tf.empty(5, 0);
s = tf('s');
L(1) = s;
This gives me an error:
Error using InputOutputModel/subsasgn (line 57)
Not enough input arguments.
Error in tf_array (line 6)
L(1) = s;
I also made sure to display class(s) and it correctly says it's tf. What do I do wrong here?
As usual, the MATLAB documentation has an example for how to do this sort of thing:
sys = tf(zeros(1,1,3));
s = tf('s');
for k = 1:3
sys(:,:,k) = k/(s^2+s+k);
end
So, the problem likely is that the indexing L(1) is wrong, it needs to be L(:,:,1).
Do note that tf.empty(5, 0) is instructing to create a 5x0 array (i.e. an empty array). There is no point to this. You might as well just skip this instruction. Because when you later do L(:,:,1), you'll be increasing the array size any way (it starts with 0 elements, you want to assign a new element, it needs to reallocate the array). You should always strive to create the arrays of the right size from the start.

convert number string into float with specific precision (without getting rounding errors)

I have a vector of cells (say, size of 50x1, called tokens) , each of which is a struct with properties x,f1,f2 which are strings representing numbers. for example, tokens{15} gives:
x: "-1.4343429"
f1: "15.7947111"
f2: "-5.8196158"
and I am trying to put those numbers into 3 vectors (each is also 50x1) whose type is float. So I create 3 vectors:
x = zeros(50,1,'single');
f1 = zeros(50,1,'single');
f2 = zeros(50,1,'single');
and that works fine (why wouldn't it?). But then when I try to populate those vectors: (L is a for loop index)
x(L)=tokens{L}.x;
.. also for the other 2
I get :
The following error occurred converting from string to single:
Conversion to single from string is not possible.
Which I can understand; implicit conversion doesn't work for single. It does work if x, f1 and f2 are of type 50x1 double.
The reason I am doing it with floats is because the data I get is from a C program which writes the some floats into a file to be read by matlab. If I try to convert the values into doubles in the C program I get rounding errors...
So, (after what I hope is a good question,) how might I be able to get the numbers in those strings, at the right precision? (all the strings have the same number of decimal places: 7).
The MCVE:
filedata = fopen('fname1.txt','rt');
%fname1.txt is created by a C program. I am quite sure that the problem isn't there.
scanned = textscan(filedata,'%s','Delimiter','\n');
raw = scanned{1};
stringValues = strings(50,1);
for K=1:length(raw)
stringValues(K)=raw{K};
end
clear K %purely for convenience
regex = 'x=(?<x>[\-\.0-9]*),f1=(?<f1>[\-\.0-9]*),f2=(?<f2>[\-\.0-9]*)';
tokens = regexp(stringValues,regex,'names');
x = zeros(50,1,'single');
f1 = zeros(50,1,'single');
f2 = zeros(50,1,'single');
for L=1:length(tokens)
x(L)=tokens{L}.x;
f1(L)=tokens{L}.f1;
f2(L)=tokens{L}.f2;
end
Use function str2double before assigning into yours arrays (and then cast it to single if you want). Strings (char arrays) must be explicitely converted to numbers before using them as numbers.

matlab How to use a textstring as input parameter in functions

I would like to use a dataset filename "AUDUSD" in several functions. It would be easier for me, just to change the filename "AUDUSD" to a more general name like "FX" and then using the abbreviation "FX" in other_matlab functions, e.g. double(). But matlab does not know the name "FX" (that should be assigned to the dataset "AUDUSD") in the code below... Any suggestions?
CODE:
FX = 'AUDUSD';
load(FX); %OKAY !!! FX works as input to open file AUDUSD!
Svars = {'S_bid','S_offer'};
Fvars = {'F_bid','F_offer'};
vS = double(FX,Svars); % FX does NOT work as input for the file AUDUSD
There is no double() function that accepts multiple cell arrays as arguments (this is what happens when you call double(FX,Svars)).
If you call double(FX), then each character in FX is interpreted for its ASCII value and then cast to double. So you get [ 65.0 85.0 68.0 85.0 83.0 68.0 ]. This is the behavior for the double() function if you provide a vector: each individual value in the vector is cast to double.
You'd have to provide more details on what you're trying to accomplish to give any more suggestions.
I have a different example, maybe you will better understand my point. The key work I would like to process is as follows:
I have got a folder with "dataset" files. I would like to loop through this folder, entering in any datasetfile, extracting the 2nd and 3rd column of each dataset file, and constructing only ONE new datasetfile with all 2nd and 3rd columns of the datasetfiles.
One problem is that the size of the datasetfiles are not the same, so I tried to translate a datasetfile into a double-matrix and then consolidate all double matrices into ONE double matrx.
Here my code:
folder_string = 'Diss_Data/Raw';
FolderContent = dir(folder_string);
No_ds = numel(FolderContent);
for i = 1:No_ds
if isdir(FolderContent(i).name)==0
file_string = FolderContent(i).name;
file_path = strcat(folder_string,'/',file_string)
dataset_filename = file_string(1:6);
load(file_path); %loads the suggested datasetfile; OKAY
M = double(dataset_filename);% returns an ASCII code number; WRONG; should transfer the datasetfile into a matrix M
vS = M(:,2:3);
%... to be continued
end
end

Using "who" variable list to open cell array

I am trying to cycle through a list of variables I have say 30+ and calculate the maximum and minimum value for each column in each variable. Save this in a new array and then export to excel.
My thoughts were to use the who function to create an array with the name of all variables which are present. Then cycling through each one using a for loop after working out the size of the array which was created. This works fine, however when I try and use the string to reference the array it does not work.
I will add in the code which I have written hopefully someone will be able to come up with an easy solution :).
variable_list = who
cell2 = input('What cell size do you want to look at? ');
STARTcell = input('What was the start cell size? ');
[num_variables, temp] = size(variable_list);
for va = 1:num_variables
variable = variable_list{va}
[max_value, max_index] = max(variable{cell2/STARTcell})
[min_value, min_index] = min(variable{cell2/STARTcell})
format_values{va} = vertcat(max_values, max_index, min_value, min_index);
end
The variables I am looking at are arrays which is why I use the cell2/STARTcell to reference them.
You need to use the eval() function to be able to get the value of a variable corresponding to a string. For example:
a = 1;
b = 2;
variable_list = who;
c = eval(variable_list{2});
results in c being 2. In your code, the following line needs to change from:
variable = variable_list{va}
to:
variable = eval(variable_list{va});
resulting in variable having the value of the variable indicated by the string variable_list{va}. If variable is of cell type, then you should be fine, otherwise you may have to revise the next two lines of code as well because it seems that you are trying to access the content of a cell.