spark结合Kmeans对数据标签化

概念:聚类算法是一种无监督学习任务,用于将对象分到具有高度相似性的聚类中.

举例:N个人有N多爱好,每个爱好提供出一个贡献值(或者称之为特征值),至于这个贡献值怎么得出目前不讨论.那么聚类算法就能实现根据这些特征值,把这N个人进行分组.

本人所在行业为轨道交通行业,致力于利用轴箱传感器采集到的数据进行故障诊断和预测.文中提到的数据源自真实采集数据.每行16个浮点型数值.

具体为: 最大值,最小值,平均值,均方值,有效值,方差,偏度,峭度,峰值,方根幅值,绝对平均值,波形指标,脉冲指标,裕度指标,峭度指标.

数据共计24000多条,假设人为复核,一条一条去过,那么必然浪费很多时间.那么如何才能更有效率呢?

答案自然是使用Kmeans对数据进行聚类.这里使用的数据已经清洗过,数据清洗概念不知者自行脑补.

接下来上代码

public void digest(String path) {
		SparkConf conf = new SparkConf().setAppName("K-means Example");
		conf.setMaster("local");
		JavaSparkContext sc = new JavaSparkContext(conf);
		// Load and parse data
		JavaRDD<String> data = sc.textFile(path);
		JavaRDD<Vector> parsedData = data.map(new Function<String, Vector>() {
			private static final long serialVersionUID = 1L;
			public Vector call(String s) {
				String[] sarray = s.split(" ");
				double[] values = new double[sarray.length];
				for (int i = 0; i < sarray.length; i++)
					values[i] = Double.parseDouble(sarray[i]);
				return Vectors.dense(values);
			}
		});
		parsedData.cache();

		// Cluster the data into two classes using KMeans
		int numClusters = 2;
		int numIterations = 20;
		KMeansModel clusters = KMeans.train(parsedData.rdd(), numClusters, numIterations);
		

		// Evaluate clustering by computing Within Set Sum of Squared Errors
		double WSSSE = clusters.computeCost(parsedData.rdd());
		System.out.println("Within Set Sum of Squared Errors = " + WSSSE);

		// Save and load model
		clusters.save(sc.sc(), "TrainningModel");
		sc.close();

	}

 第一步就是要对数据进行处理,并进行训练,最后保存模型.模型保存在了TrainningModel文件夹中.此时,我们已经有了训练后保存的模型,那么就可以拿这个模型来判定数据.具体判定方法如下

public void awardFrData(String path) {
		SparkConf conf = new SparkConf().setAppName("K-means Example");
		conf.setMaster("local");
		JavaSparkContext sc = new JavaSparkContext(conf);
		KMeansModel sameModel = KMeansModel.load(sc.sc(), "TrainningModel");
		JavaRDD<String> data = sc.textFile(path);
		JavaRDD<Vector> test = data.map(new Function<String, Vector>() {
			private static final long serialVersionUID = 1L;
			public Vector call(String s) {
				String[] sarray = s.split(" ");
				double[] values = new double[sarray.length];
				for (int i = 0; i < sarray.length; i++)
					values[i] = Double.parseDouble(sarray[i]);
				return Vectors.dense(values);
			}
		});
		JavaRDD<Integer> rst = sameModel.predict(test);
		rst.repartition(1).saveAsTextFile("Result");

	}

 上面代码将数据处理成RDD后,进行预测并返回了一个RDD,代码默认保存在了Result文件夹中.

打开Result文件夹中的part-00000文件,即可看到每行一个数字的数据.0和1.

最后,我们可以通过查看0,1标签的数据百分比来进行下一步的数据分析.

我在进行数据分析时,尝试对数据进行三类聚类话划分.发现0标签的数据占比在99%,1和2占比在1%左右.我提供的特征数据是用来诊断轴承是否故障的基本特征数据.当聚类算法把这些数据聚类后,很明显,那个1%的数据才是最可疑的数据.因为大多数时候,轴承是正常的,所以数据体现的也是相似的.

为了检验聚类真实效果,我特意将三类数据中各抽出一条进行图表对比.效果如下.



 其中Row24460是0标签,Row24462是1标签,Row24515是2标签.明显看出三组数据具有很明显的特征.

结论,在数据没有标签化之前,如果需要对数据分析.那么第一步是清洗数据,第二部是尝试对数据进行聚类.当然聚类也是一种数据清洗.在这两万多条数据中,我已经择出去了一条峭度指标达到两万多的数据.在使用聚类分析时,它被孤零零的划分为一类.我把视为异常数据.

因为这些数据采集过程中没有报出过故障,所以没有办法对其标签化.也就没有办法进行神经网络训练.但值得欣慰的是,使用Kmeans能够得出1%的数据与众不同,这个结果还是很让人满意的.

我接下来的任务就是通过尝试分析这1%的数据,对比原始数据的公里标,来复核是不是因为某段铁轨轨道波磨,或者有损伤导致的振动数据异常.

最后附上整理后的表格文件.所有对数据分析有兴趣的可以直接拿去使用.见附件.

猜你喜欢

转载自myten.iteye.com/blog/2281625