最近在接触深度学习,在自然语言处理的应用中,不可避免的要把文本转换成词向量,那么如何转化它呢?以及目前几种主要转化方式是有什么不一样呢?

接下来借助我最近做的文本分类的问题加以解释说明,主要理清word2vec和keras提供的Embedding层的差别,这也是一度使我比较困惑的地方。

一、one-hot

一切要从one-hot编码开始。我们在对文本进行预处理时,一般会根据自己的训练文档来构建一个词汇表,再对单词进行one-hot编码。

比如说在我们的所有的训练集中存在10000个互不相同的单词,那么就可以利用这10000个单词构成词汇表。我们对这10000个单词进行one-hot编码时,每个单词的向量表示都是10000维,且其中只有1和0的表示方式。假设一个单词my出现在第5个位置,那么my这个单词的10000维的向量表示中,只有第5个位置为1,其余的都为0,即[0,0,0,0,1,0,0,......]的形式。

这样就造成了一个问题,就是用one-hot编码表示的词向量会很高维也很稀疏,尤其当词汇表(字典)很大时,其效率更是低下。

二、Word Embedding(词嵌入)

由于one-hot编码表示稀疏的问题,那么词嵌入的表示表示方法就出现了。词嵌入是使用密集的矢量表示来表示单词和文档的一类方法。单词由密集向量表示,其中向量表示将单词投影到连续向量空间中。向量空间中的单词的位置是从文本中学习的,并且基于在使用单词时围绕单词的单词。学习到的向量空间中的单词的位置被称为它的嵌入:Embedding。

词嵌入有两种方式:一是单词嵌入方法(如Word2Vec)、二是神经网络中的embedding层(如keras的embedding层

那么二者有什么关系呢?

      其实二者的目标是一样的,都是我们为了学到词的稠密的嵌入表示。只不过学习的方式不一样。

      word2vec是无监督的学习方式,利用上下文环境来学习词的嵌入表示,因此可以学到相关词;

      而在keras的embedding层中,权重的更新是基于标签的信息进行学习,为了达到较高的监督学习的效果,它本身也可能会学      到相关词。

word2vec的原理这里就不进行介绍了,请参考这篇博客

下面说一下keras的Embedding层:

三、keras Embedding

Keras提供了一个嵌入层Embedding,适用于文本数据的神经网络。

1、嵌入层被定义为网络的第一个隐藏层。其用法如下所示:(参考这个查看详细API)

keras.layers.Embedding(input_dim, output_dim, embeddings_initializer='uniform', input_length=None)

它必须指定3个参数:

       input_dim:输入的文本数据中词汇的取值可能数,即词汇表(词典)的大小。

       output_dim:输出的嵌入单词的向量空间的大小,即为单词指定的输出维度。

       input_length:输入序列的长度。

       embeddings_initializer:权重矩阵的初始化方法。(可使用weights参数指定初始化值,或者使用initializer随机初始化)

2、嵌入层是一个灵活的图层,可以以多种方式使用,例如:

       它可以单独使用来学习一个单词嵌入,以后可以保存并在另一个模型中使用。

       它可以作深度学习模型的一部分,其中嵌入与模型本身一起学习。

       可以用来加载预先训练的词嵌入模型(比如word2vec模型),这是一种迁移学习

当不预先加载已训练好的词嵌入模型时,它使用随机初始化权重;否则,可以用已训练好的模型来初始化权重。

四、例子

1、使用word2vec模型初始化embedding层的权重

     1)训练word2vec模型:

//加载语料并训练
sentences = word2vec.Text8Corpus(r'F:/practise/graduateDesign/WOSCorpos.txt')
model  = word2vec.Word2Vec(sentences,sg=1, size = 100,hs = 1,min_count =1,window =3)
model.save("F:/practise/graduateDesign/WOSword2vec.model")

    2)加载模型并形成初始权重矩阵

embedding_model = word2vec.Word2Vec.load(model_name)#加载训练好的模型
 #模型中有的单词向量就用该向量表示,没有的则随机初始化一个向量
 embedding_weights = np.array(embedding_model[word] if word in embedding_model else
                              np.random.uniform(-0.25, 0.25, embedding_model.vector_size)
                         for word in embedding_model.wv.vocab.items())

 3)为使用keras写的cnn模型的wmbedding层设置初始的权重矩阵(使用weights参数)

weights = np.array([v for v in embedding_weights.values()]) 
z = Embedding(
        len(vocabulary_inv), 
        embedding_dim, 
        input_length=sequence_length, 
        weights=[weights]#为embedding层设置初始权重矩阵
        )(model_input)

4)后面就按基本的cnn编写即可。完整代码请查看这里https://github.com/wenjinhua/Text-classification-CNN