K均值聚类

K均值聚类首先随机选择K个对象作为每个簇的初始聚类中心,然后计算剩余对象与各簇中心的距离,将其分配至距离最近的簇,再重新计算每个簇的聚类中心。该算法假设聚类对象为空间向量,且以各聚类内部的均方误差和最小为目标,不断地进行计算迭代,直到准则函数收敛。

注意事项

使用K均值聚类组件时,您需要注意以下事宜:

  • 如果使用夹角余弦距离,则某些聚类可能为空,即聚类数量小于K。因为初始化的K个中心点(向量)可能是平行向量,所以按顺序遍历中心点时,样本不会被分配至后面的中心点(平行向量)。建议通过外部输入中心表的方式,使用线下准备好的K个中心点。

  • 如果输入表中存在NULL或空值,则系统报错Algo Job Failed-System Error-Null feature value found。建议使用默认值进行填充。

  • 使用稀疏格式数据作输入时,如果最大列编号超过2,000,000,则系统报错Algo Job Failed-System Error-Feature count can't be more than 2000000。建议从01开始,重新对列进行编号。

  • 如果中心点模型过大导致写失败,则系统报错Algo Job Failed-System Error-kIOError:Write failed for message: comparison_measure。建议将稀疏矩阵的列从01开始,重新编号。如果模型规模col*centerCount>27,0000,000,则只能通过命令行的方式,去除modelName参数,再重新执行聚类。

  • 如果输入表的列名存在SQL关键字,则系统报错FAILED: Failed Task createCenterTable:kOtherError:ODPS-0130161:[1,558] Parse exception - invalid token ‘,’, expect ‘’)’’

  • 输入表字段格式说明:参与训练的数据列支持INTDOUBLE数据类型。如果输入为稀疏格式的表,则支持STRING类型的数据列。

组件配置

您可以使用以下任意一种方式,配置K均值聚类组件参数。

方式一:可视化方式

Designer工作流页面配置组件参数。

页签

参数

描述

字段设置

特征列

输入数据表中,参与训练的列。列名以半角逗号(,)分隔,支持INTDOUBLE类型。如果输入为稀疏格式,则支持STRING类型的列。

附加列

附加输出至聚类结果表的输入列,列名以半角逗号(,)分隔。

输入为稀疏矩阵

使用KV格式表示稀疏数据。

kv键间分隔符

默认为半角逗号(,)。

kv键内分隔符

默认为半角冒号(:)。

参数设置

聚类数

取值范围为1~1000。

距离度量方式

支持EuclideanCosineCityblock方式。

质心初始化方法

支持RandomFirst KUniformK-Means++使用初始质心表方法。

最大迭代次数

取值范围为1~1000。

收敛标准

迭代终止条件。

初始随机种子

默认值为当前时间。如果seed为固定值,则聚类结果稳定。

执行调优

核心数

默认为系统自动分配。

每个核的内存大小

默认为系统自动分配,单位为MB。

方式二:PAI命令方式

使用PAI命令方式,配置该组件参数。您可以使用SQL脚本组件进行PAI命令调用,详情请参见SQL脚本

pai -name kmeans
    -project algo_public
    -DinputTableName=pai_kmeans_test_input
    -DselectedColNames=f0,f1
    -DappendColNames=f0,f1
    -DcenterCount=3
    -Dloop=10
    -Daccuracy=0.01
    -DdistanceType=euclidean
    -DinitCenterMethod=random
    -Dseed=1
    -DmodelName=pai_kmeans_test_output_model_
    -DidxTableName=pai_kmeans_test_output_idx
    -DclusterCountTableName=pai_kmeans_test_output_couter
    -DcenterTableName=pai_kmeans_test_output_center;

参数

是否必选

描述

默认值

inputTableName

输入表的表名。

selectedColNames

输入数据表中,参与训练的列。列名以半角逗号(,)分隔,支持INTDOUBLE类型。如果输入为稀疏格式,则支持STRING类型的列。

所有列

inputTablePartitions

输入表中,参与训练的分区。支持以下格式:

  • Partition_name=value

  • name1=value1/name2=value2:多级格式

说明

如果指定多个分区,则使用半角逗号(,)分隔。

所有分区

appendColNames

附加输出至聚类结果表的输入列,列名以半角逗号(,)分隔。

enableSparse

输入表是否为稀疏矩阵,取值为truefalse

false

itemDelimiter

KV对之间的分隔符。

半角逗号(,)

kvDelimiter

keyvalue之间的分隔符。

半角冒号(:)

centerCount

聚类数,取值范围为1~1000。

10

distanceType

距离度量方式,支持以下类型:

  • euclidean:欧式距离d(x-c)=(x-c)(x-c)'

  • cosine:夹角余弦的计算方式如下。夹角余玹

  • cityblock:曼哈顿距离d(x-c)=|x-c|

euclidean

initCenterMethod

质心初始化的方法,支持以下方法:

  • random:从输入数据中,随机采样K个初始中心点,初始随机种子由参数seed指定。

  • topk:从输入数据中,读取前K行作为初始中心点。

  • uniform:从最小值到最大值,均匀地计算K个初始中心点。

  • kmpp:通过K-Means++算法,获得K个初始中心点。

  • external:指定额外的初始质心表。

random

initCenterTableName

初始质心表的名称。如果initCenterMethodexternal,则该参数生效。

loop

最大迭代次数,取值范围为1~1000。

100

accuracy

算法终止条件。如果两次迭代的目标差小于该值,则算法终止。

0.1

seed

初始随机种子。

当前时间

modelName

输出模型的名称。

idxTableName

输出聚类结果表,包括聚类后每条记录所属的类号。

idxTablePartition

聚类结果表的分区。

clusterCountTableName

聚类统计表,统计各聚类包含的点数量。

centerTableName

聚类中心表。

coreNum

节点数量,与memSizePerCore搭配使用。取值范围为1~9999。

系统自动分配

memSizePerCore

每个节点的内存大小,取值范围为1024 MB~64*1024 MB。

系统自动分配

lifecycle

输出表的生命周期,单位为天。

组件输出

K均值聚类输出聚类结果表、聚类统计表及聚类中心表。输出格式如下:

  • 聚类结果表

    列名

    描述

    appendColNames

    附加列。

    cluster_index

    训练表中,每个样本被分配到的簇。

    distance

    训练表中,每个样本到簇中心的距离。

  • 聚类统计表

    列名

    描述

    cluster_index

    簇编号。

    cluster_count

    每个簇中的样本数量。

  • 聚类中心表

    列名

    描述

    cluster_index

    簇编号。

    selectedColNames

    训练表中,参与训练的列。

示例

以稠密格式数据作为输入:

  1. 您可以通过以下任何一种方式,生成测试数据:

    • 使用初始质心表的方式

      create table pai_kmeans_test_init_center as
      select * from
      (
      select 1 as f0,2 as f1
      union all
      select 1 as f0,3 as f1
      union all
      select 1 as f0,4 as f1
      )tmp;
    • 使用其他初始质心的方式

      create table pai_kmeans_test_input as
      select * from
      (
        select 'id1' as id,1 as f0,2 as f1
        union all
        select 'id2' as id,1 as f0,3 as f1
        union all
        select 'id3' as id,1 as f0,4 as f1
        union all
        select 'id4' as id,0 as f0,3 as f1
        union all
        select 'id5' as id,0 as f0,4 as f1
      )tmp;
  2. 使用PAI命令,提交K均值聚类算法组件参数:

    • 使用初始质心表的方式

      drop table if exists pai_kmeans_test_output_idx;
      yes
      drop table if exists pai_kmeans_test_output_couter;
      yes
      drop table if exists pai_kmeans_test_output_center;
      yes
      drop offlinemodel if exists pai_kmeans_test_output_model_;
      yes
      pai -name kmeans
          -project algo_public
          -DinputTableName=pai_kmeans_test_input
          -DinitCenterTableName=pai_kmeans_test_init_center
          -DselectedColNames=f0,f1
          -DappendColNames=f0,f1
          -DcenterCount=3
          -Dloop=10
          -Daccuracy=0.01
          -DdistanceType=euclidean
          -DinitCenterMethod=external
          -Dseed=1
          -DmodelName=pai_kmeans_test_output_model_
          -DidxTableName=pai_kmeans_test_output_idx
          -DclusterCountTableName=pai_kmeans_test_output_couter
          -DcenterTableName=pai_kmeans_test_output_center;
    • 使用随机初始质心的方式

      drop table if exists pai_kmeans_test_output_idx;
      yes
      drop table if exists pai_kmeans_test_output_couter;
      yes
      drop table if exists pai_kmeans_test_output_center;
      yes
      drop offlinemodel if exists pai_kmeans_test_output_model_;
      yes
      pai -name kmeans
          -project algo_public
          -DinputTableName=pai_kmeans_test_input
          -DselectedColNames=f0,f1
          -DappendColNames=f0,f1
          -DcenterCount=3
          -Dloop=10
          -Daccuracy=0.01
          -DdistanceType=euclidean
          -DinitCenterMethod=random
          -Dseed=1
          -DmodelName=pai_kmeans_test_output_model_
          -DidxTableName=pai_kmeans_test_output_idx
          -DclusterCountTableName=pai_kmeans_test_output_couter
          -DcenterTableName=pai_kmeans_test_output_center;
  3. 查看聚类结果表、聚类统计表及聚类中心表:

    • 聚类结果表idxTableName

      +------------+------------+---------------+------------+
      | f0         | f1         | cluster_index | distance   |
      +------------+------------+---------------+------------+
      | 1          | 2          | 0             | 0.0        |
      | 1          | 3          | 1             | 0.5        |
      | 1          | 4          | 2             | 0.5        |
      | 0          | 3          | 1             | 0.5        |
      | 0          | 4          | 2             | 0.5        |
      +------------+------------+---------------+------------+
    • 聚类统计表clusterCountTableName

      +---------------+---------------+
      | cluster_index | cluster_count |
      +---------------+---------------+
      | 0             | 1             |
      | 1             | 2             |
      | 2             | 2             |
      +---------------+---------------+
    • 聚类中心表centerTableName

      +---------------+------------+------------+
      | cluster_index | f0         | f1         |
      +---------------+------------+------------+
      | 0             | 1.0        | 2.0        |
      | 1             | 0.5        | 3.0        |
      | 2             | 0.5        | 4.0        |
      +---------------+------------+------------+

以稀疏格式数据作为输入:

  1. 生成测试数据。

    create table pai_kmeans_test_sparse_input as
    select * from
    (
      select 1 as id,"s1" as id_s,"0:0.1,1:0.2" as kvs0,"2:0.3,3:0.4" as kvs1
      union all
      select 2 as id,"s2" as id_s,"0:1.1,2:1.2" as kvs0,"4:1.3,5:1.4" as kvs1
      union all
      select 3 as id,"s3" as id_s,"0:2.1,3:2.2" as kvs0,"6:2.3,7:2.4" as kvs1
      union all
      select 4 as id,"s4" as id_s,"0:3.1,4:3.2" as kvs0,"8:3.3,9:3.4" as kvs1
      union all
      select 5 as id,"s5" as id_s,"0:5.1,5:5.2" as kvs0,"10:5.3,6:5.4" as kvs1
    )tmp;

    稀疏格式数据作为输入时,使用0填充缺失的列。如果多个列同时作为输入,则会被合并。例如,kvs0kvs1同时作为输入,则第一行的实际数据如下。

    0:0.1,1:0.2,2:0.3,3:0.4,4:0,5:0,6:0,7:0,8:0,9:0,10:0

    示例中的稀疏矩阵列从0开始编号,矩阵共511列。如果kvs中的某列包含123456789:0.1,则稀疏矩阵变为5123456789列,该矩阵会消耗大量CPU和内存。对于kvs中存在异常列编号的原始数据,建议重新进行列编号以减小矩阵规模。

  2. 使用PAI命令,提交K均值聚类组件的参数。

    pai -name kmeans
      -project algo_public
      -DinputTableName=pai_kmeans_test_sparse_input
      -DenableSparse=true
      -DselectedColNames=kvs0,kvs1
      -DappendColNames=id,id_s
      -DitemDelimiter=,
      -DkvDelimiter=:
      -DcenterCount=3
      -Dloop=100
      -Daccuracy=0.01
      -DdistanceType=euclidean
      -DinitCenterMethod=topk
      -Dseed=1
      -DmodelName=pai_kmeans_test_input_sparse_output_model
      -DidxTableName=pai_kmeans_test_sparse_output_idx
      -DclusterCountTableName=pai_kmeans_test_sparse_output_couter
      -DcenterTableName=pai_kmeans_test_sparse_output_center;
  3. 查看聚类结果表、聚类统计表及聚类中心表:

    • 聚类结果表idxTableName

      +------------+------------+---------------+------------+
      | id         | id_s       | cluster_index | distance   |
      +------------+------------+---------------+------------+
      | 4          | s4         | 0             | 2.90215437218629 |
      | 5          | s5         | 1             | 0.0        |
      | 1          | s1         | 2             | 0.7088723439378913 |
      | 2          | s2         | 2             | 1.1683321445547923 |
      | 3          | s3         | 0             | 2.0548722588034516 |
      +------------+------------+---------------+------------+
    • 聚类统计表clusterCountTableName

      +---------------+---------------+
      | cluster_index | cluster_count |
      +---------------+---------------+
      | 0             | 2             |
      | 1             | 1             |
      | 2             | 2             |
      +---------------+---------------+
    • 聚类中心表centerTableName

      +---------------+------------+------------+
      | cluster_index | kvs0       | kvs1       |
      +---------------+------------+------------+
      | 0             | 0:2.6,1:0,2:0,3:1.1,4:1.6,5:0 | 6:1.15,7:1.2,8:1.65,9:1.7,10:0 |
      | 1             | 0:5.1,1:0,2:0,3:0,4:0,5:5.2 | 6:5.4,7:0,8:0,9:0,10:5.3 |
      | 2             | 0:0.6,1:0.1,2:0.75,3:0.2,4:0.65,5:0.7 | 6:0,7:0,8:0,9:0,10:0 |
      +---------------+------------+------------+