function test_out = fknn(sample_in, sample_out, test_in, k, m) % FKNN Fuzzy k-nearest neighbor classification rule % % Usage: % TEST_OUT = FKNNR(SAMPLE_IN, SAMPLE_OUT, TEST_IN, K) % % SAMPLE_IN: Input part of the sample data % SAMPLE_OUT: Output part of the sample data % TEST_IN: Input part of the test data % K: The "k" in "K-NNR" % TEST_OUT: Output of the test data according to fuzzy KNNR % % The dimensions of the above matrices is % % SAMPLE_IN: M1xN % SAMPLE_OUT: M1xF % TEST_IN: M2xN % TEST_OUT: M2xF % % where % % M1 = the no. of sample data % N = no. of features % F = no. of classes (or categories) % M2 = no. of test data % % For more technical details, please refer to the paper: % % J. M. Keller, M. R. Gray, and J. A. Givens, Jr., "A Fuzzy K-Nearest % Neighbor Algorithm", IEEE Transactions on Systems, Man, and Cybernetics, % Vol. 15, No. 4, pp. 580-585. % % For selfdemo, type "fknn" with no arguments. % % See also INITFKNN for obtaining a fuzzy version of SAMPLE_OUT. % Roger Jang, 990805 if nargin == 0, selfdemo; return; end if nargin < 5, m = 2; end if nargin < 4, k = 3; end sample_n = size(sample_in, 1); test_n = size(test_in, 1); feature_n = size(sample_in, 2); class_n = size(sample_out, 2); % Euclidean distance matrix distmat = vecdist(sample_in, test_in); % knnmat(i,j) = class of i-th nearest point of j-th input vector % (The size of knnmat is k times test_n.) [junk, index] = sort(distmat); % knnmat = reshape(sample_out(index(1:k,:)), k, test_n); test_out = zeros(test_n, class_n); for i = 1:test_n, neighbor_index = index(1:k, i); weight = distmat(neighbor_index, i)'.^(-2/(m-1)); test_out(i,:) = weight*sample_out(neighbor_index,:)/(sum(weight)); end % ========== Self demo ========== function selfdemo data_n = 50; data = rand(data_n, 2); x = data(:, 1); y = data(:, 2); class = zeros(data_n, 1); index = find(y > x); class(index) = 1; index = find(y<=x & y>=-x+1); class(index) = 2; class(find(class==0)) = 3; sampledata = [x y class]; colordef black; figure; axis([0 1 0 1]); box on; axis equal square color = {'r', 'g', 'c'}; for i = 1:3, index = find(class==i); line(x(index), y(index), 'linestyle', 'none', 'marker', '.', ... 'color', color{i}); end k = 3; fuz_sample_out = initfknn(sampledata, k); index = find(sum(fuz_sample_out.^0.5, 2)~=1); %line(x(index), y(index), 'linestyle', 'none', 'marker', 'o', 'color', 'w'); test_in = rand(50, 2); test_out = fknn([x y], fuz_sample_out, test_in, k); % Plot test data line(test_in(:,1), test_in(:,2), 'linestyle', 'none', 'marker', '.', 'color', 'w'); % Plot desired boundaries line([0 1], [0 1], 'linestyle', ':'); line([0.5 1], [0.5 0], 'linestyle', ':'); legend('Sample data: Class 1', 'Sample data: Class 2',... 'Sample data: Class 3', 'Test data', -1); % Plot classification result of the test data [junk, max_index] = max(test_out'); for i = 1:3, index = find(max_index==i); line(test_in(index,1), test_in(index,2), 'linestyle', 'none', ... 'marker', 'o', 'color', color{i}); end title('The circle color of a sample point shows its predicted class via FKNN.'); %for i = index(:)', % text(x(i), y(i), mat2str(fuz_sample_out(i, :), 2)); %end