Suppose I have a 1000x2x10x10 matrix, and currently I put them into two cell arrays by the following code,
for i=1:1000
tmp = seqs(i,1,:);
patterns{i} = tmp(:);
tmp = seqs(i,2,:);
labels{i} = tmp(:);
end
The purpose of patterns{i} = tmp(:) and labels{i} = tmp(:) is to flatten the matrix. My question is that, is it possible to simplify the code like patterns{i}=seqs(i,1,:)(:)? I tried this one but Matlab does not allow this, and that's why I currently have to use a temporary variable tmp.
I'll just give you 3 ways to do this. All of which work.
The first is the one I normally use is to have a function on my computer called vec
function out = vec(in)
out = in(:);
end
and then you can use it via
patterns{i} = vec(seqs(i,1,:));
Then you can call this function and it allows for more streamlined code. The second is reshape mentioned in the comments
patterns{i}=reshape(seqs(i,1,:),[],1);
I typically don't recommend reshape for these types of problems because it tends to fail if you aren't careful. The last is to use squeeze and transpose.
patterns{i} = squeeze(seqs(i,1,:))';
Personally, I prefer the first because it makes my code look nicer.
Related
I have a large matrix, and I need to extract a small matrix taken from a sliding window which runs all over the large matrix, but during the operations the content of the extracted matrix does not change, so I'd like to extract the submatrix without creating a new copy but instead just acts like a C pointer that points to a portion of the large matrix. How can I do this? Please help me, thank you very much :)
I did some benchmarking to test if not using an explicit temporary matrix is faster, and it's probably not:
function move_mean(N)
M = randi(100,N);
window_size = [50 50];
dir_time = timeit(#() direct(M,window_size))
tmp_time = timeit(#() with_tmp(M,window_size))
end
function direct(M,window_size)
m = zeros(size(M)./2);
for r = 1:size(M,1)-window_size(1)
for c = 1:size(M,2)-window_size(2)
m(r,c) = mean(mean(M(r:r+window_size(1),c:c+window_size(2))));
end
end
end
function with_tmp(M,window_size)
m = zeros(size(M)./2);
for r = 1:size(M,1)-window_size(1)
for c = 1:size(M,2)-window_size(2)
tmp = M(r:r+window_size(1),c:c+window_size(2));
m(r,c) = mean(mean(tmp));
end
end
end
for M at size 100*100:
dir_time =
0.22739
tmp_time =
0.22339
So it's seems like using a temporary variable only makes your code readable, not slower.
In this answer I describe what is the 'best' solution in general. For this answer I define 'best' as most readable without a significant performance hit. (Partially shown by the existing answer).
Basically there are 2 situations that you may be in.
1. You use your submatrix several times
In this situation the best solution in general is to create a temporary variable containing the submatrix.
A = M(rmin:rmax, cmin:cmax)
There may be ways around it (defining a function/anonymous function that indexes into the matrix for you), but in general that won't make you happy.
2. You use your submatrix only 1 time
In this case the best solution is typically exactly what you referred to in the comments:
M(rmin:rmax, cmin:cmax)
A specific case of using the submatrix only 1 time, is when it is passed once to a function. Of course the contents of the submatrix may be used in that function several times, but that is irrelevant.
my code inside a parfor loop is getting longer and longer and I would like to split it up. Having parts of the code saved in different script files seems logical and very attractive and since it doesn't change anything except where the code is saved it seems like it should work. But it doesn't.
I get the usual "Transparency violation error".
The problem seems typical but I did not find this question asked or answered anywhere.
Below is a small working example.
(Yes, this could be made as a function. But in case of many more Input and Output variables this becomes really ugly imo and probably also slower due to communicating the arguments)
C = NaN(10,1); %Result vector
parfor loop = 1:10
a = 1;
b = 2;
MFile_Test %Run the m-file which contains only one line:
% c = a + b;
C(loop)=c;
end
the MFile_Test is a script just containing the line one line c = a + b.
I am beginning to understand why parallel computing has an issue here but not how to solve it. Since this would be possible without any problem if I just had the line c = a + b inside the parfor file I cannot belief there is no simple way to solve this (e.g. in the worst case something like tell matlab to load the text from another file and run it as code here and now).
If there are alternative ways to structure my code without using the script files (and, if possible, without using only functions ;)) I would appreciate such comments as well, of course.
Many thanks,
Daniel
parfor has various constraints that make using scripts inside the loop generally a bad option. The main constraint is that the text of the parfor loop must be analysable to see what new variables might be created - this is referred to as "transparency" in the doc. Try using a function instead.
So, for other people or for possible hints to improve, here is how I did it with a function and loading the input variables.
a = 1;
b = 2;
save('Input.mat');
pseudo_input = NaN;%for the function
D= NaN(10,1);%result vector
parfor loop = 1:10
D(loop) = Parfor_Fun_Test(pseudo_input);
end
And the function looks like this:
function d = Parfor_Fun_Test(InputArgs)
load('Input.mat');
d = a + b ;
end
I would have preferred to also save the output, i.e. 'd', within the function and then load it in the parfor loop, but that causes an error, probably because the same file is accessed for loading and saving at the same time by different parallel workers. So this will have to do it. (This can apparently be circumvented by saving under a different name each time, but that would probably really slow down the code.)
By the way, it seems that using cells or structures is slightly faster, but then I have to write the code inside the function as this, I assume:
d = Input.a + Input.b ;
which is more ugly and more work. So I use the save and load method as above for now.
This question already has answers here:
Dynamic variables matlab
(2 answers)
Closed 8 years ago.
I was wondering how I can use a for loop to create multiple matrix when given a certain number.
Such as If 3 was given I would need three matricies called: C1, C2 and C3.
k = 3
for i = 1:K
C... = [ ]
end
Not sure how to implement this.
The first thing coming in mind is the eval function mentioned by Dennis Jaheruddin, and yes, it is bad practice. So does the documentation say:
Why Avoid the eval Function?
Although the eval function is very powerful and flexible, it not
always the best solution to a programming problem. Code that calls
eval is often less efficient and more difficult to read and debug than
code that uses other functions or language constructs. For example:
MATLABĀ® compiles code the first time you run it to enhance performance for future runs. However, because code in an eval
statement can change at run time, it is not compiled.
Code within an eval statement can unexpectedly create or assign to a variable already in the current workspace, overwriting existing
data.
Concatenating strings within an eval statement is often difficult to read. Other language constructs can simplify the syntax in your
code.
The "safer" alternative is the function assignin:
The following will do exactly what you want:
letter = 'C';
numbers = 1:3;
arrayfun(#(x) assignin('base',[letter num2str(x)],[]),numbers)
I know cases where you need to create variables likes this, but in most cases it is better and more convenient to use cell arrays or structs.
The trick is to use a cell array:
k=3
C=cell(k,1)
for t=1:k
C{t}= rand(t)
end
If each matrix is of equal size, you would probably just want a three dimensional matrix rather than a cell array.
You now have one cell array,but can access the matrices like this:
C{2} %Access the second matrix.
The use of eval is almost inevitable in this case:
k = 3;
for i = 1:k
eval(sprintf('C%d = [];', i));
end;
Mind you that generating variable names for data storage rather than indexing them (numerically -- see the solution of Dennis Jaheruddin based on cell arrays -- or creating a dynamic struct with named fields that store the data) is almost always a bad idea. Unless you do so to cope up with some weird scripts that you don't want to / cannot modify that need some variables already created in the global workspace.
I'm writing a function to get the cosine of a given array. It works but I'm presently using a loop in order to iterate over each value in the array whereas I'm assured that it can be vectorised.
Presently the code is:
for i = 1:numel(x)
cos(i) = (sum(((-1).^(0:n)).*(x(i).^(2*(0:n)))./(factorial(2*(0:n)))));
end
and I can't for the life of me think how it vectorises, so any help would be appreciated.
EDIT: Here is the full function http://pastebin.com/n1DG6nUv
2nd EDIT: link updated with new code that doesn't overwrite cos.
Here's one way using bsxfun and gamma:
v = 0:n;
fcos = zeros(size(x));
fcos(:) = sum(bsxfun(#times,bsxfun(#power,x(:),2*v),(-1).^v./gamma(2*v+1)),2)
In the spirit of learning, note that you have several issues with the code in your question. First, you don't preallocate memory. Second, you're overwriting the cos function, which is probably not a good idea. Also, I believe that using gamma(n+1) instead of factorial(n) will be faster. Finally, there are many unnecessary parentheses that make the code hard to read.
I have some code like this in my matlab function:
for i = init:end
a= [a, char(zeros(size(a))]
a= func(a)
a = a(a~=0)
end
So, in each step of the loop, you first double the size of a, apply some random function to it, and then remove everything that is a zero.
Now, I want to run coder on this to eventually make it into c code. Of course, it gives me allocation errors.
Allowing dynamically allocated arrays doesn't help. I can't simply use different names for my variables either because it is in a for loop.
This may come a year late however something like:
function a = foobar(init,ub)
coder.varsize('a',[1,Inf]);
a = 1;
for i = init:ub
a = [a, ones(size(a))];
a = sin(a);
a = a(a~=0);
end
>> codegen foobar -args {1,1} -report
works for me in R2014a.
When you are trying to grow an array, it may be necessary to use coder.varsize in order to tell MATLAB Coder that the array is going to change size. In many cases MATLAB Coder can figure this out without using coder.varsize so it is best to try without it first and then add it in if errors are encountered.