Machine Learning & Data Analysis自然语言处理深度学习·神经网络·计算机视觉

word2vec学习小记

2017-03-19  本文已影响935人  ginobefun

word2vec是Google于2013年开源推出的一个用于获取词向量的工具包,它简单、高效,因此引起了很多人的关注。最近项目组使用word2vec来实现个性化搜索,在阅读资料的过程中做了一些笔记,用于后面进一步学习。

前注:word2vec涉及的相关理论和推导是非常严(ku)格(zao)的,本文作为一个初学者的学习笔记,希望能从自己的理解中尽量用简单的描述,如有错误或者歧义的地方,欢迎指正。

word2vec是什么?

This tool provides an efficient implementation of the continuous bag-of-words and skip-gram architectures for computing vector representations of words. These representations can be subsequently used in many natural language processing applications and for further research.

从官方的介绍可以看出word2vec是一个将词表示为一个向量的工具,通过该向量表示,可以用来进行更深入的自然语言处理,比如机器翻译等。

为了理解word2vec的设计思想,我们有必要先学习一下自然语言处理的相关发展历程和基础知识。

基础知识

语言模型

语言模型形式化表达
P('我喜欢吃梨') = P('我') * P('喜欢'|'我') * P('吃'|'我','喜欢') * P('梨'|'我','喜欢','吃')
P('我喜欢吃力') = P('我') * P('喜欢'|'我') * P('吃力'|'我','喜欢')

N-gram模型

词向量表示

// One-hot Representation 向量的维度是词表的大小,比如有10w个词,该向量的维度就是10w
v('足球') = [0 1 0 0 0 0 0 ......]
v('篮球') = [0 0 0 0 0 1 0 ......]

// Distributed Representation 向量的维度是某个具体的值如50
v('足球') = [0.26 0.49 -0.54 -0.08 0.16 0.76 0.33 ......]
v('篮球') = [0.31 0.54 -0.48 -0.01 0.28 0.94 0.38 ......]

神经网络概率语言模型

神经网络概率语言模型

word2vec的核心模型

word2vec的核心模型

CBOW和Skip-gram模型


word2vec的核心模型

通过实践了解word2vec

学习了上面的基础知识之后,我们就通过一个例子来感受一下word2vec的效果。

下载语料

从搜狗实验室下载全网新闻数据(SogouCA),该语料来自若干新闻站点2012年6月—7月期间国内、国际、体育、社会、娱乐等18个频道的新闻数据。

下载该文件解压后大约为1.5G,包含120w条以上的新闻,文件的内容格式如下图所示:

搜狗CA语料内容格式

获取新闻内容

这里我们先对语料进行初步处理,只获取新闻内容部分。可以执行以下命令获取content部分:

cat news_tensite_xml.dat | iconv -f gbk -t utf-8 -c | grep "<content>"  > corpus.txt

分词处理

由于word2vec处理的数据是单词分隔的语句,对于中文来说,需要先进行分词处理。这里采用的是中国自然语言处理开源组织开源的ansj_seg分词器,核心代码如下所示:

public class WordAnalyzer {
    private static final String TAG_START_CONTENT = "<content>";
    private static final String TAG_END_CONTENT = "</content>";
    private static final String INPUT_FILE = "/home/test/w2v/corpus.txt";
    private static final String OUTPUT_FILE = "/home/test/w2v/corpus_out.txt";

    public static void main(String[] args) throws Exception {
        BufferedReader reader = null;
        PrintWriter pw = null;
        try {
            System.out.println("开始处理分词...");
            reader = IOUtil.getReader(INPUT_FILE, "UTF-8");
            pw = new PrintWriter(OUTPUT_FILE);
            long start = System.currentTimeMillis();
            int totalCharactorLength = 0;
            int totalTermCount = 0;
            Set<String> set = new HashSet<String>();
            String temp = null;
            while ((temp = reader.readLine()) != null) {
                temp = temp.trim();
                if (temp.startsWith(TAG_START_CONTENT)) {
                    //System.out.println("处理文本:" + temp);
                    int end = temp.indexOf(TAG_END_CONTENT);
                    String content = temp.substring(TAG_START_CONTENT.length(), end);
                    totalCharactorLength += content.length();
                    Result result = ToAnalysis.parse(content);
                    for (Term term : result) {
                        String item = term.getName().trim();
                        totalTermCount++;
                        pw.print(item + " ");
                        set.add(item);
                    }
                    pw.println();
                }
            }

            long end = System.currentTimeMillis();
            System.out.println("共" + totalTermCount + "个Term,共" 
                + set.size() + "个不同的Term,共 " 
                + totalCharactorLength + "个字符,每秒处理字符数:" 
                + (totalCharactorLength * 1000.0 / (end - start)));
        } finally {
            // close reader and pw
        }
    }
}

分词处理之后的文件内容如下所示:


分词之后的语料

下载word2vec源码并编译

这里我没有从官网下载而是从github上的svn2github/word2vec项目下载源码,下载之后执行make命令编译,这个过程很快就可以结束。

开始word2vec处理

编译成功后开始处理。我这里用的是CentOS 64位的虚拟机,八核CPU,32G内存,整个处理过程耗时大约4个小时。

./word2vec -train ../corpus_out.txt -output vectors.bin -cbow 0 -size 200 -window 5 -negative 0 -hs 1 -sample 1e-3 -threads 12 -binary 1

// 参数解释
-train 训练数据 
-output 结果输入文件,即每个词的向量 
-cbow 是否使用cbow模型,0表示使用skip-gram模型,1表示使用cbow模型,默认情况下是skip-gram模型,cbow模型快一些,skip-gram模型效果好一些 
-size 表示输出的词向量维数 
-window 为训练的窗口大小,5表示每个词考虑前5个词与后5个词(实际代码中还有一个随机选窗口的过程,窗口大小<=5) 
-negative 表示是否使用负例采样方法0表示不使用,其它的值目前还不是很清楚 
-hs 是否使用Hierarchical Softmax方法,0表示不使用,1表示使用 
-sample 表示采样的阈值,如果一个词在训练样本中出现的频率越大,那么就越会被采样
-binary 表示输出的结果文件是否采用二进制存储,0表示不使用(即普通的文本存储,可以打开查看),1表示使用,即vectors.bin的存储类型

测试处理结果

处理结束之后,使用distance命令可以测试处理结果,以下是分别测试【足球】和【改革】的效果:

测试足球一词的词向量 测试改革一词的词向量

学习小结

参考材料

扫一扫 关注我的微信公众号
上一篇下一篇

猜你喜欢

热点阅读