特征表示—动态词典

动态词典构造

  • 在文本分类中,在处理流程上一般都大致会包括以下步骤:
    1. 文本分词(含去停用词)
    2. 建立测试集词列表与类别映射
    3. 统计词的频率,按照某种方法计算词权重
    4. 选择策略提取(抽取)文本特征
    5. 构造分类器,训练
    6. 模型评估
      在步骤3和4中,目前有很多方法对文本进行特征表示,如TF-IDF,CHI权重计算,基于互信息,交叉熵等。这里我主要试着阐述一下动态词典来计算词权重,并构建向量来对文本进行特征表示。

在动态词典中,文本表示的词并不是像词袋模型那样----根据构建的词表[wd1,wd2,wd3,......],计算全文档集中的词的权重,最后对每一个训练文档进行词对应的权重赋值,构建一个高维的稀疏矩阵[0,0,0.342,0,0,0.1353,0,0,......]等等。

  • 构建文档分词列表与对应类别的映射关系

表示为:
[[类别1,类别3,类别2,类别3,.....]
[[词列表1],[词列表2],[词列表3],[词列表4],....]

category_mapping = {u'其他': 0, u'电子商务': 1, u'社交网络': 2}

def get_label_mapping(source):
    """ 载入标签映射表 """
    mapping = {}
    with open(source, 'rb') as f:
        for line in f:
            filename, label = line.decode('utf-8').split()
            mapping[filename] = category_mapping[label]
    return mapping

def get_data_mapping(source, stopwords):
    """ 载入数据隐射表 """
    mapping = {}
    for root, dirs, files in os.walk(source):
        for folder in dirs:
            raw_file = os.path.join(root, folder, 'raw_%s.txt' % folder)
            with open(raw_file, 'rb') as f:
                content = f.read().strip().decode('utf-8')
            mapping['raw_%s.txt' % folder] = cut(content, stopwords)
    return mapping

def get_filename_mapping(label_mapping, data_mapping):
    idx = 0
    idx_label = {}
    idx_data = {}
    for filename, label in label_mapping.iteritems():
        idx_label[idx] = label
        idx_data[idx] = data_mapping[filename]
        idx += 1
    return idx_label, idx_data
  • 统计构建文档集总词集{wd1:num1,wd2:num2,....}
def get_vocab(idx_data):
  """ 获取文档列表的总词集
  :param idx_data:
  :return:
  """
  vocab = defaultdict(int)
  for idx, words in idx_data.iteritems():
    for word in words:
        vocab[word] += 1
  return vocab
  • 构建动态词典
  1. 首先根据第一步中文档词列表与类别映射表,按照类别,统计每个类别下所有词的词频,即label_dicts;同时,记录各个类别的总数label_counts。
  2. 然后根据第二步中统计出的全文档集中的词(不重复),对每个词应用以下公式计算权重:
wj(wdi) = [ (nj(wdi) + 0.1) / Cj ] / [(N(wdi) - nj(wdi) + 1) / (L - Cj)]  
           其中wj(wdi) —— 总词表中第i个词在类别j下的权重
           nj(wdi) —— 第i个词在类别j中出现的次数
           N(wdi) —— 第i个词在工文档集中出现的次数
           Cj —— 属于类别j的文档数
           L —— 总文档数
def build_dynamic_dict(idx_data, idx_label, vocab):
   '''
   构建动态词典
   :param idx_data: 映射文档词集
                   [[word1,word2,word3],[word3,word4],....]
   :param idx_label: 映射文档分类标签
                   [1,0,2,1,0,....]
   :param vocab:词与词频
               {word1:freq1,Word2:freq2,......}
   :return: 动态词典
           {类别1:{word1:p1,word2:p2,.....},
           类别2:{word1:p1,word2:p2,....},
           类别3:{word1:p1,word2:p2,....}
           }
   '''
   # 构造类别词典
   label_dicts = OrderedDict()
   label_counts = defaultdict(int)
   for idx, label in idx_label.iteritems():
       if not locals().has_key('dict_%d' % label):
           locals()['dict_%d' % label] = defaultdict(int)
           label_dicts[label] = eval('dict_%d' % label)

       label_counts[label] += 1
       for word in idx_data[idx]:
           label_dicts[label][word] += 1

   L = sum([x for _, x in label_counts.iteritems()])
   # 构造动态词典
   dynamic_dicts = OrderedDict()
   for label, label_dict in label_dicts.iteritems():
       if not locals().has_key('dynamic_dict_%d' % label):
           locals()['dynamic_dict_%d' % label] = defaultdict(float)
           dynamic_dicts[label] = eval('dynamic_dict_%d' % label)

       for word, N in vocab.iteritems():
           freq = label_dict.get(word, 0)
           other_freq = N - freq
           dynamic_dicts[label][word] = (
               (freq + 0.1) / label_counts[label]) / ((other_freq + 1) / (L - label_counts[label]))
   return dynamic_dicts
  • 文本向量表示
  1. 对于待表示文本,遍历词表与动态词表,生成文本词表对应的词权重,按权重大小倒序排列。并如代码注释,根据权重列表生成6个特征,添加到向量vec中。
  2. 对每一个类别执行上述操作,则vec的长度为6*类别数 = 18(此处类别数为3)
def sentence2vec(sentence, dynamic_dicts):
    """ 使用动态词典将句子转换成特征向量

    每个类别分别生成6个特征:
        - average: 平均强度
        - top_1: 类别强度最高
        - top_3: 类别强度前3之和
        - top_6: 类别强度前6之和
        - top_10: 类别强度前10之和
        - top_15: 类别强度前15之和
    """
    vec = []
    sentence = set(sentence)
    for label, dynamic_dict in dynamic_dicts.iteritems():
        weights = [dynamic_dict.get(word, 0.1) for word in sentence]
        weights = sorted(weights, reverse=True)

        # average
        vec.append(sum(weights) / len(weights))
        # top_1
        vec.append(weights[0])
        # top_3
        vec.append(sum(weights[:3]))
        # top_6
        vec.append(sum(weights[:6]))
        # top_10
        vec.append(sum(weights[:10]))
        # top_15
        vec.append(sum(weights[:15]))

    return vec
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,384评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,845评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,148评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,640评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,731评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,712评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,703评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,473评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,915评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,227评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,384评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,063评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,706评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,302评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,531评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,321评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,248评论 2 352

推荐阅读更多精彩内容