使用 Groovy 和 Apache Ignite 进行威士忌聚类

作者: Paul King
发布时间: 2022-10-27 11:13AM


在之前的 博客文章 中,Ignite logo 我们研究了使用 Apache Wayang(孵化器)和 Apache Spark 来扩展 k-means 聚类算法。让我们看看另一种用于扩展此问题的有用技术,Apache Ignite。Ignite 团队最近发布了 新版本,但早期版本也适用于我们的示例。

在我们开始之前,快速回顾一下问题。

威士忌聚类

Groovy logo 此问题探讨了寻找完美的单一麦芽苏格兰威士忌。来自 86 家酿酒厂 生产的威士忌,根据 12 个标准(酒体、甜味、麦芽味、烟熏味、果味等)由专家品尝师进行了评级。我们将使用 K-means 算法来计算质心。

whiskey_bottles K-means 是一种标准的数据科学聚类技术。在我们的案例中,它将具有相似特征(根据 12 个标准)的威士忌分组到集群中。如果我们有喜欢的威士忌,我们很有可能可以通过查看同一集群中的其他实例来找到类似的威士忌。如果我们想要尝试不同的口味,可以查看其他集群中的威士忌。质心是集群中部的名义“点”。对我们来说,它反映了该集群中威士忌每个标准的典型衡量标准。

Apache Ignite

Apache Ignite 是一个用于高性能计算的分布式数据库,具有内存级速度。它使节点集群(或网格)看起来像内存中的缓存。这种解释极大地简化了 Ignite 的功能集。Ignite 可用作

  • 具有特殊功能的内存中缓存,例如 SQL 查询和事务属性

  • 在多个分布式数据库之上具有高级读写穿透功能的内存中数据网格

  • 超快且水平可扩展的内存中数据库

  • 用于自定义或内置任务(包括机器学习)的高性能计算引擎

我们主要使用最后一种功能。Ignite 的机器学习 API 针对分类、回归、聚类和推荐等领域,具有专门构建的、集群感知的机器学习和深度学习算法。我们将使用其库中的分布式 K-means 聚类 算法。 Machine Learning _ Ignite Documentation

实现细节

Apache Ignite 具有用于将数据读入缓存的特殊功能。我们可以使用IgniteDataStreamerIgniteCache.loadCache() 从文件、流源、各种数据库源等加载数据。这在使用集群时尤其相关。

对于我们的示例,我们的数据存储在一个相对较小的 CSV 文件中,我们将使用单个节点,因此我们将使用 Apache Commons CSV 读取数据。

var file = getClass().classLoader.getResource('whiskey.csv').file as File
var rows = file.withReader {r -> RFC4180.parse(r).records*.toList() }
var data = rows[1..-1].collect{ it[2..-1]*.toDouble() } as double[][]

我们将使用代码配置单个节点 Ignite 数据缓存(但在更复杂的场景中,可以将详细信息放在配置文件中)。

var cfg = new IgniteConfiguration(
        peerClassLoadingEnabled: true,
        discoverySpi: new TcpDiscoverySpi(
                ipFinder: new TcpDiscoveryMulticastIpFinder(
                        addresses: ['127.0.0.1:47500..47509']
                )
        )
)

我们将创建一些辅助变量。

var features = ['Body', 'Sweetness', 'Smoky', 'Medicinal', 'Tobacco',
                'Honey', 'Spicy', 'Winey', 'Nutty', 'Malty', 'Fruity', 'Floral']
var pretty = this.&sprintf.curry('%.4f')
var dist = new EuclideanDistance()
var vectorizer = new DoubleArrayVectorizer().labeled(FIRST)

现在我们启动节点,填充缓存,运行我们的 k-means 算法,并打印结果。

Ignition.start(cfg).withCloseable { ignite ->
    println ">>> Ignite grid started for data: ${data.size()} rows X ${data[0].size()} cols"
    var dataCache = ignite.createCache(new CacheConfiguration<Integer, double[]>(
          name: "TEST_${UUID.randomUUID()}",
          affinity: new RendezvousAffinityFunction(false, 10)))
    data.indices.each { int i -> dataCache.put(i, data[i]) }
    var trainer = new KMeansTrainer().withDistance(dist).withAmountOfClusters(5)
    var mdl = trainer.fit(ignite, dataCache, vectorizer)
    println ">>> KMeans centroids:\n${features.join(', ')}"
    var centroids = mdl.centers*.all()
    centroids.each { c -> println c*.get().collect(pretty).join(', ') }
    dataCache.destroy()
}

结果

以下是输出。

[18:13:11]    __________  ________________
[18:13:11]   /  _/ ___/ |/ /  _/_  __/ __/
[18:13:11]  _/ // (7 7    // /  / / / _/
[18:13:11] /___/\___/_/|_/___/ /_/ /x___/
[18:13:11]
[18:13:11] ver. 2.14.0#20220929-sha1:951e8deb
[18:13:11] 2022 Copyright(C) Apache Software Foundation
...
[18:13:11] Configured plugins:
[18:13:11]   ^-- ml-inference-plugin 1.0.0
[18:13:14] Ignite node started OK (id=f731e4ab)
...
>>> Ignite grid started for data: 86 rows X 13 cols
>>> KMeans centroids
Body, Sweetness, Smoky, Medicinal, Tobacco, Honey, Spicy, Winey, Nutty, Malty, Fruity, Floral
2.7037, 2.4444, 1.4074, 0.0370, 0.0000, 1.8519, 1.6667, 1.8519, 1.8889, 2.0370, 2.1481, 1.6667
1.8500, 1.9000, 2.0000, 0.9500, 0.1500, 1.1000, 1.5000, 0.6000, 1.5500, 1.7000, 1.3000, 1.5000
1.2667, 2.1333, 0.9333, 0.1333, 0.0000, 1.0667, 0.8000, 0.5333, 1.8000, 1.7333, 2.2667, 2.2667
3.6667, 1.5000, 3.6667, 3.3333, 0.6667, 0.1667, 1.6667, 0.5000, 1.1667, 1.3333, 1.1667, 0.1667
1.5000, 2.8889, 1.0000, 0.2778, 0.1667, 1.0000, 1.2222, 0.6111, 0.5556, 1.7778, 1.6667, 2.0000
[18:13:15] Ignite node stopped OK [uptime=00:00:00.663]

我们可以在蜘蛛图中绘制质心特征。 Whiskey clusters with Apache Ignite

更多信息

  • 包含源代码的仓库:WhiskeyIgnite

  • 包含使用各种库(包括 Apache Commons CSV、Weka、Smile、Tribuo 等)的类似示例的仓库:Whiskey

  • 使用 Apache Spark 直接执行的类似示例,但使用 spark-mllib 库中的内置并行化 k-means,而不是手工制作的算法:WhiskeySpark