西瓜书课后11.1(Relief算法)

题目

试编程实现Relief算法,并考察其在西瓜数据集3.0上的运行结果。

分析

Relief是一种过滤式特征选择方法。简单来说就是利用这种方法可以计算出各个特征子集的重要性。我们用 δ j \delta^j δj来度量 j j j属性的重要程度,公式为 δ j = ∑ − d i f f ( x i j , x i , n h j ) 2 + d i f f ( x i j , x i , n m j ) 2 \delta^j = \sum-diff(x_i^j,x^j_{i,nh})^2+diff(x_i^j,x^j_{i,nm})^2 δj=diff(xij,xi,nhj)2+diff(xij,xi,nmj)2。其中 x i j x_i^j xij第i个样本在属性j上的取值。 x i , n h x_{i,nh} xi,nh表示与第i个样本类别相同且距离最近的样本,称为“猜中近邻”; x i , n m x_{i,nm} xi,nm表示与第i个样本类别不同且最近的样本,称为“猜错近邻”。得到这两个点之后,分别计算其与 x i x_i xi的j属性上的距离,然后带入公式。可以这样理解公式,样本在j上的值与“猜中近邻”在j上的值越相近越好,与“猜错近邻”上的值越远越好。

代码

import numpy as np
import matplotlib.pyplot as plt

# 特征字典,后面用到了好多次,干脆当全局变量了
featureDic = {
    '色泽': ['浅白', '青绿', '乌黑'],
    '根蒂': ['硬挺', '蜷缩', '稍蜷'],
    '敲声': ['沉闷', '浊响', '清脆'],
    '纹理': ['清晰', '模糊', '稍糊'],
    '脐部': ['凹陷', '平坦', '稍凹'],
    '触感': ['硬滑', '软粘']}


def getDataSet():
    """
    get watermelon data set 3.0 alpha.
    :return: 编码好的数据集以及特征的字典。
    """
    dataSet = [
        ['青绿', '蜷缩', '浊响', '清晰', '凹陷', '硬滑', 0.697, 0.460, 1],
        ['乌黑', '蜷缩', '沉闷', '清晰', '凹陷', '硬滑', 0.774, 0.376, 1],
        ['乌黑', '蜷缩', '浊响', '清晰', '凹陷', '硬滑', 0.634, 0.264, 1],
        ['青绿', '蜷缩', '沉闷', '清晰', '凹陷', '硬滑', 0.608, 0.318, 1],
        ['浅白', '蜷缩', '浊响', '清晰', '凹陷', '硬滑', 0.556, 0.215, 1],
        ['青绿', '稍蜷', '浊响', '清晰', '稍凹', '软粘', 0.403, 0.237, 1],
        ['乌黑', '稍蜷', '浊响', '稍糊', '稍凹', '软粘', 0.481, 0.149, 1],
        ['乌黑', '稍蜷', '浊响', '清晰', '稍凹', '硬滑', 0.437, 0.211, 1],
        ['乌黑', '稍蜷', '沉闷', '稍糊', '稍凹', '硬滑', 0.666, 0.091, 0],
        ['青绿', '硬挺', '清脆', '清晰', '平坦', '软粘', 0.243, 0.267, 0],
        ['浅白', '硬挺', '清脆', '模糊', '平坦', '硬滑', 0.245, 0.057, 0],
        ['浅白', '蜷缩', '浊响', '模糊', '平坦', '软粘', 0.343, 0.099, 0],
        ['青绿', '稍蜷', '浊响', '稍糊', '凹陷', '硬滑', 0.639, 0.161, 0],
        ['浅白', '稍蜷', '沉闷', '稍糊', '凹陷', '硬滑', 0.657, 0.198, 0],
        ['乌黑', '稍蜷', '浊响', '清晰', '稍凹', '软粘', 0.360, 0.370, 0],
        ['浅白', '蜷缩', '浊响', '模糊', '平坦', '硬滑', 0.593, 0.042, 0],
        ['青绿', '蜷缩', '沉闷', '稍糊', '稍凹', '硬滑', 0.719, 0.103, 0]
    ]

    features = ['色泽', '根蒂', '敲声', '纹理', '脐部', '触感', '密度', '含糖量']
    # # 每种特征的属性个数
    # numList = []  # [3, 3, 3, 3, 3, 2]
    # for i in range(len(features) - 2):
    #     numList.append(len(featureDic[features[i]]))

    dataSet = np.array(dataSet)
    return dataSet, features


def getDiff(dataSet, i, j, mode=""):
    """
    得到数据集dataSet中第i个数据的第j个属性值与其"猜中近邻"第j个属性值的距离。
    对于离散型的属性j,若第i个样本的j属性值与其"猜中近邻"的j属性值相同则距离为0,反之为1。
    对于连续型的属性j,直接计算差的绝对值。
    :param mode:        "nh":猜中近邻。 "nm":猜错近邻
    :param dataSet:     数据集
    :param i:           第i个数据
    :param j:           第j个属性
    :return:            第i个数据的第j个属性值与其"猜中近邻"第j个属性值的距离
    """
    exDataSet = None
    if mode == 'nh':
        exDataSet = dataSet[dataSet[:, -1] == dataSet[i][-1]]
    if mode == 'nm':
        exDataSet = dataSet[dataSet[:, -1] != dataSet[i][-1]]

    dist = np.inf
    if j < 6:               # 前六个为离散型数据,后两个是连续型数据。
        dist = 1            # 对于离散型数据,初始dist为1,当遇到相同的j属性值时,置零。
        for k in range(len(exDataSet)):
            if k == i:      # 遇到第i个样本跳过。
                continue
            if exDataSet[k][j] == dataSet[i][j]:
                dist = 0
                break
    else:
        for k in range(len(exDataSet)):
            if k == i:
                continue
            sub = abs(float(exDataSet[k][j]) - float(dataSet[i][j]))
            if sub < dist:
                dist = sub
    return dist


def Relief(dataSet):
    """
    计算Relief度量。
    :param dataSet:
    :return:
    """
    m, n = dataSet.shape
    r = []  # 相关统计量
    for j in range(n - 1):
        rj = 0
        for i in range(m):
            diffNh = getDiff(dataSet, i, j, mode='nh')
            diffNm = getDiff(dataSet, i, j, mode='nm')
            rj += -(diffNh**2) + (diffNm**2)
        r.append(rj)

    return r


def main():
    dataSet, features = getDataSet()
    rf = np.array(Relief(dataSet))
    index = rf.argsort()
    print(rf[index])
    print(np.array(features)[index])


if __name__ == '__main__':
    main()

输出结果

经过了从小到大的排序:
在这里插入图片描述
对应属性越大的度量值表示,其样本与同类的样本离得近,与不同类的样本离得远,也以为着这种属性更好。可以通过这种方法选择更好的属性,即过滤式选择特征。

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值