
目录一、Embedding降维原理1建立索引表2获取one-hot编码3lookup table4压缩二、推荐原理三、Word2Vec总结上一篇内容 内容推荐系统 讲到了维度爆炸解决办法就是Embedding嵌入它是把高维稀疏向量压缩到低维稠密空间的技术而实现它的经典工具就是Word2Vec。一、Embedding降维原理1建立索引表在训练前扫描语料时构建存成一个字典文件词→索引的映射gensim 里就是模型的 vocab可序列化保存。例如{PAD: 0, apple: 3, banana: 7, ..., king: 128, ...}存储样本时只需要存储索引文件就会变得很小。2获取one-hot编码原始的词表示方式是one-hot编码词表有 10000 个词每个词就是一根 10000 维向量只有自己那一格是 1其余全 0。只需知道apple是词表里的第几个词就能确定apple的向量。例如apple [0, 0, 1, 0, ..., 0] ← 10000维9999个零维度等于词表大小信息密度却极低。酒店推荐里的三千多维词频向量稀疏程度稍好但维度照样爆炸。3lookup table从语料中取一个训练样本比如句子片段i love eating apple and banana # apple的邻居是eating 和 and选中间词apple作为目标词神经网络的输入就是 apple 的 one-hot 向量设置隐藏层为300层输出为与语料统计的真实邻居分布的概率 y前向传播取一个词 → 查表得300维 → 预测10000维邻居概率 ŷ↓与语料统计的真实邻居分布 y比误差↓反向传播调整 W 和 W′ 的每个数值↓重复千万次直到 ŷ 越来越接近 y以上的训练过程我们前面是介绍过的神经网络基础三。经过几百上千轮训练后获得了一个10000 行 × K 列的稠密矩阵是模型训练出来的参数权重W就是lookup table嵌入表。4压缩压缩这个动作就是one-hot 与 lookup table做一次矩阵乘法one-hot(1×10000) × lookup table(10000×K) 词向量(1×K) [0,0,1,0,...,0] × W W 的第3行由于 one-hot 只有一个 1乘矩阵的效果等价于按位置查表取行——输入 apple 的 one-hot第 3 位为 1结果就是把 W 的第 3 行抽出来。所以叫 lookup查表。工程实现里连矩阵乘法都不做直接传词的索引去表里取行数学等价、效率更高。一个容易误解的点lookup table 的行数并没有变少还是 10000 行压缩发生在每一行的宽度上——从 10000 维稀疏变成 K 维稠密。降维降的是表示每个词所需的维度。二、推荐原理假如有一本百科全书书里的句子都统计。我们可以把他里面的单词都向量化学习语料的真实邻居分布。这些单词之间其实是有规律的比如i love eating apple 和 i love eating banana 中apple 和 banana 的邻居分布会高度重合。要让模型对两者的邻居概率预测都准它们在隐藏层的表示必然被推向相近位置。同理man 和 woman 共享另一组上下文。语料够大时邻居相似 → 向量相近这一规律就被自动编码进了空间结构——语义关系被几何化了。因为大家是在同样的一个尺度上来去量化的都是同一个标准。那么这个标准只要一样的加加减减最后得出来的数值再通过相似度计算能保证我们的逻辑也是有效的所以他能帮你做推荐。总结一下计算机能帮你干活通过向量的方法的话来去抽象。但是本质上它就是一串数字它在抽象的这个维度上在空间上它可以给你做一个相似度的一个匹配。三、Word2VecWord2Vec谷歌开源Python 端用gensim调用的设计精髓在于训练任务的标注是免费的。word2Vec有两种模式• Skip-Gram给定input word预测上下文• CBOW给定上下文预测inputword与 Skip-Gram相反如ilove eatingappleand bananaapple是目标词window邻居 2Skip-Gram是给定apple预测两边的词。CBOW是给定两边的词预测apple。我们使用Word2Vec去做一个计算小说中的人物相似度的功能比如孙悟空与猪八戒孙悟空与 孙行者• Step1读取《三国演义》文档使用jieba分词工具进行分词import jieba import os from utils import files_processing Story_PATH os.path.join(os.path.dirname(os.path.abspath(__file__)), three_kingdoms) # 源文件所在目录 source_folder Story_PATH\\source segment_folder Story_PATH\\segment # 字词分割对整个文件内容进行字词分割 def segment_lines(file_list,segment_out_dir,stopwords[]): for i,file in enumerate(file_list): segment_out_nameos.path.join(segment_out_dir,segment_{}.txt.format(i)) with open(file, rb) as f: document f.read() document_cut jieba.cut(document) sentence_segment[] for word in document_cut: if word not in stopwords: sentence_segment.append(word) result .join(sentence_segment) result result.encode(utf-8) with open(segment_out_name, wb) as f2: f2.write(result) # 对source中的txt文件进行分词输出到segment目录中 file_listfiles_processing.get_files_list(source_folder, postfix*.txt) segment_lines(file_list, segment_folder)切分效果如下中间加了好多空格• Step2将训练语料转化成一个sentence的迭代器# 切分之后的句子合集 sentences word2vec.PathLineSentences(segment_folder)• Step3使用word2vec进行训练把每个单词压缩成100维的向量window邻居 3# 设置模型参数进行训练 model word2vec.Word2Vec(sentences, vector_size100, window3, min_count1)• Step4计算两个单词的相似度print(model.wv.similarity(关羽, 刘备)) print(model.wv.similarity(关羽, 关云长)) print(model.wv.most_similar(曹操)) #跟曹操相关的人都有哪些 print( * 60) print(model.wv.most_similar(positive[刘备, 关羽, 张飞])) # 刘关张相加 print( * 60) print(model.wv.most_similar(positive[刘备, 关羽, 张飞], negative[关云长])) # 刘关张相加 - 关云长输出总结Word2Vec是帮忙训练语料的要是有足够多的语料我们自己也可以训练Embedding模型。