在 MATLAB 中使用感知器对数据进行分类
Posted
技术标签:
【中文标题】在 MATLAB 中使用感知器对数据进行分类【英文标题】:Classify data with a perceptron in MATLAB 【发布时间】:2014-04-29 19:57:47 【问题描述】:我正在生成可以线性分离的随机数据。我想编写自己的感知器版本来分离它们。我知道有些帖子有类似的问题 - 但我找不到我的错误。我真的被困住了。该算法有效,但似乎没有收敛。如果您能帮助我,我将不胜感激。
我的代码:
single_layer_perceptron.m
% INPUT
% amount of values
points = 20;
% stepsize
s = 1.0;
% INITIALIZE
% Booleans
TRUE = 1;
FALSE = 0;
% generate data
D = generateRandomData(points);
% x-values
x = D(:,1);
% y-values
y = D(:,2);
% training set
d = D(:,3);
% weights
w = zeros(3,1);
% bias
b = 1;
% sucsess flag
isCorrect = FALSE;
% correctly predicted values counter
p = 0;
% COMPUTE
% while at east one point is not correctly classified
while isCorrect == FALSE
% for every point in the dataset
for i=1 : points
% calculate outcome with current weight
c = heaviside(b * w(1) + x(i) * w(2) + y(i) * w(3));
% compare output with training set
a = errorFunction(c,d(i));
% if outcome was wrong
if a ~= 0
% ajust weights
w(1) = w(1) + a*s*b;
w(2) = w(2) + a*s*x(i);
w(3) = w(3) + a*s*y(i);
else
% increase correctness counter
p = p + 1;
end
end
%disp(w);
disp(p);
if p >= points
isCorrect = TRUE;
end
p = 0;
end
generateRandomData.m
function f = generateRandomData(points)
% generates random data that can be lineary seperated (silent)
% generate random function y = mx + n
m = 2 * rand * sign(randn); % in (-2,2)/0
n = 10 * rand + 5; % in (5,15)
% generate random points
x = 20 * rand(points,2); % in ((0,20), (0,20))
% labeling
f = [x, zeros(points,1)];
for i=1:length(x(:,1))
y = m*x(i,1) + n;
if x(i,2) > y
f(i,3) = 1;
end
end
end
activationFunctionHeaviside.m
function f = activationFunctionHeaviside(x)
f = (1/2)*(sign(x)+1);
end
errorFunction.m
function f = errorFunction(c,d)
% w has been classified as c - w should be d
if c < d
% reaction too small
f = -1;
elseif c > d
% reaction too large
f = 1;
else
% reaction correct
f = 0;
end
end
非常感谢!
【问题讨论】:
变量“points”究竟表示什么?好的,我在您的评论行中看到了值的数量..那是?例如,我正在研究 Fisher iris 数据集;在这种情况下,我可以用什么“点”代替? 【参考方案1】:single-layer perceptron 是一个线性二元分类器,当数据不可线性分离时不会收敛。如果我们绘制数据,我们会发现两个类是重叠的。
我们可以通过向您的函数generateRandomData.m
添加容差来解决此问题function f = generateRandomData(points)
% generates random data that can be lineary seperated (silent)
% generate random function y = mx + n
m = 2 * rand * sign(randn); % in (-2,2)/0
n = 10 * rand + 5; % in (5,15)
% generate random points
x = 20 * rand(points,2); % in ((0,20), (0,20))
% tolerance
tol = 0.5;
% labeling
f = [x, -ones(points,1)];
for ii=1:size(f,1)
y = m*f(ii,1) + n;
if f(ii,2) > y+tol
f(ii,3) = 1;
elseif f(ii,2) < y-tol
f(ii,3) = 0;
else
f(ii,1) = f(ii,1)+2*tol;
f(ii,3) = 1;
end
end
end
但是,您的代码仍然没有收敛,因为您的 errorFunction.m 已切换符号。应该是这样的:
function f = errorFunction(c,d)
% w has been classified as c - w should be d
if c < d
% reaction too small
f = +1;
elseif c > d
% reaction too large
f = -1;
else
% reaction correct
f = 0;
end
end
一旦我们做了这些改变,我们就会得到一个很好的线性分类:
绘制假设的代码:
% Plot
idx = logical(D(:,3));
Xax = 0:20; Yax=-(b*w(1)+Xax*w(2))/w(3);
figure;
hold on;
scatter(D(idx,1),D(idx,2),'bo')
scatter(D(~idx,1),D(~idx,2),'rx')
plot(Xax,Yax,'k--')
【讨论】:
对你有帮助真是太好了。如果此解决方案解决了您的问题,请不要忘记将其标记为有效答案以帮助其他用户。 还有一个问题:你是怎么画线的?我试过了:xValues = linspace(0,20,10); yValues = (-1 * ( xValues* w(1) + b * w(3) )) / w(2);
@Chris,公差有什么作用?
容差仅用于生成训练数据。它确保标签在特征空间中是线性可分的。
@tashuhka,这是一个二进制在线感知器,对吧?以上是关于在 MATLAB 中使用感知器对数据进行分类的主要内容,如果未能解决你的问题,请参考以下文章
MATLAB:使用 fitctree 训练的分类器对新数据进行标签预测