机器学习(三):无监督学习 K-means算法

 

继续之前关于机器学习的笔记,此次为无监督学习的算法分享。

0x01 无监督学习概念

类比于之前的有监督学习而言,无监督学习最大的特点在于训练集中不会给出正确的分类,即训练样本中并没有对样本进行划分,需要算法自己学习,找出其中哪些样本是属于一类的。如下图所示

                                                              

这种自动分类算法又称为聚类算法,是一种通过学习进行自动分类的算法。

0x02 聚类算法 K-means 

聚类算法中最为常用的为K-means算法,下面来介绍这种算法的原理。

首先原始的数据集如下所示。                       

随后随机生成两个聚类中心点,用于将数据集初步分为两类。如下所示。

                                                            

其中,分类方法为,分别取出数据集中的所有点,计算每个点到达两个中心点的距离,如果该点距离红色中心点近则该点为红色,相反为蓝色。最终结果如上图所示。随后,移动中心点到下图。

移动的算法为,计算所有的红色点的横纵坐标平均值,并将中心点移动到平均值位置,即分别将中心点向自己分类的中心移动。然后重复上述步骤重新对所有的点进行染色。 如下图所示。

 重复以上的步骤直至中心点不再变动,就会发现K-means算法已经将训练集分成了红蓝两类。如下图所示

0x03 matlab K-meas算法实现  

首先是将数据集根据距离中心点的距离进行划分,本例子中将数据集划分成三类,因此初始化过程中有三个中心点。

load('ex7data2.mat');

% 选取中心点个数
K = 3; 
initial_centroids = [3 3; 6 2; 8 5];  % 三个中心点的坐标

随后根据数据集中的各个点到三个中心点的距离大小来对数据集进行分类。其中 idx 是一个和数据集一样大的列矩阵,用于记录对应数据集中的每个点被划分的中心点。1代表第一个中心点,2代表第二个中心点,3代表第三个。

function idx = findClosestCentroids(X, centroids)

K = size(centroids, 1);  % 中心点个数

idx = zeros(size(X,1), 1);  % 用于记录每个数据所属的中心点

m = size(idx, 1);

for i = 1:m
    min = 100000;
    flag = 0;
    for j = 1:K
        % 计算该点与中心点的距离的平方
        temp = (X(i,1)-centroids(j,1)).^2 + (X(i,2)-centroids(j,2)).^2; 
        if temp <= min
            min = temp;
            flag = j;
        end
    end
    
    idx(i,1) = flag;
end
    
end

然后计算中心点的移动位置。计算中心点所在群体的中心位置,并将其移动到该位置。方法分别计算中心点所在的群的所有点的坐标和,然后用和除以群数量得到平均值。

function centroids = computeCentroids(X, idx, K)

[m n] = size(X);

centroids = zeros(K, n);

num1 = 0;
num2 = 0;
num3 = 0;
sum1 = [0;0];
sum2 = [0;0];
sum3 = [0;0];
flag = 1;

for i = 1:size(idx, 1)
    if idx(i,1) == 1
        num1 = num1 + 1;
        sum1 = sum1 + [X(i,1);X(i,2)];
    elseif idx(i,1) == 2
        num2 = num2 + 1;
        sum2 = sum2 + [X(i,1);X(i,2)];
    elseif idx(i,1) == 3
        num3 = num3 + 1;
        sum3 = sum3 + [X(i,1);X(i,2)];
    end
end

u1 = sum1 ./ num1;
u2 = sum2 ./ num2;
u3 = sum3 ./ num3;

centroids(1, 1) = u1(1, 1);
centroids(1, 2) = u1(2, 1);
centroids(2, 1) = u2(1, 1);
centroids(2, 2) = u2(2, 1);
centroids(3, 1) = u3(1, 1);
centroids(3, 2) = u3(2, 1);

end

通过多次循环以上两个算法,并观察其变化过程。

function [centroids, idx] = runkMeans(X, initial_centroids, max_iters, plot_progress)

if ~exist('plot_progress', 'var') || isempty(plot_progress)
    plot_progress = false;
end


if plot_progress
    figure;
    hold on;
end

% Initialize values
[m n] = size(X);
K = size(initial_centroids, 1);
centroids = initial_centroids;
previous_centroids = centroids;
idx = zeros(m, 1);

% Run K-Means
for i=1:max_iters
    
    % Output progress
    fprintf('K-Means iteration %d/%d...\n', i, max_iters);
    if exist('OCTAVE_VERSION')
        fflush(stdout);
    end
    
    % For each example in X, assign it to the closest centroid
    idx = findClosestCentroids(X, centroids);
    
    % Optionally, plot progress here
    if plot_progress
        plotProgresskMeans(X, centroids, previous_centroids, idx, K, i);
        previous_centroids = centroids;
        fprintf('Press enter to continue.\n');
        pause;
    end
    
    % Given the memberships, compute new centroids
    centroids = computeCentroids(X, idx, K);
end

% Hold off if we are plotting progress
if plot_progress
    hold off;
end

end

结果如下图所示

可以看出中心点一点一点向自身群体的中心移动,最终将数据集划分成三类。 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值