Task2: 特征提取

本文详细介绍了分词技术中的最大匹配法,包括正向最大匹配和逆向最大匹配,以及它们的分词思路、步骤和实际应用案例。同时提到了双向最大匹配法,用于优化分词结果。此外,还提及了词袋模型和词嵌入的简单概念,并展示了使用`pkuseg`库进行中文分词的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基本概念:

最大匹配法【Maximum Matching】MM

最大匹配是指以词典为依据,取词典中最长单词的字数量作为截取词的起始匹配长度,将截取后的最大长度的词与词典中的词进行比对(为提升扫描效率,还可以根据字数多少设计多个字典,然后根据字数分别从不同字典中进行扫描匹配), 直到还剩一个单字则终止,如果该单字无法切分,则作为未登录词处理(没有被收录在分词词表中但必须切分出来的词,包括各类专有名词(人名、地名、企业名等)、缩写词、新增词汇等等)

正向最大匹配法
分词思路:
在词典中进行扫描,尽可能地选择与词典中最长单词匹配的词作为目标分词,然后进行下一次匹配。
分词步骤:
词典中最长的单词为n个,那么最大匹配的起始子串字数也为 n个
(1)扫描字典,测试读入的子串是否在字典中
(2)如果存在,则从输入中删除掉该子串,重新按照规则取子串,重复(1)
(3)如果不存在于字典中,则从右向左减少子串长度,重复(1)

正向最大匹配法

从左往右地进行最大匹配法。尽可能地选择与词典中最长单词匹配的词作为目标分词,然后进行下一次匹配

栗子:

待切分文本 计算语言学课程有意思

词典(表) {"计算", "计算语言学", "课程", "有", "意思"}(真实的词表中会有成千上万个平时我们使用的已经分好的词语)

匹配过程

确定最大匹配的起始子串字数为词典中最长单词的长度5

输入 计算语言学课程有意思

第一轮 取子串“计算语言学”,正向取词,如果匹配失败,每次去掉待匹配子串最后面的一个字

第1次. “计算语言学”,扫描词典表,匹配,输出“计算语言学”,输入变为“课程有意思”

第二轮 取子串“课程有意思”

第1次. “课程有意思”, 扫描词典表,不匹配,子串长度减一变为“课程有意”

第2次. “课程有意”, 扫描词典表,不匹配,子串长度减一变为“课程有”

第3次. “课程有”, 扫描词典表,不匹配,子串长度减一变为“课程”

第4次. “课程”, 扫描词典表,匹配,输出“课程”,输入变为“有意思”

第三轮 取子串“有意思”

第1次. “有意思”, 扫描词典表,不匹配,子串长度减一变为“有意”

第2次. “有意”, 扫描词典表,不匹配,子串长度减一变为“有”

第3次. “有”, 扫描词典表,匹配,输出“有”,输入变为“意思”

第四轮 取子串“意思”

第1次. “意思”,扫描词典表,匹配,输出“意思”,输入变为“”

输入长度为零,终止扫描。

最终分词结果为:计算语言学/课程/有/意思

逆向最大匹配算法 RMM

从右往左地进行最大匹配法。尽可能地选择与词典中最长单词匹配的词作为目标分词,然后进行下一次匹配。在实践中,逆向最大匹配算法性能通常优于正向最大匹配算法。

栗子:

待切分文本 计算语言学课程有意思

词典(表) {"计算", "计算语言学", "课程", "有", "意思"}(真实的词表中会有成千上万个平时我们使用的已经分好的词语)

匹配过程

确定最大匹配的起始子串字数为词典中最长单词的长度5

输入 计算语言学课程有意思

第一轮 取子串“课程有意思”,逆向取词,如果匹配失败,每次去掉待匹配子串最前面的一个字

第1次. “课程有意思”,扫描词典表,不匹配,子串长度减一变为“程有意思”

第2次. “程有意思”,扫描词典表,不匹配,子串长度减一变为“有意思”

第3次. “有意思”,扫描词典表,不匹配,子串长度减一变为“意思”

第4次. “意思”,扫描词典表,匹配,输出“意思”,输入变为“计算语言学课程有”

第二轮 取子串“言学课程有”

第1次. “言学课程有”, 扫描词典表,不匹配,子串长度减一变为“学课程有”

第2次. “学课程有”, 扫描词典表,不匹配,子串长度减一变为“课程有”

第3次. “课程有”, 扫描词典表,不匹配,子串长度减一变为“程有”

第4次. “程有”, 扫描词典表,子串长度减一变为“有”

第5次. “有”, 扫描词典表,匹配,输出“有”,输入变为“计算语言学课程”

第三轮 取子串“语言学课程”

第1次. “语言学课程”, 扫描词典表,不匹配,子串长度减一变为“言学课程”

第2次. “言学课程”, 扫描词典表,不匹配,子串长度减一变为“学课程”

第3次. “学课程”, 扫描词典表,不匹配,子串长度减一变为“课程”

第4次. “课程”, 扫描词典表,匹配,输出“课程”,输入变为“计算语言学”

第四轮 取子串“计算语言学”

第1次. “计算语言学”,扫描词典表,匹配,输出“计算语言学”,输入变为“”

输入长度为零,终止扫描。

最终分词结果为:计算语言学/课程/有/意思

双向最大匹配法

两种算法都切一遍,然后根据大颗粒度词越多越好,非词典词(未登录词)和单字词越少越好的原则,选取其中一种分词结果输出

算法流程:

  1. 比较正向最大匹配和逆向最大匹配结果

  2. 如果分词数量结果不同,那么取分词数量较少的那个

  3. 如果分词数量结果相同

    3.1 分词结果相同,可以返回任何一个

    3.2 分词结果不同,返回单字数比较少的那个

    语言模型中unigram、bigram、trigram的概念;

    unigram 一元分词,把句子分成一个一个的汉字。
    bigram 二元分词,把句子从头到尾每两个字组成一个词语。
    trigram 三元分词,把句子从头到尾每三个字组成一个词语。

     

    词袋:

一种表示文档的模型,模型忽略语法词序等,可以看作是若干个词汇的集合。具体地是用词表中的所有词去向量化表示一个文档,因此每个文档的维度是一样的,都是词表的维度。

代码

import pandas as pd
import numpy as np
train_file = 'cnews/cnews.train.txt'
val_file = 'cnews/cnews.val.txt'
test_file  = 'cnews/cnews.test.txt'

test_data = pd.read_csv(test_file,sep='\t',engine='python',names=['label','content'],encoding='UTF-8')
train_data = pd.read_csv(train_file,sep='\t',engine='python',names=['label','content'],encoding='UTF-8')
validation_data = pd.read_csv(val_file,sep='\t',engine='python',names=['label','content'],encoding='UTF-8')

from multiprocessing import Pool, cpu_count
import re
import pkuseg

remove = re.compile('[\s\d,。?!~:“”;,.:?"!~$%^&@#¥#*()()、|/]')
def parallelize_dataframe(df, func):
    df_split = np.array_split(df, cpu_count())
    pool = Pool(cpu_count())
    df = pd.concat(pool.map(func, df_split))
    pool.close()
    pool.join()
    return df
seg = pkuseg.pkuseg()    
def pku_cut(df):
    df['content'] = df['content'].apply(lambda x: re.sub(remove, '', str(x).strip()))#去除一些符号
    df['content'] = df['content'].apply(lambda x: seg.cut(x))分词
    return df

##分词
test_data = parallelize_dataframe(test_data, pku_cut)
train_data = parallelize_dataframe(train_data, pku_cut)
validation_data = parallelize_dataframe(validation_data, pku_cut)
##保存好分词后的数据
test_data.to_csv('cnews/test.csv',index=False)
train_data.to_csv('cnews/train.csv',index = False)
validation_data.to_csv('cnews/val.csv',index = False)

## 加载数据
train=pd.read_csv('cnews/train.csv')
test = pd.read_csv('cnews/test.csv')
val =pd.read_csv('cnews/val.csv')

all_content = pd.concat([train['content'],test['content'],val['content']]).values

## 计算词汇表与词频
from collections import defaultdict
def build_vocab(sentences):
    vocab = defaultdict(int) #将词汇表初始化为一个字典
    for i, sentence in enumerate(sentences):
        for word in sentence.split(','): ## split的原因是我读取的数据每一行是一个字符串,要将其分开,转为list
            vocab[word] += 1 #记录每个词出现的次数
    return vocab 
vocab = build_vocab(all_content)
vocab_list = [ key for key,value in vocab.items() ]
w2i = {w:i for i,w in enumerate(vocab_list)}
##将w2i存起来
import pickle 
with open('cnews_w2i.pickle', 'wb') as handle: 
 pickle.dump(w2i, handle, protocol=pickle.HIGHEST_PROTOCOL) 
from gensim.models import KeyedVectors
wv_from_text = KeyedVectors.load_word2vec_format('/mnt/7/Tencent_AILab_ChineseEmbedding.txt', binary=False)

def load_embed(word_index, wv):
all_embs = wv.vectors
emb_mean,emb_std = all_embs.mean(), all_embs.std()
    embed_size = all_embs.shape[1]

    nb_words = len(word_index)
    embedding_matrix = np.random.normal(emb_mean, emb_std, (nb_words, embed_size))
    for word, i in word_index.items():
        if word in wv: 
            embedding_matrix[i] = wv[word]
            
    return embedding_matrix,emb_mean,emb_std
embedding_matrix,emb_mean,emb_std = load_embed(w2i, wv_from_text)
##将embedding_matrix 存起来
with open('embedding_matrix_v1.pickle', 'wb') as handle: 

pickle.dump(embedding_matrix, handle, protocol=pickle.HIGHEST_PROTOCOL) 
 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值