维数灾难的简单验证

上数据挖掘课的时候,有点好奇为什么数据维数高时最近邻无意义,现在简单验证了一下

数据模拟

假定所有数据的每一维特征都在 [ 0 , 1 ) [0,1) [0,1)内,利用numpy能方便地生成这样的数据:

def generate_data(size, d):
    return np.random.random((size,d))

开始验证

距离计算方式采用欧氏距离:

def compute_distance(p1, p2):
    return np.sqrt(np.sum(np.square(p1 - p2)))
尝试1

计算数据集中任意两点的最大距离数据集中样本点之间的平均距离,发现随着维数增加,这两个值也在随之增加。(不是说样本之间的差异性会变小吗?)
但是想一下,就能明白了:
维数为 1 1 1时,最大距离为 1 = 1 \sqrt{1}=1 1 =1,维数为 2 2 2时,最大距离为 1 + 1 = 2 \sqrt{1+1}=\sqrt{2} 1+1 =2 n n n维的最大距离为 n \sqrt{n} n . 尽管样本点不一定能使最大距离能取到,但距离的取值范围发生了变化—它变大了
于是我们可以得出结论距离的绝对大小关系不能反映出问题

尝试2

问题的关键在于这些距离是不是变得相似了,而不是这些距离是不是变小了。Kevin Beyer在论文中写道:当维数趋于极限值时,查询点到数据集中所有点的距离都相等。以此可以想到一个新的验证思路:
随机取一个样本点,计算其他样本点到该点的距离,并计算这些距离的方差
结果又出问题了,好像并没有什么规律
方差-维数
现在思考一个问题:
简单数据集 d 1 = 0.9 , 1.1 d_{1}=0.9,1.1 d1=0.9,1.1 v a r 1 = 0. 1 2 + 0. 1 2 2 var_{1}=\frac{0.1^{2}+0.1^{2}}{2} var1=20.12+0.12
d 2 = 1.85 , 2.15 d_{2}=1.85,2.15 d2=1.85,2.15 v a r 2 = 0.1 5 2 + 0.1 5 2 2 var_{2}=\frac{0.15^{2}+0.15^{2}}{2} var2=20.152+0.152
显然 v a r 1 &lt; v a r 2 var_{1}&lt;var_{2} var1<var2,但是实际上 d 1 d_{1} d1中样本与均值的相差百分比是 0.1 1 \frac{0.1}{1} 10.1 d 2 d_{2} d2则是 0.15 2 \frac{0.15}{2} 20.15.
也就是说 d 2 d_{2} d2相差的幅度更小

尝试3

能不能把数据均一化一下呢?以消除数字大小对变化幅度的影响?一个简单的想法是除以最大距离,这样所有数据的范围就能被限定在 [ 0 , 1 ) [0,1) [0,1)内,即:
随机取一个样本点,计算其他样本点到该点的距离,并除以最大距离,计算这个结果的方差

def test_sample(data):
    idx = np.random.randint(len(data))
    distance = []
    max_distance = None
    for i in range(len(data)):
        if i != idx:
            d = compute_distance(data[i], data[idx])
            distance.append(d)
            if max_distance is None or d > max_distance:
                max_distance = d
    distance = np.array(distance)
    return distance/max_distance 

再来看看结果:
偏差-维数
然后在不同大小的数据集上测试:
偏差-位数 比较

结论

当数据维数从 0 0 0~ 10 10 10变化时,查询点到其他样本点的距离以极快的速度变得越来越相似。当数据维数趋近于无穷时,查询点到其他样本点的距离都相等,此时KNN已失去了效果
延伸思考:
计算距离相似度有没有更好的办法?
怎么证明数据维数趋近于无穷时,查询点到数据集中所有点的距离都相等?

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值