relief算法研究

最近由于工作需要,对数据进行降维处理,通过对各种算法的研究,想寻找一种比较理想的算法,处理数据维度,达到降维的目的,对PCA进行研究,但是PCA是对当前多维数据的空间变换,无法达到物理降维的目的,因此想选择物理降维的算法,因此对卡方算法和relief算法进行相关研究,这两种算法是对数据的物理降维,是特征选择的操作算法。

通过几天的查找资料,整理和总结一下内容:

个人总结:

relief算法是基于现有训练数据样本的预测算法。

即:需要有当前数据集,能够从中分辨出同类样本和不同类样本,然后,从不同分类中选择相关的样本数据,计算各个属性的相关权重。

这也是我开始比较迷茫的一点:不知道如何选择样本R,H,M。我从开始的观点是没有训练样本,是对未知数据集的特征选择。因此在算法的开始,无法选择样本R,H,M。后来同事提醒我,这是有训练样本数据的,从这个观点出发,可以很容易的获取R,H,M。

在以下算法代码中,使用了随机抽取R样本,根据距离获取H和随机抽取M样本的方式实现代码。

relief的算法相关原理:

Relief算法是一种特征权重算法(Feature weighting algorithms),根据各个特征和类别的相关性赋予特征不同的权重,权重小于某个阈值的特征将被移除。Relief算法中特征和类别的相关性是基于特征对近距离样本的区分能力。算法从训练集D中随机选择一个样本R,然后从和R同类的样本中寻找最近邻样本H,称为Near Hit,从和R不同类的样本中寻找最近邻样本M,称为NearMiss,然后根据以下规则更新每个特征的权重:如果RNear Hit在某个特征上的距离小于RNear Miss上的距离,则说明该特征对区分同类和不同类的最近邻是有益的,则增加该特征的权重;反之,如果RNear Hit在某个特征的距离大于RNear Miss上的距离,说明该特征对区分同类和不同类的最近邻起负面作用,则降低该特征的权重。以上过程重复m次,最后得到各特征的平均权重。特征的权重越大,表示该特征的分类能力越强,反之,表示该特征分类能力越弱。Relief算法的运行时间随着样本的抽样次数m和原始特征个数N的增加线性增加,因而运行效率非常高。

relief算法研究_第1张图片

个人代码:

	/**
	 * relief算法
	 */
	public void relief(){		
		
		matrix = new double[length][width];
		//将样本数据赋值到matrix中
		
		//权重值全部置为0
		weight = new double[n_vars];	
		for(int i = 0; i < n_vars; i++){
			weight[i] = 0.0;
		}
		//属性的最大值和最小值
		double[] max = new double[n_vars];
		double[] min = new double[n_vars];
		for(int i = 0; i < width; i++){
			for(int j = 0; j < length; j++){
				double d = matrix[j][i];
				if(d > max[i]){
					max[i] = d;
				}
				if(d < min[i]){
					min[i] = d;
				}
			}
		}		
		//随机抽样m次
		for(int i = 0; i < m; i++){
			//随机抽取样本R
			Random random = new Random();
			int R_index = random.nextInt(width);
			double[] R = new double[width];
			for(int index = 0; index < width; index++){
				R[index] = matrix[R_index][index];
			}
			//计算出距离样本R最近的样本和最远的样本
			double maxvalue = 0.0;
			double minvalue = 0.0;
			int maxrow = 0;
			int minrow = 0;
			double distince = 0.0;			
			for(int len = 0; len < length; len++){
				if(len != R_index){
					for(int wid = 0; wid < width; wid++){
						distince += Math.pow(R[wid]-matrix[len][wid], 2);
					}
					distince = Math.sqrt(distince);
					if(len == 0){
						maxvalue = distince;
						minvalue = distince;
					}
					if(distince > maxvalue){
						maxvalue = distince;
						maxrow = len;
					}
					if(distince < minvalue){
						minvalue = distince;
						minrow = len;
					}
				}
			}
			
			int H_index = minrow;
			double[] H = new double[width];
			for (int index = 0; index < width; index++) {
				H[index] = matrix[H_index][index];
			}
			int M_index = maxrow;
			double[] M = new double[width];
			for(int index = 0; index < width; index++){
				M[index] = matrix[M_index][index];
			}
			
			//relief计算权重			
			for(int j = 0; j < n_vars; j++){
				weight[j] = weight[j]-(Math.abs(R[j]-H[j])/(max[j]-min[j]))/m + (Math.abs(R[j]-M[j])/(max[j]-min[j]))/m;
			}
		}
		
		for(int i = 0; i < width; i++){
			System.out.println(weight[i]);
		}
	}


ReliefF作算法,可以处理多类别问题。该算法用于处理目标属性为连续值的回归问题。ReliefF算法在处理多类问题时,每次从训练样本集中随机取出一个样本R,然后从和R同类的样本集中找出Rk个近邻样本(near Hits),从每个R的不同类的样本集中均找出k个近邻样本(near Misses),然后更新每个特征的权重。

relief算法研究_第2张图片

个人代码:

在Relief算法中,对P(C)的处理,我使用1/t,t为不同类数量。

	//有t个不同类
	public int t;
	
	/**
	 * reliefF算法
	 */
	public void reliefF(){		
		
		matrix = new double[length][width];
		//将样本数据赋值到matrix中
		
		//权重值全部置为0
		weight = new double[n_vars];	
		for(int i = 0; i < n_vars; i++){
			weight[i] = 0.0;
		}
		//属性的最大值和最小值
		double[] max = new double[n_vars];
		double[] min = new double[n_vars];
		for(int i = 0; i < width; i++){
			for(int j = 0; j < length; j++){
				double d = matrix[j][i];
				if(d > max[i]){
					max[i] = d;
				}
				if(d < min[i]){
					min[i] = d;
				}
			}
		}
		//随机抽样m次		
		Map map = new HashMap();
		double[][] H = new double[k][width];
		double[][] M = new double[k][width];
		List lstM = new ArrayList();
		double[] R = new double[width];
		for(int i = 0; i < m; i++){
			//随机抽取样本R
			Random random = new Random();
			int R_index = random.nextInt(width);			
			for(int index = 0; index < width; index++){
				R[index] = matrix[R_index][index];
			}
			//计算所有数据到样本的距离
			for(int len = 0; len < length; len++){
				double distince = 0.0;
				int row = 0;
				if(len != R_index){
					for(int wid = 0; wid < width; wid++){
						distince += Math.pow(R[wid]-matrix[len][wid], 2);
					}
					distince = Math.sqrt(distince);
					row = len;
					map.put(distince, row);
				}
			}
			//对样本距离排序
			Set set = map.keySet();
			List lst = new ArrayList(set);
			Collections.sort(lst);
			//获取距离最近的k个样本作为H
			for(int a = 0; a < k; a++){
				double d = lst.get(a);
				int r = map.get(d);
				for(int b = 0; b < width; b++){
					H[a][b] = matrix[r][b];
				}
			}
			
			//假设有t个不同分类,在每个不同类中获取k个样本
			//在数据中随机获取k个样本作为M(C)
			for(int a = 0; a < t; a++){
				double[] RD = new double[width];
				//随机抽取样本
				Random rd = new Random();
				int id = rd.nextInt(width);
				while(true){
					if(id != R_index){
						break;
					}
					else{
						id = rd.nextInt(width);
					}
				}
				for(int index = 0; index < width; index++){
					R[index] = matrix[R_index][index];
				}
				//计算所有数据到样本的距离
				Map maprd = new HashMap();
				for(int len = 0; len < length; len++){
					double distince = 0.0;
					int row = 0;
					if(len != R_index){
						for(int wid = 0; wid < width; wid++){
							distince += Math.pow(R[wid]-matrix[len][wid], 2);
						}
						distince = Math.sqrt(distince);
						row = len;
						maprd.put(distince, row);
					}
				}
				//对样本距离排序
				Set setrd = map.keySet();
				List lstrd = new ArrayList(set);
				Collections.sort(lst);
				//获取不同类距离最近的k个样本作为				
				for(int q = 0; q < k; q++){
					double d = lst.get(q);
					int r = map.get(d);
					for(int p = 0; p < width; p++){
						M[q][p] = matrix[r][p];
					}
				}
				lstM.add(M);
			}
		
		}
		//计算H的diff
		double[] tmpval1 = new double[n_vars];
		double[] tmpval2 = new double[n_vars];
		for(int i = 0; i < n_vars; i++){
			for(int j = 0; j < k; j++){
				tmpval1[i] += Math.abs(R[i]-H[j][i])/(max[i]-min[i]);				
			}
		}
		//计算不同类的diff
		double[] value = new double[n_vars];
		for(double[][] d : lstM){			
			for(int i = 0; i < n_vars; i++){
				for(int j = 0; j < k; j++){					
					value[i] += Math.abs(R[i]-M[j][i])/(max[i]-min[i]);
				}
			}			
		}
		for(int i = 0; i < n_vars; i++){
			tmpval2[i] += value[i]/t;
		}
		//计算权重
		for(int j = 0; j < n_vars; j++){
			weight[j] = weight[j]- tmpval1[j]/(m*k) + tmpval2[j]/(m*k);
		}
		for(int i = 0; i < width; i++){
			System.out.println(weight[i]);
		}
	}

参考:

Relief算法在笔迹识别中的应用

http://blog.csdn.net/candy_candy_fighting/article/details/41448265

希望大家提出建议,完善算法代码。QQ:245008803,mail:[email protected]

你可能感兴趣的:(大数据)