特征选择算法之Relief算法python实现
Relief算法python實現
- 一、特征選擇算法簡介
- (一)子集搜索與評價
- (二)特征選擇分類
- 1. 過濾式特征選擇
- 2. 包裹式特征選擇
- 3. 嵌入式特征選擇
- 二、Relief算法簡介
- (一)原理
- (二)偽算法
- 三、Relief算法python實現
- (一)代碼
一、特征選擇算法簡介
對一個學習任務,給定它的數據屬性集,屬性即為“特征”。其中有些屬性對學習任務有用稱之為“相關特征”,有些屬性無用則稱之為“無關特征”。無關特征的存在不僅會在一定程度上加大數據集的冗余程度,還會在學習任務過程中造成不小的影響。因此,從給定的特征集合中選擇出相關特征子集非常必要,而這個過程,即為“特征選擇”。特征選擇有兩個顯著的好處,一是可以起到降維的作用,二是可以減小學習任務的訓練難度。
如何選擇出相關特征子集?窮舉顯然是不合適的。我們希望可以給它一個初始集合,稱之為“候選集合”,然后評價其的好壞,基于評價結果生成下一個候選集合,如此循環,直至無法找到更好的候選集合為止。當然這種方法容易讓結果陷入局部最優。那么采用這種方法,關鍵在于兩點:如何根據評價結果產生下一個候選特征子集?如何評價一個候選特征子集的好壞?下面將根據此作簡單介紹。
(一)子集搜索與評價
第一個關鍵點是“子集搜索”問題,第二個關鍵點是“子集評價”問題。關于子集搜索,常見的方法有“前向搜索”、“后向搜索”、“雙向搜索”等。關于子集評價,方法之一是計算信息熵增益,以此作為評價標準。將特征子集搜索與子集評價結合起來,即可進行特征選擇。
(二)特征選擇分類
常見的特征選擇大致可分為三類:過濾式、包裹式和嵌入式。其中,Relief算法針對二分類進行特征選擇,ReliefF算法針對多分類進行特征選擇,ReliefF算法詳細參見博文:https://blog.csdn.net/qq_40871363/article/details/86594578
1. 過濾式特征選擇
2. 包裹式特征選擇
3. 嵌入式特征選擇
本文主要對過濾式特征選擇算法進行python實現。
二、Relief算法簡介
待補充
(一)原理
待補充
(二)偽算法
待補充
三、Relief算法python實現
(一)代碼
代碼片
// An highlighted block # _*_ coding:utf8 _*_""" # 說明:特征選擇方法一:過濾式特征選擇(Relief算法) # 思想:先用特征選擇過程對初始特征進行"過濾",然后再用過濾后的特征訓練模型 # 時間:2019-1-14 # 問題: """import pandas as pd import numpy as np import numpy.linalg as la import random# 異常類 class FilterError:passclass Filter:def __init__(self, data_df, sample_rate, t, k):"""#:param data_df: 數據框(字段為特征,行為樣本):param sample_rate: 抽樣比例:param t: 統計量分量閾值:param k: 選取的特征的個數"""self.__data = data_dfself.__feature = data_df.columnsself.__sample_num = int(round(len(data_df) * sample_rate))self.__t = tself.__k = k# 數據處理(將離散型數據處理成連續型數據,比如字符到數值)def get_data(self):new_data = pd.DataFrame()for one in self.__feature[:-1]:col = self.__data[one]if (str(list(col)[0]).split(".")[0]).isdigit() or str(list(col)[0]).isdigit() or (str(list(col)[0]).split('-')[-1]).split(".")[-1].isdigit():new_data[one] = self.__data[one]# print '%s 是數值型' % oneelse:# print '%s 是離散型' % onekeys = list(set(list(col)))values = list(xrange(len(keys)))new = dict(zip(keys, values))new_data[one] = self.__data[one].map(new)new_data[self.__feature[-1]] = self.__data[self.__feature[-1]]return new_data# 返回一個樣本的猜中近鄰和猜錯近鄰def get_neighbors(self, row):df = self.get_data()row_type = row[df.columns[-1]]right_df = df[df[df.columns[-1]] == row_type].drop(columns=[df.columns[-1]])wrong_df = df[df[df.columns[-1]] != row_type].drop(columns=[df.columns[-1]])aim = row.drop(df.columns[-1])f = lambda x: eulidSim(np.mat(x), np.mat(aim))right_sim = right_df.apply(f, axis=1)right_sim_two = right_sim.drop(right_sim.idxmin())# print right_sim_two# print right_sim.values.argmax() # np.argmax(wrong_sim)wrong_sim = wrong_df.apply(f, axis=1)# print wrong_sim# print wrong_sim.values.argmax()# print right_sim_two.idxmin(), wrong_sim.idxmin()return right_sim_two.idxmin(), wrong_sim.idxmin()# 計算特征權重def get_weight(self, feature, index, NearHit, NearMiss):data = self.__data.drop(self.__feature[-1], axis=1)row = data.iloc[index]nearhit = data.iloc[NearHit]nearmiss = data.iloc[NearMiss]if (str(row[feature]).split(".")[0]).isdigit() or str(row[feature]).isdigit() or (str(row[feature]).split('-')[-1]).split(".")[-1].isdigit():max_feature = data[feature].max()min_feature = data[feature].min()right = pow(round(abs(row[feature] - nearhit[feature]) / (max_feature - min_feature), 2), 2)wrong = pow(round(abs(row[feature] - nearmiss[feature]) / (max_feature - min_feature), 2), 2)# w = wrong - rightelse:right = 0 if row[feature] == nearhit[feature] else 1wrong = 0 if row[feature] == nearmiss[feature] else 1# w = wrong - rightw = wrong - right# print wreturn w# 過濾式特征選擇def relief(self):sample = self.get_data()# print samplem, n = np.shape(self.__data) # m為行數,n為列數score = []sample_index = random.sample(range(0, m), self.__sample_num)print '采樣樣本索引為 %s ' % sample_indexnum = 1for i in sample_index: # 采樣次數one_score = dict()row = sample.iloc[i]NearHit, NearMiss = self.get_neighbors(row)print '第 %s 次采樣,樣本index為 %s,其NearHit行索引為 %s ,NearMiss行索引為 %s' % (num, i, NearHit, NearMiss)for f in self.__feature[0:-1]:w = self.get_weight(f, i, NearHit, NearMiss)one_score[f] = wprint '特征 %s 的權重為 %s.' % (f, w)score.append(one_score)num += 1f_w = pd.DataFrame(score)print '采樣各樣本特征權重如下:'print f_wprint '平均特征權重如下:'print f_w.mean()return f_w.mean()# 返回最終選取的特征def get_final(self):f_w = pd.DataFrame(self.relief(), columns=['weight'])final_feature_t = f_w[f_w['weight'] > self.__t]print final_feature_tfinal_feature_k = f_w.sort_values('weight').head(self.__k)print final_feature_kreturn final_feature_t, final_feature_k# 幾種距離求解 def eulidSim(vecA, vecB):return la.norm(vecA - vecB)def cosSim(vecA, vecB):""":param vecA: 行向量:param vecB: 行向量:return: 返回余弦相似度(范圍在0-1之間)"""num = float(vecA * vecB.T)denom = la.norm(vecA) * la.norm(vecB)cosSim = 0.5 + 0.5 * (num / denom)return cosSimdef pearsSim(vecA, vecB):if len(vecA) < 3:return 1.0else:return 0.5 + 0.5 * np.corrcoef(vecA, vecB, rowvar=0)[0][1]if __name__ == '__main__':data = pd.read_csv('西瓜數據集3.csv')[['色澤', '根蒂', '敲擊', '紋理', '臍部', '觸感', '密度', '含糖率', '類別']]print dataf = Filter(data, 1, 0.8, 6)f.relief()# f.get_final()總結
以上是生活随笔為你收集整理的特征选择算法之Relief算法python实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 8 旋转数组的最小数字
- 下一篇: 数论中的偶数阶Abel群的阶