一、分词
1、采用jieba分词
安装:全自动安装:pip install jieba / pip3 install jieba
https://blog.csdn.net/flysky1991/article/details/73948971
https://www.jianshu.com/p/e8b5d01ca073
https://www.cnblogs.com/echo-cheng/p/7967221.html
https://www.cnblogs.com/Denise-hzf/p/6612212.html
三种分词模式:
-精确模式:试图将句子最精确地切开,适合文本分析;(选择)
-全模式:把句子中所有的可以成词的词语都扫描出来, 速度非常快,但是不能解决歧义;
-搜索引擎模式:在精确模式的基础上,对长词再次切分,提高召回率,适合用于搜索引擎分词。
主要涉及如下几种算法:
(1)基于前缀词典实现高效的词图扫描,生成句子中汉字所有可能成词情况所构成的有向无环图 (DAG);
DAG分词过程:对待分词句子, 根据给定的词典进行查词典操作, 生成几种可能的句子切分。dag记录的是句子中某个词的开始位置, 从0到n-1(n为句子的长度), 每个开始位置作为字典的键, value是个list, 其中保存了可能的词语的结束位置(通过查字典得到词, 开始位置+词语的长度得到结束位置)。
例如:{0:[1,2,3]} 这样一个简单的DAG, 就是表示0位置开始, 在1,2,3位置都是词, 就是说0~1, 02,03这三个起始位置之间的字符, 在dict.txt中是词语。
比如 sentence 是 "国庆节我在研究结巴分词",对应生成的DAG是这样的:{0: [0, 1, 2], 1: [1], 2: [2], 3: [3], 4: [4], 5: [5, 6], 6: [6], 7: [7, 8], 8: [8], 9: [9, 10], 10: [10]} 其中的数字表示每个汉字在sentence中的位置,所以0:[0,1,2] 表示 在trie 树中,"国"开头的词语中对应于该 sentence 有三种匹配情况:国,国庆,国庆节。
(2)采用了动态规划查找最大概率路径, 找出基于词频的最大切分组合;
(3)对于未登录词,采用了基于汉字成词能力的 HMM 模型,采用Viterbi 算法(动态规划)进行计算==>HMM五元组中(观察值(句子),状态转移矩阵(BMES 4X4),发射矩阵(4Xn(好多汉字)),初始状态值(BMES))求解状态值(BMES),根据状态值分词
https://blog.csdn.net/riverflowrand/article/details/50057323
(4)基于Viterbi算法做词性标注;(计算概率)
http://www.cnblogs.com/bottlebox/archive/2011/11/21/2256644.html
(5)基于tf-idf和textrank模型抽取关键词;
textrank与tf-idf不同,不再依赖语料环境(通过语料环境求idf)
textrank公式:
其中,d是阻尼系数,防止结果为0,一般取0.85
程序步骤:
1、文章分词: 对每一篇文章进行分词,分词系统主要由坤雁分词系统、ansj分词,结巴分词等。
2、分词结果数据清洗: 主要包括去停用词、去除符号字母数字等。
3、构建候选关键词图: 根据设定的词语选择窗口截取文本的分词结果,将每个词语作为候选关键词图的节点,截取的每一段文本中的词语作为相邻的边,以此构建候选关键词图。
4、关键词提取: 利用pagerank思想循环迭代候选关键词图, 每个节点的权重初始化化为1.0f,通过设定的迭代次数达到稳定后,对节点权重进行倒序排序,从而得到最重要的num个单词,作为候选关键词。
程序主要包含两大部分,第一部分为候选关键词图构件。第二部分为关键词提取
1.依赖语料
tf-idf的idf值依赖于语料环境,这给他带来了统计上的优势,即它能够预先知道一个词的重要程度.这是它优于textrank的地方。
而textrank只依赖文章本身,它认为一开始每个词的重要程度是一样的。
2.词语的互相关联性
tf-idf是纯粹用词频的思想(无论是tf还是idf都是)来计算一个词的得分,最终来提取关键词,完全没有用到词之间的关联性。
而textrank用到了词之间的关联性(将相邻的词链接起来),这是其优于tf-idf的地方。
https://blog.csdn.net/u013041398/article/details/52473994
https://blog.csdn.net/gzt940726/article/details/80256011
例子:
# encoding=utf-8
import jieba
seg_list = jieba.cut("沧州渤海新区金龙渤海新城三期B幢401号英泰丽斯科技发展有限公司2015年11月16日", cut_all=True)
print("Full Mode: " + "/ ".join(seg_list)) # 全模式
Full Mode: 沧州/ 渤海/ 新区/ 金/ 龙/ 渤海/ 新城/ 三期/ B/ 幢/ 401/ 号/ 英/ 泰/ 丽斯/ 科技/ 发展/ 有限/ 有限公司/ 公司/ 2015/ 年/ 11/ 月/ 16/ 日
seg_list = jieba.cut("沧州渤海新区金龙渤海新城三期B幢401号英泰丽斯科技发展有限公司2015年11月16日", cut_all=False) #cut_all=False可以不写
print("Default Mode: " + "/ ".join(seg_list)) # 精确模式 默认
Default Mode: 沧州/ 渤海/ 新区/ 金龙/ 渤海/ 新城/ 三期/ B/ 幢/ 401/ 号/ 英泰/ 丽斯/ 科技/ 发展/ 有限公司/ 2015/ 年/ 11/ 月/ 16/ 日
seg_list = jieba.cut_for_search("沧州渤海新区金龙渤海新城三期B幢401号英泰丽斯科技发展有限公司2015年11月16日") # 搜索引擎模式
print("Search Mode: ".join(seg_list))
Search Mode: 沧州/ 渤海/ 新区/ 金龙/ 渤海/ 新城/ 三期/ B/ 幢/ 401/ 号/ 英泰/ 丽斯/ 科技/ 发展/ 有限/ 公司/ 有限公司/ 2015/ 年/ 11/ 月/ 16/ 日
二、建立自己字典
分词后,针对自己当前的分类目的需要对自己的数据集建立词典(word_dict),通常train.txt,test.txt,val.txt(能得到的所有文件)都用来建立字典,字典就是一个word_dict.txt文件,里面存有所有出现过的词。
在应用的时候,每一个词会对应一个index,可以通过文本中单词顺序定义为0,1,2...也可以根据建词典时的词频降序标为0,1,2,3...
full_feature_set = set([key for key in full_feature_set])
# ensure <unk> is 0
word_dict = {v:(k+1) for (k,v) in enumerate(full_feature_set - set(['<unk>']))}
word_dict['<unk>'] = 0
word_dict得到字典key:word, value:index
对于一个输入的句子,每一个词通过word_dict对应一个index,最后会得到一个列表作为网络输入,例如,你好:1,世界:2,则句子"你好 世界"对应网络输入[1, 2]
out of vocabulary未登录词:如果对于测试集出现了word_dict中没有的词,则可以用<unk>代替,或者更新word_dict(在数据量较大生成word_dict时频率小于5的词一般不计入)
三、embedding layer
https://www.zhihu.com/question/45027109?sort=created
embedding layer是网络的第一层,经过该层可以产生词向量
词汇是语料库的基本元素, 所以, 使用embedding layer来学习词嵌入, 将一个词映射成为固定维度的稠密向量. 有了这一步, 才能构造矩阵, 实现神经网络的前向传播.
如何使用?
- 从头训练
就像word2vec一样, 这一层是可学习的, 用随机数initialize , 通过BP去调整. - pre-trained + fine tuning
用其他网络(如 word2vec、glove) 训练好的现成的词向量, 作为初始化参数, 然后继续学习. - pre-trained + static
用其他网络(如 word2vec、glove) 训练好的现成的词向量, 作为初始化参数, 并且这些参数保持固定, 不参与网络的学习.
keras 的 Embedding
Embedding(Layer)
类.
- 将索引映射为固定维度的稠密的向量.
eg. [[4], [20]] -> [[0.25, 0.1], [0.6, -0.2]]
This layer can only be used as the first layer in a model.
__init__(self, input_dim, output_dim,input_length,...)
- 构造函数,三个参数分别代表vocab_size、vector_dimension、fixed_word_number.
- 继承自父类的weights、trainable参数.
如一个语料库, 词汇量为20万, word representation vector is 200d, 文章的截断长度为250个单词, 那么
embedding_layer=Embedding(input_dim=20E4,output_dim=200,input_length=250,weights=embedding_matrix,trainable=is_trainable)
实现过程
输入是word2index得到的第一个句子列表[1, 33, 55, 3]四个词,第二个句子[33, 56]两个词,对于每一个句子要设置成相同的维数,不够补零,大于截断
pad_sequence 函数
对于word2vec得到的.bin文件,他的主要作用是用来对embedding layer进行初始化,因为随机初始化训练时间较长,将训练集中的词在.bin文件中查找,如果存在就得到它的词向量。
pretrain_embed = 'path'
pre_vocab = 'path1'
pretrain_embedding = loadPretrain(pretrain_embed)
vocab = loadVocab(pre_vocab) # all word in embedding word2index
word_embeds = np.random.uniform(-np.sqrt(0.01), np.sqrt(0.01), (len(word_dict), emb_dim))
n = 0
for w in word_dict:
if w in vocab:
word_embeds[word_dict[w]] = pretrain_embeding[vocab[w]]
n +=1
else:
print(w)
其中pre_vocab和pretrain_embed是由.bin文件得到的,得到的方式:
pip install torchwordemb
import torchwordemb
torchwordemb.load_word2vec_bin(path)
read word2vec binary-format model from path.
return(vocab, vec)
- vocab is a dict mapping a word to its index
- vec is a torch.FloatTensor of size V x D, which V is teh vocabulary size and D is the dimension of wordd2vec.
vocab, vec = torchwordemb.load_word2vec_bin("***.bin")
print(vrc.size())
print(vec[w2v.vocab["apple"]])
torchwordemb.load_word2vec_text(path)
read word2vec text-format model from path.
torchwordemb.load_glove_text(path)
read glove text-format model from path.
其实就是One hot representation => Distributed representation
四、神经网络
embedding层后就开始接神经网络,CNN/RNN/LSTM/RCNN
以RNN为例:
self.loss_val = self.loss() # -->self.loss_nce()
self.train_op = self.train()
self.predictions = tf.argmax(self.logits, axis=1, name="predictions") # shape:[None,]
correct_prediction = tf.equal(tf.cast(self.predictions, tf.int32), self.input_y) # tf.argmax(self.logits, 1)-->[batch_size]
self.accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32), name="Accuracy") # shape=()
loss ==> 交叉熵损失+l2损失
(可选:nce_loss ==> nce_loss + l2损失)
学习率:
通过tf.train.exponential_decay函数实现指数衰减学习率。
步骤:
1.首先使用较大学习率(目的:为快速得到一个比较优的解);
2.然后通过迭代逐步减小学习率(目的:为使模型在训练后期更加稳定);
tf.train.exponential_decay(learning_rate, global_step, decay_steps, decay_rate, staircase=True/False)
公式:decayed_learning_rate=learining_rate*decay_rate^(global_step/decay_steps)
- decayed_learning_rate为每一轮优化时使用的学习率;
- learning_rate为事先设定的初始学习率;
- decay_rate为衰减系数;
- decay_steps为衰减速度。
- tf.train.exponential_decay函数则可以通过staircase(默认值为False,当为True时,(global_step/decay_steps)则被转化为整数) ,选择不同的衰减方式。
初始的学习速率是learining_rate,如果staircase=True,那就表明每decay_steps次计算学习速率变化,更新原始学习速率,如果是False,那就是每一步都更新学习速率。学习速率第一次训练开始变化,global_steps每次自动加1。