knn classification 10 fold implement and sorting - matlab

i have 8 feature from a mat file
each of this feature divided 4 part (X_train , Y_train , X_test,Y_test)
for 10 times randomly obtained this parameter
now i should classify this feature according KNN
my code is here
kk=7;
bb=1;
mdl1= ClassificationKNN.fit([X1_train{bb};X2_train{bb};X3_train{bb};X4_train{bb};X5_train{bb};X6_train{bb};X7_train{bb};X8_train{bb};X9_train{bb};X10_train{bb};X11_train{bb};X12_train{bb}],[Y1_train{bb};Y2_train{bb};Y3_train{bb};Y4_train{bb};Y5_train{bb};Y6_train{bb};Y7_train{bb};Y8_train{bb};Y9_train{bb};Y10_train{bb};Y11_train{bb};Y12_train{bb}],'NumNeighbors',kk);
.
.
.
bb=10;
mdl10= ClassificationKNN.fit([X1_train{bb};X2_train{bb};X3_train{bb};X4_train{bb};X5_train{bb};X6_train{bb};X7_train{bb};X8_train{bb};X9_train{bb};X10_train{bb};X11_train{bb};X12_train{bb}],[Y1_train{bb};Y2_train{bb};Y3_train{bb};Y4_train{bb};Y5_train{bb};Y6_train{bb};Y7_train{bb};Y8_train{bb};Y9_train{bb};Y10_train{bb};Y11_train{bb};Y12_train{bb}],'NumNeighbors',kk);
as you seen this functions repeat 10 times for evaluate the 10 mdl
in the following i write this code to simplify the project
for j=1:10
for h=1:12
mdl{j}{h}=ClassificationKNN.fit([X_train{j}{h}],[Y_train{j}{h}]);
end
end
this code work proerly without (mdl{j}{h}) but if this sentence is used i have this error message ((Cell contents assignment to a non-cell array object))
anybode know what shall i do to fix this problem
thanks

at first you should define the mdl variable size
mdll= cell(10, 8);
then form this for loop
for j=1:10
mdll{j}= ClassificationKNN.fit([X_train{j}{1};X_train{j}{2};X_train{j}{3};X_train{j}{4};X_train{j}{5};X_train{j}{6};X_train{j}{7};X_train{j}{8};X_train{j}{9};X_train{j}{10};X_train{j}{11};X_train{j}{12}],[Y_train{j}{1};Y_train{j}{2};Y_train{j}{3};Y_train{j}{4};Y_train{j}{5};Y_train{j}{6};Y_train{j}{7};Y_train{j}{8};Y_train{j}{9};Y_train{j}{10};Y_train{j}{11};Y_train{j}{12}],'NumNeighbors',kk);
end
i checked it and work correctly

Related

“Index exceeds the number of array elements” for piecewise function

I am trying to create piecewise functions V(t), D(t).
I try to find the piecewise, then I use the piecewise of t to construct functions and plot them.
But it shows "Index exceeds the number of array elements. Index must not exceed 51".
How can I fix it?
I put my code below and I really hope someone can answer it. Thaks!
z=zeros(1,50);
p_i=zeros(1);
p=0.023;
for i=1:50
z(i)=rand;
if z(i)>p
p_i(end+1)=i+z(i);
end
end
n=numel(p_i);
V=zeros(1,n);
w=zeros(1,n);
D=zeros(1,n);
V_op=zeros(1,n);
%get the number of pi
sigma_w0=0.2;
Q=5;
P=2;
Q_op=4;
for i=1:n
if i>1
w(i)=w(i-1)+normrnd(0,sigma_w0);
V(i)=Q*w(i);
D(i)=P*w(i);
V_op(i)=Q_op*w(i);
else
w(1)=2;
V(i)=Q*w(i);
D(i)=P*w(i);
V_op(i)=Q_op*w(i);
end
end
t=0:0.0002:50;
V_p=zeros(size(t));
D_p=zeros(size(t));
V_opp=zeros(size(t));
for m=1:length(t)
t(m)>=p_i(i)& t(m)<p_i(i+1)
V_p(m)=V(i);
D_p(m)=D(i);
V_opp(m)=V_op(i);
end
Yes, if you run your code you'll see it is functional before the last for loop since it is evaluating that in the 1 to 50 range (m=1:length(t)) but your line is printing 51 values so you need to check only the next part and reorganize the idea:
t(m)>=p_i(i)& t(m)<p_i(i+1)
If you print the first part (t(m)>=p_i(i)) it is okay, but check the other part and you'll notice the error. Maybe you can print all your results moving your increment value (+1) and prevent it from exceeding 1 to 51.

Unrecognized function or variable in parfor in MATLAB

I am a beginner in MATLAB software and I use MATLAB online .The problem is in initializing a variable called 'estModel' in a parallel loop . I want to use parallel processing because the calculations take a long time to complete but this problem occurs when I use 'threads' in parpool instead of 'local' . In 'local' mode this problem does not exist and the code is executed correctly and the results are correct . But in the case of 'threads', the variable 'estModel' is not initialize in the parfor loop , and give this error : Unrecognized function or variable 'estModel' . In 'local' mode the number of workers are 2 but in 'threads' mode the number of workers are 8 . So I use 'threads' instead of 'local' . I do not know about parpool structure completely . Is there a problem in this part ( parpool : local or threads or ... and chooses 'threads' based on the number of workers ) ? Finally the three variables 'kh', 'model' and 'DATA' are completely initializing before parallel loop and the variable 'model' uses the arima function .
Can anyone help me to solve this problem?
code :
clear all;
close all;
clc;
DATA=xlsread('test'); % The data for modeling and forecasting is read from an excel file called test, which is a column vector.
size_of_DATA=length(DATA);
p=20; % nonseasonal autoregressive polynomial degree range in arima model.
q=10; % nonseasonal moving average polynomial degree range in arima model.
D=2; % degree of nonseasonal integration range in arima model.
h=0; % counter
for k=1:D
for j=1:q
for i=1:p
if i+j+k-2<=size_of_DATA
h=h+1;
model(h)=arima(i-1,k-1,j-1);
end
end
end
end
poolobj=parpool('threads');
parfor i=1:h
estModel(i)=estimate(model(i),DATA);
end
delete(poolobj);
The excel file called 'test' is an arbitrary time series that is a column vector with 500 datas (of course, its length can vary). you can use file in this link for test : ln5.sync.com/dl/9e3913140/ctiyajcx-mgmnis6z-8mgyaigq-p2a9hpxu

How to do a 10-fold cross validation without using built-in function in MATLAB?

I try to do a 10 folds cross validation without using built-in function to train and recognize digit from 0-9 I have sample of 500 picture(50 for each digit to train and test.)
I try implement the answer MATLAB: 10 fold cross Validation without using existing functions and other websites but it didn't help that much. Mostly because I'm new to MATLAB so I don't know much about what I should do to tweak it.
This is the code I have so far.
c=zeros(10,size(x,2),size(x,3));
K=10;
k=10;
test= 1:50/K;
for fold =1:K
if(test(1)~=1)
train = x(1:test(1)-1,:,:);
if (test(5) ~=50)
train=[train ; x(test(end):50,:,:)];
end
else
train = x(test(1):50,:,:);
end
test = test+ones(1,50/K)*50/K;
end
for i =0:9
test=test+50/K*ones(1,5);
c(i+1,:,:)=cal_likelihood(x(1+i*50:50+i*50,:,:),50/k*(k-1));
end
Variable explanation
x is the 500x28x28 double where it keeps all 500 digit picture.
test is a test set.
train is a training set.
In order to do 10 folds cross validation I need to change training set like
1st fold : 1:5 for test,6:45 for train
2nd fold : 6:10 for test,1:5 11:50 for train and so on
The problem is I don't know how to shift the training set from one set to another like from 6:45 to 1:5 and 11:50. or Can I write a better loop than this?
PSS. If someone who answer this don't mind What does 500x28x28 double actually mean.
There are a few ways you could write this, some of which are easier to understand than others. Matlab is quite nice to write in as while expressions such as 1:3 evaluate to [1,2,3], the expression 1:0 evaluates to the empty set. So, it is very straightforward to generate the sets without having to use if statements.
I'd start off the loop as:
samples_per_digit=50;
block_sze=samples_per_digit/K;
for fold =1:K
test_ind = 1+(fold-1)*block_sze:fold*block_sze;
train_ind = [1:(fold-1)*block_sze, (fold*block_sze+1):samples_per_digit];
for i=0:9
train=x(train_ind+i*samples_per_digit,:,:);
test=x(test_ind+i*samples_per_digit,:,:);
% Perform training and validation in here for this fold of the digit i
You can verify that test_ind and train_ind correspond to the subsets of blocks of training and validation that you need. It is only in the innermost loop that these translate to the matrices corresponding to the digit images, using the value of i to compute the offset. Of course, if you wish, you can swap the order of the loops, computing all of the folds for a single digit. It all depends on how you wish to store your results.

Structure array changes size when passed to a reduction function in the parfor loop Matlab?

I ran into a weird problem when I used structure arrays inside a parfor loop. Below is my main function:
comm_struct=struct('field1',0,'field2',zeros(10,1),'field3',sparse(zeros(10,10)));
a(1:100,1)=comm_struct;
b(1:10,1)=comm_struct;
disp(size(b))
parfor ct=1:12
b=max_select_2(b,a);
end
where max_select_2 is
function y=max_select_2(b,a)
if size(b,1)~=10
error('size of b is not 10 but %d',size(b,1)),
end
d(1:110,1)=struct('field1',0,'field2',zeros(10,1),'field3',sparse(zeros(10,10)));
d(1:10,1)=b;
d(11:110,1)=a;
[~,sort_idx]=sort([d.field1],'descend');
y=d(sort_idx(1:10));
If I replace the parfor with |for| and ran on my local matlab, no problem, but if I use parfor and run this on a cluster the output is
10 1
which is expected but I also got the error message
"size of b is not 10 but 100"
which means for some reason when b is passed to the function max_select_2, its size changed from 10 to 100? I doubt that it has something to do with how matlab handles the structure array but I don't really know what's going on and how to fix it...
Any help is appreciated! Thanks!
Li
The accumulation function you are using is not allowed (reference)
Unless f is a known noncommutative built-in, it is assumed to be commutative. There is currently no way to specify a user-defined, noncommutative function in parfor.
From my understanding of your code, I recommend to use ; (concatenate) to accumulate and sort outside the parfor loop. Another alternative would be a sliced matrix where each iteration is allowed to fill one column of 10 elements, finally sorting and reshaping it to a vector outside the loop.

Extract parts of a big matrix and allocate them in new variables with loop function

I am a total beginner in MATLAB and I hope to find some help here. I have some model prediction results for 80 individuals alltogether in one large matrix. I need to extract the data for each individual from the big matrix, assign them in a new variable/matrix, do some extra calculations and then plot certain information as needed.
To do so, I am trying to write a script with a loop function but in a complicated, or maybe more accurately: in a primitive way!
Simplified Example:
My matrix is called: All_Indi_Data .... its dimension is: 600 rows x 21 columns
%Column 1: grouping variable (e.g., code or ID with values 1,2,3,4,5, etc.);
%Column 2: independent var.;
%Column 3: t;
%Column 4: OBS;
%Column 5: PRED;
i= length (All_Indi_Data);
%% First Indi.
q=1; % indicating the ID of the indi for which I want to extract the data
j=1; % variable added to insure writing start from the first row
for r=1:i
if All_Indi_Data (r,1)==q
Indi_1 (j,1:21) = All_Indi_Data (r,1:21)
j=j+1
end
end
%% Second Indi.
q=q+1
j=1
for r=1:i
if All_Indi_Data (r,1)==q
Indi_2 (j,1:21) = All_Indi_Data (r,1:21)
j=j+1
end
end
.
.
.
1) My first question is: can I allocate these data in new variables (Indi_1, Indi_2, ect.) in a more simple way with or without the loop function?!!! I would appreciate your help a lot.
2) Is there any code or any way to plot these selected parts (according to the grouping variable, e.g. data for Indi_1) from the previously mentioned big matrix without wasting a lot of time and space (wto recopying the core part of the code again and again) for the script, and using the loop function?! in other words, I would like to detect - with loop function & the grouping variable- which values are of interest and then to plot them (e.g. data in colum 3 with data from column 4 for each individual, starting from the first to the last)?!
I hope that I described my problem clearly and hope to hear something from the expert guys :) ...
Thanks a lot in advance ..
Try the following code:
for idx=1:80
pos=find(All_Indi_Data(:,1)==idx);
eval(['Indi_' num2str(idx) '=All_Indi_Data(pos,:);']);
end
What I do is: in each iteration, I search for a value of the ID, indicated in the variable idx. Note that I do not use ´i´ as the name of a variable, because Matlab uses it and ´j´ and the imaginary unit for complex numbers and that could cause problems.
Then, using find I search for the position (or positions) of All_Indi_Data in which I can find the information of that individual. Now I have in the variable ´pos´ the indexes of the rows in which there is information for the individual of interest.
Finally, using eval I extract the data for each individual into a variable. Note that eval combined with a loop makes it easy to create lots of variables. I indicate the rows I want to extract with ´pos´ and, as I want all the columns, I use just ´:´ (you could use ´1:21´ too).
With another similar loop you can plot the information you want. For example:
for idx=1:80
eval(['x=Indi_' num2str(idx) ';']);
% Now I have in X the information for this individual
%Plot the columns of x I want
plot(x(:, 3), x(:,4));
pause; %stay here until a press a key
end