在kNN中处理不完整数据(数据稀疏性)

我正在尝试使用kNN创建一个简单的推荐系统。

假设我有一个表格:

User | Book1 | Book2 | Book3 | Book4 | Book5 | Book6 | Book7 |1    | 5     | ?     | 3     | ?     | 4     | 3     | 2     |2    | 3     | 4     | ?     | 2     | 3     | 4     | 2     |3    | 4     | 2     | 1     | ?     | ?     | 3     | 3     |4    | 2     | 5     | 3     | ?     | 4     | 1     | 1     |5    | 1     | 1     | 4     | 3     | 1     | ?     | 1     |6    | 5     | 2     | 5     | 4     | 4     | 2     | ?     |

所以,如果要找出用户1的可能得分,我考虑的是计算用户1阅读的书籍与其他用户的绝对差异。然后,我会使用这个差异来找出列表中与用户1最“接近”的用户。但在现实世界中,会有更多未知分数(?)。那么,在使用kNN时,我该如何处理这些未知分数呢?

我还没有任何代码,因为我还没有真正理解如何实现这个功能。

任何帮助都将不胜感激!


回答:

你没有“未知特征”,你有不完整的数据点。

这实际上是kNN中的一个众所周知的问题,并且有经过充分验证的方法来处理它。

虽然这个问题实际上是一个“不完整数据”问题,但在kNN的背景下,它通常(通常?)被称为稀疏性问题。

在实践中,构建kNN模型时的稀疏性问题,除了可能的有效存储/检索模型数据之外,是kNN的核心问题。

例如,考虑亚马逊的推荐引擎,其中产品评分为用户特征,构成,用户构成,要使这个矩阵100%完整,每个亚马逊客户都必须购买并评论亚马逊销售的每一件产品。这个矩阵的实际稀疏度必须超过95%。

最常见的方法(据我所知仍然是最先进的)被称为NNMA,或非负矩阵近似。这种技术也经常被错误地称为NNMF,其中F代表分解。(NNMA基于一种分解技术,但结果不是原始数据矩阵的因子。)我提到这一点是因为这个替代术语虽然不正确,但被广泛使用,所以我会在搜索引擎查询中包括它。

本质上,这种技术可以用来消除矩阵中的稀疏性,或者换句话说,填充缺失的单元格(即,第R行的顾客没有评论第C列的产品)。

你可以在Albert Au Yeung Ching-man的博客上找到一个完整的nnma实现,包括一个配套的教程(使用Python + NumPy)。

或者,有几个Python包(通过PyPI提供)包含了NNMA的打包代码。我只使用过其中一个,PyMF,你可以在Google Code上找到它。

为了让你了解NNMA是如何发挥作用的,这是我在Python + NumPy中实现的简单但完整的NNMA实现

import numpy as NPdef cf(q, v):    """ the cost function """    qv = (q - v)**2    return NP.sum(NP.sum(qv, axis=0))def nnma(d, max_iter=100):    x, y = d.shape    z = y    w = NP.random.rand(x, y)    h = NP.random.rand(y, z)    for i in range(max_iter):        wh = NP.dot(w, h)        cost = cf(d, wh)        if cost == 0:             break        hn = NP.dot(w.T, d)        hd = NP.dot(NP.dot(w.T, w), h)        h *= hn/hd        wn = NP.dot(d, h.T)        wd = NP.dot(NP.dot(w, h), h.T)        w *= wn/wd    return NP.dot(w, h)

要使用这个NNMA函数,只需传入一个2D数组(矩阵),对于每个缺失的单元格使用“0”(换句话说,你的数据矩阵,对于每个缺失的值插入一个“0”):

>>> d    # the original (sparse) data matrix with missing cells denoted by "0"s  array([[ 7.,  0.,  4.,  7.,  0.,  1.],         [ 3.,  9.,  7.,  3.,  1.,  7.],         [ 4.,  4.,  3.,  7.,  3.,  9.],         [ 4.,  8.,  0.,  9.,  2.,  1.],         [ 6.,  3.,  9.,  5.,  9.,  3.],         [ 6.,  1.,  4.,  4.,  1.,  0.],         [ 0.,  4.,  8.,  6.,  0.,  5.],         [ 9.,  0.,  6.,  0.,  5.,  2.],         [ 6.,  8.,  4.,  6.,  3.,  7.],         [ 3.,  6.,  3.,  8.,  7.,  2.]])>>> d1 = nnma(d)     # call nnma, passing in the original data matrix>>> d1    # the approximated data matrix with all missing values populated   array([[ 6.998,  0.29 ,  3.987,  7.008,  0.292,  0.796],          [ 2.989,  8.92 ,  6.994,  3.02 ,  1.277,  7.053],          [ 4.007,  4.496,  2.999,  7.01 ,  3.107,  8.695],          [ 4.005,  8.019,  0.254,  9.002,  1.917,  0.89 ],          [ 5.998,  3.014,  9.001,  4.991,  8.983,  3.052],          [ 5.992,  1.077,  4.007,  3.976,  0.753,  0.464],          [ 0.346,  3.436,  7.993,  5.988,  0.194,  5.355],          [ 9.001,  0.124,  5.997,  0.375,  5.02 ,  1.867],          [ 6.   ,  7.994,  3.998,  6.   ,  2.999,  7.009],          [ 2.995,  6.022,  3.001,  7.987,  6.939,  2.185]])

正如你所见,结果还不错,特别是对于一个非常简单的实现。所有缺失的项目都被填充了,其余的值与原始数据矩阵中的对应值非常接近,例如,原始数据矩阵中第0列第0行的值为7.0,在近似矩阵中为6.998。

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注