文档章节

在Ignite中使用k-均值聚类算法

李玉珏
 李玉珏
发布于 2018/12/03 19:49
字数 1398
阅读 1.5K
收藏 30

在本系列前面的文章中,简单介绍了一下Ignite的k-最近邻(k-NN)分类算法,下面会尝试另一个机器学习算法,即使用泰坦尼克数据集介绍k-均值聚类算法。正好,Kaggle提供了CSV格式的数据集,而要分析的是两个分类:即乘客是否幸存。

为了将数据转换为Ignite支持的格式,前期需要做一些清理和格式化的工作,CSV文件中包含若干个列,如下:

  • 乘客Id
  • 幸存(0:否,1:是)
  • 船票席别(1:一,2:二,3:三)
  • 乘客姓名
  • 性别
  • 年龄
  • 泰坦尼克号上的兄弟/姐妹数
  • 泰坦尼克号上的父母/子女数
  • 船票号码
  • 票价
  • 客舱号码
  • 登船港口(C=瑟堡,Q=皇后镇,S=南安普顿)

因此首先要做的是,删除任何和特定乘客有关的、和生存无关的列,如下:

  • 乘客Id
  • 乘客姓名
  • 船票号码
  • 客舱号码

接下来会删除任何数据有缺失的行,比如年龄或者登船港口,可以对这些值进行归类,但是为了进行初步的分析,会删除缺失的值。

最后会将部分字段转换为数值类型,比如性别会被转换为:

  • 0:女
  • 1:男

登船港口会被转换为:

  • 0:Q(皇后镇)
  • 1:C(瑟堡)
  • 2:S(南安普顿)

最终的数据集由如下的列组成:

  • 船票席别
  • 性别
  • 年龄
  • 泰坦尼克号上的兄弟/姐妹数
  • 泰坦尼克号上的父母/子女数
  • 票价
  • 登船港口
  • 幸存

可以看到,幸存列已被移到最后。

下一步会将数据拆分为训练数据(80%)和测试数据(20%),和前文一样,还是使用Scikit-learn来执行这个拆分任务。

准备好训练和测试数据后,就可以编写应用了,本文的算法是:

  1. 读取训练数据和测试数据;
  2. 在Ignite中保存训练数据和测试数据;
  3. 使用训练数据拟合k-均值聚类模型;
  4. 将模型应用于测试数据;
  5. 确定含混矩阵和模型的准确性。

读取训练数据和测试数据

通过下面的代码,可以从CSV文件中读取数据:

private static void loadData(String fileName, IgniteCache<Integer, TitanicObservation> cache)
        throws FileNotFoundException {

   Scanner scanner = new Scanner(new File(fileName));

   int cnt = 0;
   while (scanner.hasNextLine()) {
      String row = scanner.nextLine();
      String[] cells = row.split(",");
      double[] features = new double[cells.length - 1];

      for (int i = 0; i < cells.length - 1; i++)
         features[i] = Double.valueOf(cells[i]);
      double survivedClass = Double.valueOf(cells[cells.length - 1]);

      cache.put(cnt++, new TitanicObservation(features, survivedClass));
   }
}

该代码简单地一行行的读取数据,然后对于每一行,使用CSV的分隔符拆分出字段,每个字段之后将转换成double类型并且存入Ignite。

将训练数据和测试数据存入Ignite

前面的代码将数据存入Ignite,要使用这个代码,首先要创建Ignite存储,如下:

IgniteCache<Integer, TitanicObservation> trainData = getCache(ignite, "TITANIC_TRAIN");
IgniteCache<Integer, TitanicObservation> testData = getCache(ignite, "TITANIC_TEST");
loadData("src/main/resources/titanic-train.csv", trainData);
loadData("src/main/resources/titanic-test.csv", testData);

getCache()的实现如下:

private static IgniteCache<Integer, TitanicObservation> getCache(Ignite ignite, String cacheName) {

   CacheConfiguration<Integer, TitanicObservation> cacheConfiguration = new CacheConfiguration<>();
   cacheConfiguration.setName(cacheName);
   cacheConfiguration.setAffinity(new RendezvousAffinityFunction(false, 10));

   IgniteCache<Integer, TitanicObservation> cache = ignite.createCache(cacheConfiguration);

   return cache;
}

使用训练数据拟合k-NN分类模型

数据存储之后,可以像下面这样创建训练器:

KMeansTrainer trainer = new KMeansTrainer()
        .withK(2)
        .withDistance(new EuclideanDistance())
        .withSeed(123L);

这里k的值配置为2,表示有2个簇(幸存和未幸存),对于距离测量,可以有多个选择,比如欧几里得、海明或曼哈顿,在本例中会使用欧几里得,另外,种子值赋值为123。

然后拟合训练数据,如下:

KMeansModel mdl = trainer.fit(
        ignite,
        trainData,
        (k, v) -> v.getFeatures(),        
// Feature extractor.

        (k, v) -> v.getSurvivedClass()    
// Label extractor.

);

Ignite将数据保存为键-值(K-V)格式,因此上面的代码使用了值部分,目标值是Survived类,特征在其它列中。

将模型应用于测试数据

下一步,就可以用训练好的分类模型测试测试数据了,可以这样做:

int amountOfErrors = 0;
int totalAmount = 0;
int[][] confusionMtx = {{0, 0}, {0, 0}};

try (QueryCursor<Cache.Entry<Integer, TitanicObservation>> cursor = testData.query(new ScanQuery<>())) {
   for (Cache.Entry<Integer, TitanicObservation> testEntry : cursor) {
      TitanicObservation observation = testEntry.getValue();

      double groundTruth = observation.getSurvivedClass();
      double prediction = mdl.apply(new DenseLocalOnHeapVector(observation.getFeatures()));

      totalAmount++;
      if ((int) groundTruth != (int) prediction)
         amountOfErrors++;

      int idx1 = (int) prediction;
      int idx2 = (int) groundTruth;

      confusionMtx[idx1][idx2]++;

      System.out.printf(">>> | %.4f\t | %.0f\t\t\t|\n", prediction, groundTruth);
   }
}

确定含混矩阵和模型的准确性

下面,就可以通过对测试数据中的真实分类和模型进行的分类进行对比,来确认模型的真确性。

代码运行之后,输出如下:

>>> Absolute amount of errors 56

>>> Accuracy 0.6084

>>> Precision 0.5865

>>> Recall 0.9873

>>> Confusion matrix is [[78, 55], [1, 9]]

这个初步的结果可不可以改进?可以尝试的是对特征的衡量,在Ignite和Scikit-learn中,可以使用MinMaxScaler(),然后会给出如下的输出:

>>> Absolute amount of errors 29

>>> Accuracy 0.7972

>>> Precision 0.8205

>>> Recall 0.8101

>>> Confusion matrix is [[64, 14], [15, 50]]

作为进一步分析的一部分,还应该研究幸存与否和年龄和性别之间的关系。

总结

通常来说,k-均值聚类并不适合监督学习任务,但是如果分类很容易,这个方法还是有效的。对于本例来说,关注的就是是否幸存。

© 著作权归作者所有

李玉珏

李玉珏

粉丝 395
博文 80
码字总数 151127
作品 0
沈阳
架构师
私信 提问
加载中

评论(4)

_凤求凰_
_凤求凰_
看不懂看不懂。。
李玉珏
李玉珏 博主

引用来自“久永”的评论

看的人多,懂的人少。
哈哈哈

如果有需求,可以和我们联系!
sofn
sofn
厉害,有空深入研究下
久永
久永
看的人多,懂的人少。
哈哈哈
在Ignite中使用线性回归算法

在本系列前面的文章中,简单介绍了一下Ignite的机器学习网格,下面会趁热打铁,结合一些示例,深入介绍Ignite支持的一些机器学习算法。 如果要找合适的数据集,会发现可用的有很多,但是对于...

李玉珏
2018/11/22
330
0
Apache Ignite 2.5.0 版本发布,千级节点伸缩性

Apache Ignite 2.5: 千级节点伸缩性 Apache Ignite的用户通常知道的两个关键点是-扩展性和性能。在很多分布式系统的整个生命周期中,通常会不停地改进性能,而对扩展性相关的改进次数,会比较...

李玉珏
2018/06/01
1.9K
10
在Ignite中使用k-最近邻(k-NN)分类算法

在本系列前面的文章中,简单介绍了一下Ignite的线性回归算法,下面会尝试另一个机器学习算法,即k-最近邻(k-NN)分类。该算法基于对象k个最近邻中最常见的类来对对象进行分类,可用于确定类成...

李玉珏
2018/11/28
367
0
全面对比,深度解析 Ignite 与 Spark

经常有人拿 Ignite 和 Spark 进行比较,然后搞不清两者的区别和联系。Ignite 和 Spark,如果笼统归类,都可以归于内存计算平台,然而两者功能上虽然有交集,并且 Ignite 也会对 Spark 进行支...

编辑部的故事
2018/09/13
4K
6
搭建第一个Ignite集群时的注意事项

开发者在搭建第一个Ignite集群时,常常会遇到各种障碍,社区在收集了各种常见问题后,整理了一份检查清单帮助开发者,总之,本文的目的是帮助开发者在一开始就搭建一个正常的集群,走在正确的...

李玉珏
2019/03/27
1.8K
3

没有更多内容

加载失败,请刷新页面

加载更多

微盟被员工删库,这事到底多严重?该如何解决?

此举直接给公司带来数10亿的市值蒸发损失!在这个"远程办公”的节骨眼出事了。竟然是因为内部人员因个人精神、生活等原因对公司数据库进行了恶意的破坏! 面对这种情况我们应该如何解决呢? ...

欢乐马在开源
5分钟前
33
0
浅谈Chatbot的架构模型和响应机制

不知您是否已注意到:人工智能已经不再是少数科技公司的初级原型产品了。在许多服务类行业中,带有人工智能的聊天机器人(Chatbot)正在逐步取代人工客服,提供及时、周到、互动的服务。通过机...

Java进阶程序员xx
7分钟前
31
0
IT 老程序员的重要性

很多单位,会认为程序员年龄大了,不能高强度工作,价格比新人高,用新人便宜。 新闻上 各种IT企业各种 比如删库,传密码到git等等。不用想,大多都是新人。 不是不用新人,新人经验的积累是...

mellen
11分钟前
8
0
全文搜索引擎 Elasticsearch 入门:集群搭建

本文主要介绍什么是 ElasticSearch 以及为什么需要它,如何在本机安装部署 ElasticSearch 实例,同时会演示安装 ElasticSearch 插件,以及如何在本地部署多实例集群,方便在日后学习分布式相...

武培轩
12分钟前
17
0
Redis的两种持久化方式

RDB 我们所谓的RDB持久化就是指的讲当前进程的数据生成快照存入到磁盘中,触发RDB机制又分为手动触发与自动触发 AOF AOF持久化是以独立的日志记录每次写命令,重启Redis的时候再重新执行AOF...

无名氏的程序员
13分钟前
17
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部