在结构化数据中经常遇到列表或交易等非结构化列,比较典型的案例如下,此时一个列表列会包含字符串 或 一个列表:

ID列     Tag列  
用户A    tag1, tag2, tag3  
用户B    tag3, tag5, tag6, tag10  
用户C    tag3, tag5, tag6, tag10  

如何对此类列进行编码和提取特征呢?本文将给出一些基础和进阶的解决方法。

方法1:进行基础统计

在进行编码时,最基础的想法是可以统计个数,个数的多少可以直观反应这列包含的信息的多少。

df['Tag列'].apply(len)  

当然可以直接进行统计列表长度,也可以先计算每个tag的频次,然后进行相应的统计。

  • 优点:实现简单,并没有增加维度;

  • 缺点:信息丢失较多

方法2:提取TFIDF

在进行编码的过程中,可以使用onehot对单个某个tag进行编码,又或者使用直接使用TFIDF进行编码。

  • CounterVecoter:计算TF

  • TFIDFVector:计算TF + IDF

from sklearn.feature_extraction.text import CountVectorizer  
from sklearn.feature_extraction.text import TfidfVectorizer  
  • 优点:可以对tag进行有效索引;

  • 缺点:增加特征维度;

方法3:TFIDF + LDA/SVD

进行次数编码容易造成维度爆炸,一种代替的方法是先进行TFIDF编码,然后进行降维:LDA、SVD或者t-SNE降维。

from sklearn.decomposition import PCA  
from sklearn.decomposition import LatentDirichletAllocation  
from sklearn.decomposition import TruncatedSVD  
  • 优点:维度更低,特征更加有区分性。

  • 缺点:降维需要额外的训练时间;

方法4:句子嵌入

词向量是一种非常有效的单词编码方法,可以对单词进行映射。我们可以参考无监督句子编码的方法,对tag进行嵌入,然后对多个tag进行聚合。

如果一个tag编码为100维度,则我们需要将任意多个tag都编码为100维度。这里的聚合方法包括:

  • Mean-pooling

  • Max-pooling

  • TFIDF-pooling

  • SIF Embedding

上述实现过程需要额外训练词向量,如果使用深度学习框架实现会更加快速。

  • 优点:维度更加可控,语义更加完整。

  • 缺点:不适用tag乱序的情况

方法5:频繁项聚类

对于tag列可以作为集合进行处理,可以参考频繁项挖掘的方法进行聚类操作。频繁项集聚类提供了一个减少维度,聚类之后的聚类类别可以单独当做类别变量。

相应簇由包含频繁项集,当然也可以使用文本聚类的方法,比如层次聚类。

  • 优点:可解释性强,维度低;

  • 缺点:需要额外编码,聚类更新困难

方法6:PageRank

在多个tag进行编码的过程,可以单独计算每个tag的IDF,也就是权重。当然我们也可以将多个tag组合在一起视为一个图。

比如tag1, tag2, tag3可以构建为一个三个节点的有向图,构建完成之后然后计算每个节点的权重。

通过PageRank可以计算得到每个tag的权重,也可以得到所有tag得到的图的核心节点。

  • 优点:tag权重有意义,可解释。

  • 缺点:适用于tag间存有向的情况。

方法7:minihash或者LSH

如果将tag列表当做集合看待,我们可以使用minihash进行对集合进行编码,然后使用LSH进行编码。LSH包含多次哈希,最终可以将包含相同tag的列表哈希得到相同的桶中。

  • 优点:适用于大规模和分布式数据集

  • 缺点:需要手动设计哈希函数

12-02 11:18