一、正向最大匹配和反向最大匹配
正向,即从前到后的顺序,最大匹配,即按照词表中出现的最长词进行匹配,例如:
词表:北京 生前 北京大学 前来 大学 大学生
分词结果:北京大学生前来报道 → \rightarrow →北京大学 / 生前 / 来 / 报到
实现正向最大匹配的方式有两种:
1.设置一个定长滑动窗口,长度为词表中词的最大长度,从前往后依次匹配。如果词语没有在词表中出现,就从右边缩小一个单位的滑动窗口,直到匹配,或者,直到窗口缩小到最后一个字都没有匹配。如果匹配到了词表中的一个词,就在匹配的词语后切分,如果直到最后一个字仍未匹配,就在这个字后切分。
2.用一个字典记录词表里的词,记录方式是对于词表中出现的词语的前缀,values记为0,对于词表中出现的词语,values记为1。从前往后遍历字段,如果出现的词语是前缀,就继续扩大一格向右遍历,如果出现的词语是词表中的词,则记录下来,继续扩大窗口,直到出现的词语既不是前缀也不是词表中的词,就在记录的词后做切分。
反向最大匹配就是从后到前进行最大匹配。正反向最大匹配都很依赖词表,对于人名等的无法枚举实体词无法有效的处理,而且一旦字段中出现了错别字,分词将会把一个在词表中出现的词语分成单独的字,造成一连串影响。
二、jieba分词
pip install jieba
根据词表中的词将字段所有可能的切分方式,将分词后的语料进行词频统计,选出词频最高的那一种切分方式作为结果。
三、基于机器学习的中文分词
分词的本质其实是对字段中的每一个字做二分类,判断是否在字的后面做切分,所以分词问题也就转化成了数学问题。例如:
上 海 | 自 来 水 | 来 自 | 海 | 上
对应每个字的编码应该是:0 1 0 0 1 0 1 1 1
首先,第一层用embedding层将离散数据转化为向量(batch_size,sentence_len) → \rightarrow →(batch_size,sentence_len,vec_dim),第二层用RNN层处理(因为分词有时序信息),(batch_size,sentence_len,vec_dim) → \rightarrow →(batch_size,sentence_len,hidden_size),接着用线性层处理(做二分类),(batch_size,sentence_len,hidden_size) → \rightarrow →(batch_size,sentence_len,2),最后用mse计算loss函数。
代码如下:
import torch
import torch.nn as nn
import jieba
import numpy as np
import random
import json
from torch.utils.data import DataLoader
"""
基于pytorch的网络编写一个分词模型
我们使用jieba分词的结果作为训练数据
看看是否可以得到一个效果接近的神经网络模型
"""
class TorchModel(nn.Module):
def __init__(self, input_dim, hidden_size, num_rnn_layers, vocab):
super(TorchModel, self).__init__()
self.embedding = nn.Embedding(len(vocab) + 1, input_dim, padding_idx=0) #shape=(vocab_size, dim)
self.rnn_layer = nn.RNN(input_size=input_dim,
hidden_size=hidden_size,
batch_first=True,
num_layers=num_rnn_layers,
)
self.classify = nn.Linear(hidden_size, 2)