Using matlab FCM to cluster my own data - matlab

I am trying to use fcm (fuzzy C-means clustering) matlab tool, but I don't know how to put my own data. I am trying to cluster nodes based on distance from the center. So my data are x and y coordinates. I am basically trying to compare it with k-means this is how I did the k-means:
X=[x_users,y_users];
nc=20;
idx = kmeans(X,nc);
I need to know how to do the same thing with fcm, am sorry if my question is too naive.
Thanks,

fcm(X,nc);
will do it. For example:
data = rand(100,2);
nc = 2;
[center,U,obj_fcn] = fcm(data,nc);
plot(data(:,1),data(:,2),'o');
maxU = max(U);
index1 = find(U(1,:)== maxU);
index2 = find(U(2,:)== maxU);
line(data(index1,1),data(index1,2),'linestyle','none',...
'marker','*','color','g');
line(data(index2,1),data(index2,2),'linestyle','none',...
'marker', '*','color','r');
Using kmeans the answer would be like the following plot:
idx = kmeans(data,nc);
data1 = data(idx==1,:);
data2 = data(idx==2,:);
figure;plot(data1(:,1),data1(:,2),'x');
hold on;plot(data2(:,1),data2(:,2),'or');

Related

Align two 3D datasets

I am working on a problem where I am trying to align two datasets.
The issue is that the data order is not known. Below is a sample code where I am trying to align data1 and data3.
The second issue is when the number of points in both the datasets are not equal.
Any suggestions? Thanks.
rng(11);
N = 10 %10 points
data1 = randn(10,3); %10 coordinates
order = randperm(N)
data2 = data1(order,:); %Reordered data
%Rotation matrix and translation vector
rotM = [0.5771 0.1728 0.7982;
-0.4940 0.8521 0.1728;
-0.6503 -0.4940 0.5771]
TT = [1 2 3];
data3 = data2*rotM + TT;
Edit: Align = rotate and transform data3 to recover rotM and T.
What you are trying to do is a point cloud registration. And PC registration cares little about the order of points.
Assuming you are using Matlab, you could check the below website for the Matlab ICP algorithm. https://www.mathworks.com/help/vision/ref/pcregistericp.html
And
rotM = tform.R;
TT = tform.Translation ;

Reverse-calculating original data from a known moving average

I'm trying to estimate the (unknown) original datapoints that went into calculating a (known) moving average. However, I do know some of the original datapoints, and I'm not sure how to use that information.
I am using the method given in the answers here: https://stats.stackexchange.com/questions/67907/extract-data-points-from-moving-average, but in MATLAB (my code below). This method works quite well for large numbers of data points (>1000), but less well with fewer data points, as you'd expect.
window = 3;
datapoints = 150;
data = 3*rand(1,datapoints)+50;
moving_averages = [];
for i = window:size(data,2)
moving_averages(i) = mean(data(i+1-window:i));
end
length = size(moving_averages,2)+(window-1);
a = (tril(ones(length,length),window-1) - tril(ones(length,length),-1))/window;
a = a(1:length-(window-1),:);
ai = pinv(a);
daily = mtimes(ai,moving_averages');
x = 1:size(data,2);
figure(1)
hold on
plot(x,data,'Color','b');
plot(x(window:end),moving_averages(window:end),'Linewidth',2,'Color','r');
plot(x,daily(window:end),'Color','g');
hold off
axis([0 size(x,2) min(daily(window:end))-1 max(daily(window:end))+1])
legend('original data','moving average','back-calculated')
Now, say I know a smattering of the original data points. I'm having trouble figuring how might I use that information to more accurately calculate the rest. Thank you for any assistance.
You should be able to calculate the original data exactly if you at any time can exactly determine one window's worth of data, i.e. in this case n-1 samples in a window of length n. (In your case) if you know A,B and (A+B+C)/3, you can solve now and know C. Now when you have (B+C+D)/3 (your moving average) you can exactly solve for D. Rinse and repeat. This logic works going backwards too.
Here is an example with the same idea:
% the actual vector of values
a = cumsum(rand(150,1) - 0.5);
% compute moving average
win = 3; % sliding window length
idx = hankel(1:win, win:numel(a));
m = mean(a(idx));
% coefficient matrix: m(i) = sum(a(i:i+win-1))/win
A = repmat([ones(1,win) zeros(1,numel(a)-win)], numel(a)-win+1, 1);
for i=2:size(A,1)
A(i,:) = circshift(A(i-1,:), [0 1]);
end
A = A / win;
% solve linear system
%x = A \ m(:);
x = pinv(A) * m(:);
% plot and compare
subplot(211), plot(1:numel(a),a, 1:numel(m),m)
legend({'original','moving average'})
title(sprintf('length = %d, window = %d',numel(a),win))
subplot(212), plot(1:numel(a),a, 1:numel(a),x)
legend({'original','reconstructed'})
title(sprintf('error = %f',norm(x(:)-a(:))))
You can see the reconstruction error is very small, even using the data sizes in your example (150 samples with a 3-samples moving average).

Input & Coefficients from time domain to frequency, add them together and back to time domain

I am currently studying computer science and i have a task to solve for my lab project. I have to transfer input's signal & coefficients' from time domain to frequency domain, add them together and transfer back to time domain. My results have to match filter function output. However i cannot seem to find what am doing wrong here. I think its something wrong when i add two frequency via conj function. Unfortunately neither my teacher nor my lab supervisor are interested in actually teaching anything so i have to find answers on my own. Hope you guys can help.
clc
clear
B = [0.2];
A = [1,-0.5];
xt = ones(1,20);
xt = padarray(xt,[0,100])
A1 = 1;
A2 = 1;
f1 = 1;
f2 = 25;
fs = 1000;
xd = fft(xt);
wd = freqz(B,A,length(xt));
y = filter(B,A,xt);
yd = conj((wd)').*xd;
yt = real(ifft(yd));
subplot(4,2,1);
plot(xt)
title('Input signal')
subplot(4,2,2);
plot(abs(xd))
title('Input in frequency domain')
subplot(4,2,4);
plot(abs(wd))
title('Coefficients in frequency domain')
subplot(4,2,7);
plot(y)
title('Output using FILTER function')
subplot(4,2,6);
plot(yd)
title('Adding input with coefficients in frequency domain')
subplot(4,2,8);
plot(yt)
title('Back to time domain using IFFT')
The matlab function freqz() can be a little misleading. The "FFT" domain of your coefficients needs to be generated differently. Replace your stuff with the following code, and it should give you what you want:
xt = xt.';
xd = fft(xt);
wd = freqz(B,A,length(xt),'whole');
y = filter(B,A,xt);
yd = wd.*xd;
yt = ifft(yd);
figure
plot(abs(xd))
hold on
plot(abs(wd))
figure
plot(y,'.k','markersize',20)
hold on
plot(yt,'k')
hold off
Also, a note on the ' operator with complex vectors: unless you use the .' operator (e.g., x = x.'), it will transpose the vector while taking the complex conjugate, i.e., (1+1i).' = (1+1i) while (1+1i)' = (1-1i)

fuzzy c means in matlab

I am clustering some data in matlab using the builtin fuzzy c means algorithm which returns C the cluster centers, U fuzzy partition matrix. So I know what the cluster centers are from C but how can I figure out which cluster center each data point belongs to? using the fuzzy partition matrix or some other way?
I know it is a very old question but someone else might find helpful if I give the answer.
The following example is from the Matlab help. There are 2 clusters in the example.
index1 is the indices of the data point that belong to the cluster 1, and index2 is similar. So, using this info what you need is easily obtained.
data = rand(100, 2);
[center,U,obj_fcn] = fcm(data, 2);
plot(data(:,1), data(:,2),'o');
maxU = max(U);
index1 = find(U(1,:) == maxU);
index2 = find(U(2, :) == maxU);
line(data(index1,1),data(index1, 2),'linestyle','none',...
'marker','*','color','g');
line(data(index2,1),data(index2, 2),'linestyle','none',...
'marker', '*','color','r');

Binning in matlab

I have been unable to find a function in matlab or octave to do what I want.
I have a matrix m of two columns (x and y values). I know that I can extract the column by doing m(:,1) or m(:,2). I want to split it into smaller matricies of [potentially] equal size and and plot the mean of these matricies. In other words, I want to put the values into bins based on the x values, then find means of the bins. I feel like the hist function should help me, but it doesn't seem to.
Does anyone know of a built-in function to do something like this?
edit
I had intended to mention that I looked at hist and couldn't get it to do what I wanted, but it must have slipped my mind.
Example: Let's say I have the following (I'm trying this in octave, but afaik it works in matlab):
x=1:20;
y=[1:10,10:1];
m=[x, y];
If I want 10 bins, I would like m to be split into:
m1=[1:2, 1:2]
...
m5=[9:10, 9:10]
m6=[10:11, 10:-1:9]
...
m10=[19:20, 2:-1:1]
and then get the mean of each bin.
Update: I have posted a follow-up question here. I would greatly appreciate responses.
I have answered this in video form on my blog:
http://blogs.mathworks.com/videos/2009/01/07/binning-data-in-matlab/
Here is the code:
m = rand(10,2); %Generate data
x = m(:,1); %split into x and y
y = m(:,2);
topEdge = 1; % define limits
botEdge = 0; % define limits
numBins = 2; % define number of bins
binEdges = linspace(botEdge, topEdge, numBins+1);
[h,whichBin] = histc(x, binEdges);
for i = 1:numBins
flagBinMembers = (whichBin == i);
binMembers = y(flagBinMembers);
binMean(i) = mean(binMembers);
end