特征选择学习笔记

学习目标

掌握特征选择的基本原理及方法,实现特征的选择

1.特征选择原理

对于一个学习任务而言,有些特征很关键,但有些特征对于最后的分类可能并没有什么用,我们称前者为相关特征,后者为无关特征,特征选择是一个选择相关特征,去除无关特征的过程。

为什么要进行特征选择?

1.降维。 同PCA
2.减少任务的难度。 较少的干扰会降低任务的难度

无关特征不同于冗余特征,无关特征是指与学习任务无关的特征,而冗余特征是指可以从当前特征中推演出来的特征

去除冗余特征在很大程度上可以降低任务的难度,但是若冗余特征充当了中间变量,冗余特征的存在也是有益

常见的特征选择方法包括:

1.过滤式选择 2.嵌入式选择 3.包裹式选择

1.1 过滤式选择

过滤式选择是先进行特征选择,后进行训练器学习;即,特征选择与训练器学习是具有先后顺序

过滤式选择的方法采用Relief法,该方法设计了 “相关统计量” 来描述各个特征的重要程度

最终可以指定一个阈值,选择比阈值大的相关统计变量所对应的特征;或者直接选择前k大的相关统计变量对应的特征作为最终特征

确定相关统计变量的方法

1.在同类样本中找到距离最近的样本 x n h x_nh xnh作为”猜中近邻"
2.在不同类的样本中找到距离最近的样本 x n m x_nm xnm作为"猜错近邻“

根据公式:

− d i f f ( x i j , x n h j ) 2 + d i f f ( x i j , x n m j ) 2 -diff(x_i^j,x_{nh}^j)^2+diff(x_i^j,x_{nm}^j)^2 diff(xij,xnhj)2+diff(xij,xnmj)2

可求得样本 x i x_i xi在特征 j j j上的相关统计变量

若特征 j j j离散变量:

x i j = x n h j x_i^j=x_{nh}^j xij=xnhj时,diff=0
x i j ≠ x n h j x_i^j \neq x_{nh}^j xij=xnhj时,diff=1

若特征 j j j连续变量:

d i f f = ∣ x i j − x n h j ∣ diff=|x_i^j-x_{nh}^j| diff=xijxnhj

若当前问题为多分类问题,相关统计变量的公式可以转化为

− d i f f ( x i j , x n h j ) 2 + ∑ k ≠ p ( L k / L ) ∗ d i f f ( x i j , x n m j ) 2 -diff(x_i^j,x_{nh}^j)^2+\sum_{k\neq p} (L_k/L)*diff(x_i^j,x_{nm}^j)^2 diff(xij,xnhj)2+k=p(Lk/L)diff(xij,xnmj)2

此时的 x n m j x_{nm}^j xnmj为在类别 k k k上的猜错近邻( k k k不为样本 x i x_i xi的标签 p p p

实战

1.计算同类最近击中和非同类最近击中

#计算最近击中和最远击中
def caculate_distance(x,grap):
    distance={}
    for i in range(0,len(grap)):
        xj=np.array(list(grap.iloc[i]))
        x=np.array(x)#计算xj与x之间的距离
        if any(xj!=x):#若计算的样本不是x本身
            dis=np.sum(np.sqrt(np.square(xj-x)))#计算距离
            distance[dis]=xj
    distance=sorted(distance.items(),key=lambda x:x[0])
    return distance[0][1]
def caculate_hit_and_miss(x): 
    miss_all_categoral=[]
    hit=np.array([])
    for col,grap in data.groupby(by='花瓣种类'):
        if col==x[-1]:    #计算同类最近击中距离
            hit=caculate_distance(x,grap)
        else:
            mis=caculate_distance(x,grap)#计算非同类最近击中距离
            miss_all_categoral.append((len(grap)/len(data),mis))
    return hit,miss_all_categoral

2.计算相关统计量

def caculate_statistical(x,hit,miss):
    statisitical=[]
#     形如[(0.3333333333333333, array([5.1, 2.5, 3. , 1.1, 2. ]))]
    for i in range(0,len(hit)-1):#对于第i个特征
        a=-np.square(abs(x[i]-hit[i]))#计算同类相关量
        b=0
        for j in range(0,len(miss)):   #计算非同类相关量
            b+=np.square(abs(miss[j][1][i]-x[i]))*miss[j][0]
        statisitical.append(a+b)   
    return statisitical   

3.分别汇总各特征 在所有样本上的的相关统计量之和

def filter_chioce():  
    all_statistical=[]
    for i in range(0,len(data)):
        hit,miss=caculate_hit(data.iloc[i])#计算对于样本x的最近击中和最远击中
        all_statistical.append(caculate_statistical(data.iloc[i],hit,miss))
    result=np.array(all_statistical).sum(axis=0)
    return result

4.得到结果

result=filter_chioce()
result=DataFrame(result,column=['花萼长度', '花萼宽度', '花瓣长度', '花瓣宽度'])

在这里插入图片描述
可以看出,花瓣长度与花瓣宽度的相关统计变量较大,特征对分类过程的贡献较大

1.2 嵌入式选择

嵌入式选择是指将训练器学习的过程与特征选择的过程融为一体,最有代表性的嵌入式选择就是神经网络的误差传播过程

实战

for epoch in range(iter):
    print(".......")
    for step,(x,y) in enumerate(train_db):
        #x:[b,28,28]
        x=tf.reshape(x,[-1,784])
        with tf.GradientTape() as tape:
            out=net(x)
            #out:[b,10]
            #y:[b]
            y=tf.one_hot(y,depth=10)
            loss_mse=tf.reduce_mean(tf.losses.MSE(y,out))
            loss_ce=tf.reduce_mean(tf.losses.categorical_crossentropy(y,out,from_logits=True))
        grad=tape.gradient(loss_ce,net.trainable_variables)#求解梯度,进行优化器优化
        optimizer.apply_gradients(zip(grad,net.trainable_variables))
        if step % 20==0:
            print("epoch={0},loss={1}".format(epoch,loss_ce))

    test_accurancy=0
    print("testing.......")
    for step,(x_test,y_test) in enumerate(test_db):
        x_test= tf.reshape(x_test, [-1, 784])
        y_test=tf.cast(y_test,tf.int64)
        test_out=net(x_test)
        #test_out:[b,10]
        #y_test:[b]
        test_out=tf.nn.softmax(test_out,axis=1)
        test_out=tf.argmax(test_out,axis=1)
        # test_out:[b]
        acc=tf.reduce_mean(tf.cast(tf.equal(test_out,y_test),dtype=tf.float32))
        test_accurancy+=float(acc)
    test_accurancy=test_accurancy/step
    print("epoch={0},test_accurancy={1}".format(epoch, test_accurancy))

1.3 包裹式选择

包裹式选择是指根据训练器的学习结果来选择特征,包裹式特征选择可以为学习器选择 “量身定做” 的特征子集

包裹式选择的学习效果一般比过滤式选择要好,但是包裹式选择在选择特征的过程中需要多次训练学习器,计算开销比较大

实战

data1=np.genfromtxt('iris.data.txt',delimiter=',')
data=data1[:,:4]
labels=data1[:,-1]
m,n=data.shape
numstep=10  #确定步长
best_state={}
best_predict_labels=np.ones((m,1))
min_error=np.inf
data=np.mat(data)#获得数据
labels=np.mat(labels)

for i in range(0,n):#遍历所有的特征
    max_num=max(data[:,i])
    min_num=min(data[:,i])
    stepsize=(max_num-min_num)/numstep  #求解当前列所需要走过的步数
    for j in range(-1,int(numstep+1)):
        thresh=(min_num+j*stepsize)#获得阈值,注意阈值的求法
        for flag in ['less','great']:
            predict_labels=weakclassifier(data,i,flag,thresh)#训练弱分类器,找到最好的分类方法
            error=np.mat(np.ones((m,1)))#定义误差矩阵
            error[labels.T==predict_labels]=0#如果预测对了就是0
            weighted_error=(D.T*error)  #公式中是按照加权的方法构造的矩阵
#        if weighted_error<min_error :#如果说当前的错误率是最小的话
                min_error=weighted_error
                best_state['dim']=i
                best_state['thresh']=thresh
                best_state['flag']=flag
                best_predict_labels=predict_labels.copy()
print('best character:',best_state['dim'])
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值