I have MATLAB R2015b and I am working on a Pattern Recognition project. I have loaded fisher iris data set.
I have written the code below for k-NN classification:
rng default;
fold_number = 5;
indices = crossvalind('Kfold',species, fold_number);
val = 1:2:5; % for these small k values there will not be an important difference
% regarding the cp ErrorRates. The difference is going to be
% observable for val = 1:2:100, for example!!! But the
% exercise asks only for k = 1,3,5.
err_arr = [];
for k=val
cp = classperf(species); % Reinitialize the cp-structure!
for i = 1:fold_number
test = (indices == i);
train = ~test;
class = knnclassify(meas(test,:),meas(train,:),species(train), k);
%class = knnclassify(meas(test,2),meas(train,2),species(train), k); % To experiment only with the 2nd feature
classperf(cp,class,test);
end
err_arr = [err_arr; cp.ErrorRate];
fprintf('The k-NN classification error rate for k = %d is: %f\n', k,cp.ErrorRate);
end
fprintf('\n The error array is: \n');
disp(err_arr);
fprintf('Program paused. Press enter to continue.\n');
pause
After that, I would like to plot the confusion matrix. So, I need this line of code:
[C,order] = confusionmat(species, predicted_species);
So, I have to find the predicted_species matrix. I have thought to write the below line of code about that:
predicted_species = resubPredict(class);
Here is the moment I am getting the on the title mentioned error and I do not know why, while resubPredict is a function supported by my MATLAB version.
Could anyone help me solve this problem?
Take a look at the top of the documentation for resubPredict, there you will notice the line
Class ClassificationKNN
Meaning that the function can only be used with inputs of that type. In your case you are passing doubles.
You have to switch to the new interface, fitcknn instead of knnclassify
Related
I have code that uses Wolff's Algorithm to simulate the XY Model in MATLAB and I want to implement a pcolor/color map to demonstrate each spin according to their angles across the system. But I want it to be live and changing as the angles change.
Any idea how to do this?
This is an example of how I want it to look https://i.stack.imgur.com/aSp7s.png
If you save each snapshot of the lattice in a cell array A{t}, you can use the following function to view and save it as a video (if fileName is not empty, the function saves an mp4 video).
Another option is to adapt the function view_lattice to run your simulation (which, honestly, I wouldn't recommend, for performance issues). I will mark where you should edit for doing a "live" simulation
This is at least MATLAB R2019b (although it may be compatible with earlier versions, but no guarantee).
File view_lattice.m
function view_lattice(A,fileName)
% for a 'live' simulation, you will have to remove A from the input
% parameters and add the ones you need for the XY Wolff algorithm,
% which will be used to calculate each configuration A in the time loop below
% you will also need to remove the assert statements for 'live' simulation
%
% otherwise, you save snapshots from your simulation
% and use this function as is
%
% A -> A{k}[m,n] snapshot k containing the angles of spins in lattice site at row m and col n
% fileName -> if contains string, then records a video with the snapshots and name it with this string
assert(iscell(A) && all(cellfun(#(a)isnumeric(a) && ismatrix(a),A)),'A must be cell of numeric matrices');
assert(ischar(fileName),'fileName must be either an empty char or contain a file name');
recordVideo = ~isempty(fileName);
if recordVideo
vw = setup_video(fileName);
else
vw = [];
end
% setting some default axis properties to speed-up plotting
set(0,'DefaultAxesPlotBoxAspectRatio',[1 1 1],'DefaultAxesDataAspectRatioMode','manual','DefaultAxesDataAspectRatio',[1,1,1],'DefaultAxesNextPlot','replace');
fh = figure;
ax=axes;
for t = 1:numel(A) % for 'live' simulation, this loop should be the time loop
% here you calculate the new configuration A
% and call the function below with A instead of A{t}
vw = record_frame(vw,fh,ax,A{t},t,recordVideo);
end
% any video to close?
if recordVideo
vw.close();
end
end
function vw = record_frame(vw,fh,ax,A,t,recordVideo)
imagesc(ax,A);
title(ax,sprintf('snapshot %g',t)); % if you want, y
axis(ax,'square');
daspect(ax,[1,1,1]);
pause(0.01);
if recordVideo
vframe = getframe(fh);
vw.writeVideo(vframe);
end
end
function vw = setup_video(fileName)
vid_id = num2str(rand,'%.16g');
vid_id = vid_id(3:6);
vid_id = [fileName,'_',vid_id];
% Initialize video
vw = VideoWriter([vid_id,'.mp4'], 'MPEG-4'); %open video file
vw.Quality = 100;
vw.FrameRate = 16;
vw.open();
end
Test script: test.m
clearvars
close all
A = cell(1,30);
for t = 1:numel(A)
% creating a sequence of random snapshots only for illustration
A{t} = rand(20,20);
end
% viewing the animation and saving it as a video with name test
view_lattice(A,'test');
Output
This is a followup to a previous issue I was having.
I want to give an offset to a signal then add some delay in it and calculate RMSE for that but when taking difference I am having the following issue:
I would like to ask the following things:
How can I solve the above problem?
Will anybody please explain in simple words what iddata does - because I have studied different portals including MATLAB but remained unable to get a good concept.
How can I store data of type iddata in cell for subtraction in the last part of my code?
Code with Problem :
drv(1)=load('123.mat');
t = drv(1).x;
ref = drv(1).y;
angle = drv(1).z;
Fs = 1000;
t1 =t';
ref1= ref';
d_data = iddata(ref1, t1, 1/Fs);
%% Add offset:
x = 1;
afterOffset1= {};
for i = 100:10:130
T = getTrend(d_data);
% <detrend data if needed>
T.InputOffset = i;
T.OutputOffset = i;
afterOffset = retrend(d_data,T);
afterOffset1{x,1}= afterOffset;
x= x+1 ;
end
%% Add delay:
y=20;
afterDelay1= {};
for i = 1:1:4
% delaySamples = i; % Must be a non-negative value
% afterDelay = iddata([NaN(delaySamples,1); d_data.OutputData],...
% [d_data.InputData; NaN(delaySamples,1)], 1/Fs);
afterOffset1{i}.Tstart = y;
afterDelay1{i,1}= afterOffset1{i};
y= y+10;
end
%% Plot:
n = size(afterDelay1,1);
figure();
for i=1:1:n
subplot(2,2,i);
plot(d_data);
hold all
plot(afterDelay1{i});
end
sig_diff = angle(1)-afterDelay1;
square_error(i,:) = (sig_diff(i)).^2;
mse(i,:)= mean(square_error(i));
rmse(i,:) = sqrt(mse(i));
sig_diff = d_data_1 - afterDelay; % <<<<<<<<<<<<<<<<<<<<<< Problem is here
% square_error = (sig_diff).^2;
% mse= mean(square_error);
% rmse = sqrt(mse);
end
You most likely want the OutputData attribute from the iddata object which is the output or y signal of your problem:
sig_diff = angle(1)-afterDelay1.OutputData;
Also note that this will give you a column vector, but your code later on assumes it's a row vector. You may want to transpose this data after you perform the above calculation before proceeding:
sig_diff = angle(1)-afterDelay1.OutputData;
sig_diff = sig_diff.';
In general, iddata is a function that creates an object that represents input and output time or frequency domain data. Take note that when you create an iddata object, the input matrix can potentially have multiple sources and so each column dictates a source. The same can be said for the output where each column dictates an output. Therefore, it is very important that you transpose your data prior to using this function to ensure that each signal is in a separate column, or just use a single column to represent one input / output.
Inside the object has a variety of attributes, including the sampling time or sampling frequency, the valid domain and range that the function takes on and finally accessing the input and output data. OutputData is one of these fields. I'd recommend looking at the documentation that talks about all of the attributes that you can access with iddata. OutputData is clearly defined here: https://www.mathworks.com/help/ident/ref/iddata.html
Hoping you may be able to assist me with this error. I am running some code to fit curves to ages using a cross validation regime. I iterate the curve fitting 1000 times to assess the best fit.
I define my models as:
linear_ft = fittype({'x', '1'});
monotonic_ft= fittype({'-1/x', '1'});
quadratic_ft = fittype('poly2');
I then run the following to iterate through different selections of data splitting, recording the residuals following the curve fit...
Data = randn(4,300,10,10);
Ages = randn(300,1);
for thisDim1 = 1:4
for thisDim2 = 1:10
for thisDim3 = 1:10
for nIts = 1:1000
RandomOrder = randperm(300,300);
Fit_Subs = RandomOrder(1:length(Ages)/2); % Take random subs to fit to
Test_Subs = RandomOrder(length(Ages)/2+1:300); % Take random subs to test fit to
Fit_Data = squeeze(Data(thisDim1,Fit_Subs,thisDim2,thisDim3)); % Take data to fit to
Test_Data = squeeze(Data(thisDim1,Test_Subs,thisDim2,thisDim3)); % Take data to test fit
Fit_Ages = Ages;
Fit_Ages(Fit_Subs) = []; %Take ages of Fit Subs only
Test_Ages = Ages;
Test_Ages(Test_Subs) = []; % Take ages of Test Subs only
Nsubs = (length(Ages)/2);
% Model Data using Curves
fFit_Lin = fit(Fit_Ages,Fit_Data',linear_ft);
fFit_Mon = fit(Fit_Ages,Fit_Data',monotonic_ft);
fFit_Quad = fit(Fit_Ages,Fit_Data',quadratic_ft);
% Fit Modelled Data to Test Data
tFit_Lin = fFit_Lin(Test_Ages);
tFit_Mon = fFit_Mon(Test_Ages);
tFit_Quad = fFit_Quad(Test_Ages);
% Calculate Median Residual
Lin_Med_Resid(nIts) = median(tFit_Lin - Test_Data');
Mon_Med_Resid(nIts) = median(tFit_Mon - Test_Data');
Quad_Med_Resid(nIts) = median(tFit_Quad - Test_Data');
end
end
end
end
If you run this with the fourth loop (nIts) as a for-loop it will run. If you run it as a parfor-loop it won't stating the error:
Error using fit>iFit (line 264)
The name 'lower' is not an accessible property for an instance of class
'llsqoptions'.
Error in fit (line 108) [fitobj, goodness, output, convmsg] = iFit(
xdatain, ydatain, fittypeobj, ...
Does anyone have any idea how to fix this? I would be most grateful for any advice!!
Thanks,
Ben
Try restarting MATLAB or typing clear all to see if it clears things up for you.
Your code works for me, but the parallel toolbox can be a bit finicky in my experience.
Hey I'm having trouble integrating a function in MATLAB, constantly getting errors. I'm trying to fill a matrix with the function. exp(x-1)*x^j+k
I2 = zeros(26,3);
k = [0.13, 0.0024, 0.000035];
for i = 1:length(k)
for j = 0:25
fun = #(x,j) exp(x-1).*x.^j+k(i);
I2(j,i) = integral(fun,0,1);
end %end j-loop
end %end i-loop
display(I2);
Thanks.
In the current form the function handle is expecting two inputs but you want a function with a single input for integral. Changing your function handle definition to the following should fix this.
fun = #(x) exp(x-1)*x^j+k(i);
Look at the code snippet here in the mathworks documentation,
Digital Servo Control of a Hard-Disk Drive
Gf1 = tf(w1*[a1 b1*w1],[1 2*z1*w1 w1^2]); % first resonance
Gf2 = tf(w2*[a2 b2*w2],[1 2*z2*w2 w2^2]); % second resonance
Gf3 = tf(w3*[a3 b3*w3],[1 2*z3*w3 w3^2]); % third resonance
Gf4 = tf(w4*[a4 b4*w4],[1 2*z4*w4 w4^2]); % fourth resonance
my question is, how can I implement the above statements within a loop like,
% pseudo code
for i = 1:4
Gf%d = tf(w%d*[a%d b%d*w%d],[1 2*z%d*w%d w%d^2]); i
and then execute the result in matlab?
Here's one option:
w = [w1 w2 w3 w4];
%# same thing for a, b, d...
for i=1:4
Gf(i) = tf(w(i)*[a(i) b(i)*w(i)],[1 2*z(i)*w(i) w(i)^2]); % ith resonance
end
You could either use eval:
for i = 1:4
eval(sprintf('Gf%d = tf(w%d*[a%d b%d*w%d],[1 2*z%d*w%d w%d^2]);', i));
end
or you could turn your parameters into arrays. Arrays would be more efficient, if you have control over how you format your data.
The best way to do this is to use arrays.
for i = 1:n
trans(i) = % your stuff here %
end
Then just replace the different variables with the correct array indexes.