2011-04-09 53 views
2

许多数据挖掘算法/策略使用数据记录的矢量表示来模拟数据的空间表示(如支持向量机)。如何将包含非数字特征的数据记录表示为向量(数学,NOT C++向量)?

我的麻烦来自于如何表示数据集中的非数字特征。我的第一个想法是为具有从1到n的数字(其中n是特征数量)的特征“混淆”每个可能的值。

在做一些研究时,我发现一个建议是,当处理具有少量可能值的特征时,应该使用长度为n的位串,其中每个位表示不同的值,并且只有一个位对应于被存储的值被翻转。我可以看到,在理论上如何使用这种方法来节省内存,其功能的可用值比用于在目标系统上存储整数值的位数少,但我正在使用的数据集对于各种功能具有许多不同的值所以我不认为这个解决方案会对我有所帮助。

在向量中表示这些值的一些可接受的方法是什么?何时每个策略都是最佳选择?

回答

0

所以有一个约定来做到这一点。以示例显示比解释要容易得多。

假设你从你的网站分析应用程序收集,组描述每个访问者网站指标:

  1. 性/性别

  2. 采集通道

  3. 论坛参与度

  4. acco UNT型

每个这些是分类变量(又名因子)而不是连续的变量(例如,总会话时间或帐户年龄)。

# column headers of raw data--all fields are categorical ('factors') 
col_headers = ['sex', 'acquisition_channel', 'forum_participation_level', 'account_type'] 

# a single data row represents one user 
row1 = ['M', 'organic_search', 'moderator', 'premium_subscriber'] 

# expand data matrix width-wise by adding new fields (columns) for each factor level: 
input_fields = [ 'male', 'female', 'new', 'trusted', 'active_participant', 'moderator', 
       'direct_typein', 'organic_search', 'affiliate', 'premium_subscriber', 
       'regular_subscriber', 'unregistered_user' ] 

# now, original 'row1' above, becomes (for input to ML algorithm, etc.) 
warehoused_row1 = [1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0] 

对于我来说,这种转换技术似乎比将每个变量保持为单个列更明智。例如,如果你使用后者,那么你必须将三种类型的采集通道与它们的数字表示进行协调 - 即,如果自然搜索是“1”,那么应该是加法器2和direct_typein 3,反之亦然?

这种表示的另一个重要优点是,尽管宽度扩展,它仍然是数据的紧凑表示。 (在列扩展是实质的情况下 - 即一个字段是用户状态,这可能意味着1列变为50,稀疏矩阵表示显然是个好主意。)

对于这种类型的工作,我使用数值计算库NumPySciPy

从Python交互式提示:

>>> # create two data rows, representing two unique visitors to a Web site: 

>>> row1 = NP.array([0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0]) 

>>> row2 = NP.array([1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0]) 

>>> row1.dtype 
    dtype('int64') 
>>> row1.itemsize 
    8 

>>> # these two data arrays can be converted from int/float to boolean, substantially 
>>> # reducing their size w/ concomitant performance improvement 
>>> row1 = NP.array(row1, dtype=bool) 
>>> row2 = NP.array(row2, dtype=bool) 

>>> row1.dtype 
    dtype('bool') 
>>> row1.itemsize # compare with row1.itemsize = 8, above 
    1 

>>> # element-wise comparison of two data vectors (two users) is straightforward: 
>>> row1 == row2 # element-wise comparison 
    array([False, False, False, False, True, True, False, True, True, False], dtype=bool) 
>>> NP.sum(row1==row2) 
    5 

对于基于相似性的计算(例如k-最近邻),有用于由称为Tanimoto系数分类变量的扩展数据矢量特定指标。对于特定表示我在这里使用的,功能应该是这样的:

def tanimoto_bool(A, B) : 
    AuB = NP.sum(A==B) 
    numer = AuB 
    denom = len(A) + len(B) - AuB 
    return numer/float(denom) 

>>> tanimoto_bool(row1, row2) 
    0.25 
0

有没有“被广泛接受的答案”,我知道,这完全取决于你想要什么。

背后您的文章的主要思想是,一个国家的琐碎记忆表征可能是太占用大量内存。例如,要存储一个最多可以有四个状态的值,您将使用一个int(32位),但只能使用2位进行管理,所以可以少16倍。

但是,聪明的你一个向量的表示(即:紧凑型),时间越长会带你到代码/从/到平凡表示解码。

我做了一个项目,我代表了一个Connect-4板的状态,有两个双打(64比特),每个双人都拥有双盘编码。这是将状态存储为42个整数的巨大改进!我可以通过更小的内存占用来进一步探索。这通常是你想要的。

有可能通过的Connect-4的巧妙认识到它只有一个双码!我试了一下,程序变得很长,我恢复了使用2个双打而不是1个。该程序大部分时间用于代码/解码功能。这通常是你不想要的。

现在,因为你想要的答案,有一些准则:

  • 如果你可以存储一个字节的布尔只,然后将它们保存为布尔(语言/编译器相关的)。

  • 串连所有的小功能(3和256之间可能的值)的原始类型,如intdouble,long double或任何你的语言使用。然后编写函数来编码/解码,如果可能的话,使用bitshift运算符来提高速度。

  • 记住,可以有“很多”(超过256)个可能的值,是功能。

当然,这些不是绝对的。如果您有一个可以采用2^15值和另一个2^17值的功能,那么将它们连接成具有32位大小的原始类型。

TL; DR:有关内存消耗和速度之间的贸易。您需要根据您的问题

调整
相关问题