在Ignite中使用k-均值聚类算法
在本系列前面的文章中,简单介绍了一下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来执行这个拆分任务。
准备好训练和测试数据后,就可以编写应用了,本文的算法是:
- 读取训练数据和测试数据;
- 在Ignite中保存训练数据和测试数据;
- 使用训练数据拟合k-均值聚类模型;
- 将模型应用于测试数据;
- 确定含混矩阵和模型的准确性。
读取训练数据和测试数据
通过下面的代码,可以从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-均值聚类并不适合监督学习任务,但是如果分类很容易,这个方法还是有效的。对于本例来说,关注的就是是否幸存。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
vue-router中scrollBehavior的巧妙用法
问题:使用keep-alive标签后部分安卓机返回缓存页位置不精确问题 解决方案: <div id="app"> <keep-alive> <router-view v-if="$route.meta.keepAlive"></router-view> </keep-alive> <router-view v-if="!$route.meta.keepAlive"></router-view> </div> const router = new Router({ scrollBehavior(to, from, savedPosition) { if (savedPosition && to.meta.keepAlive) { return savedPosition; } return { x: 0, y:0 }; }, }); 前端全栈学习交流圈:866109386,面向1-3经验年前端开发人员,帮助突破技术瓶颈,提升思维能力 群内有大量PDF可供自取,更有干货实战项目视...
- 下一篇
几个简单的技巧让你写出的vue.js代码更优雅
本文参考自油管上某个国外大神的公开演讲视频,学习了一下觉得很不错,所以在项目中也使用了这些不错的技巧。 1. watch 与 computed 的巧妙结合 如上图,一个简单的列表页面。 你可能会这么做: created(){ this.fetchData() }, watch: { keyword(){ this.fetchData() } } 如果参数比较多,比如上图 关键字筛选, 区域筛选, 设备ID筛选, 分页数, 每页几条数据, 可能会是这样: data(){ return { keyword:'', region:'', deviceId:'', page:1 } }, methods:{ fetchData(paramrs={ keyword:this.keyword, region:this.region, deviceId:this.deviceId, page:this.page, }){ this.$http.get("/list",paramrs).then("do some thing") } }, created(){ this.fetchData() }, ...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2全家桶,快速入门学习开发网站教程
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- CentOS6,CentOS7官方镜像安装Oracle11G
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器
- CentOS7,CentOS8安装Elasticsearch6.8.6
- CentOS8编译安装MySQL8.0.19
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- 设置Eclipse缩进为4个空格,增强代码规范