在之前的文章中谈到了文本向量化的一些基本原理和概念,本文将介绍Word2Vec的代码实现

https://www.cnblogs.com/dogecheng/p/11470196.html#Word2Vec

Word2Vec论文地址

https://arxiv.org/abs/1301.3781

1.Embedding

与one-hot编码相比,词嵌入可以将更多的信息塞入更低的维度中

下面我们用 Keras 完成一个词嵌入的学习,Keras 的 Embedding 层的输入是一个二维整数张量, 形状为(samples,sequence_length),即(样本数,序列长度)

较短的序列应该用 0 填充,较长的序列应该被截断,保证输入的序列长度是相同的

Embedding 层输出是(samples,sequence_length,embedding_dimensionality) 的三维浮点数张量

  • 首先,我们需要对文本进行分词处理,然后对分词结果进行序列化
  • 再统一输入的序列长度,最后把统一长度的序列化结果输入到 Embedding 层中

整个过程可以用下面的图描述

从样本的角度看,我们可以用下面的图描述这个过程

示意代码如下

from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import pad_sequences
from keras.models import Sequential
from keras.layers import Embedding, Flatten, Dense
docs = ["The cat sat on the mat.", "I love green eggs and ham."] # 只考虑最常见的8个单词
max_words = 8
# 统一的序列化长度
# 大于这个长度截断,小于这个长度用0补全
maxlen = 5
# 嵌入的维度
embedding_dim = 3 # 分词
tokenizer = Tokenizer(num_words=max_words)
tokenizer.fit_on_texts(docs)
# 字典
word_index = tokenizer.word_index # 序列化
sequences = tokenizer.texts_to_sequences(docs)
# 统一序列长度
data = pad_sequences(sequences, maxlen=maxlen) # Embedding模型
model = Sequential()
# Embedding至少需要max_wrods和embedding_dim两个参数
model.add(Embedding(max_words, embedding_dim, input_length=maxlen, name='embedding'))
model.compile('rmsprop', 'mse') out = model.predict(data)
print(out)
print(out.shape)
# 查看权重
layer = model.get_layer('embedding')
print(layer.get_weights())

刚刚对Keras中的一些文本处理模块和Embedding做了简单的说明和演示

在Embedding层后面可以跟上神经网络,完成各种文本任务

下面使用IMDB电影评论做一个情感预测任务

from keras.datasets import imdb
from keras import preprocessing
from keras.models import Sequential
from keras.layers import Flatten, Dense, Embedding # 特征单词数
max_words = 10000
# 在20单词后截断文本
# 这些单词都属于max_words中的单词
maxlen = 20
# 嵌入维度
embedding_dim = 8 # 加载数据集
# 加载的数据已经序列化过了,每个样本都是一个sequence列表
(x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=max_words) # 统计序列长度,将数据集转换成形状为(samples,maxlen)的二维整数张量
x_train = preprocessing.sequence.pad_sequences(x_train, maxlen=maxlen)
x_test = preprocessing.sequence.pad_sequences(x_test, maxlen=maxlen) # 构建模型
model = Sequential()
model.add(Embedding(max_words, embedding_dim, input_length=maxlen))
# 将3维的嵌入张量展平成形状为(samples,maxlen * embedding_dim)的二维张量
model.add(Flatten())
model.add(Dense(1, activation='sigmoid'))
model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['acc'])
model.summary() history = model.fit(x_train, y_train, epochs=10, batch_size=32, validation_split=0.2)

我们只是简单测试一下,我们最后得到的效果如下图所示,这是只看前20个(maxlen为20)单词的效果

如果增加到50个单词,验证集就达到了80%的正确率

2.Word2Vec

2.1.gensim实现Word2Vec

gensim库提供了一个word2vec的实现,我们使用几个API就可以方便地完成word2vec

from gensim.models import Word2Vec
import re
documents = ["The cat sat on the mat.", "I love green eggs and ham."]
sentences = []
# 去标点符号
stop = '[’!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~]+'
for doc in documents:
doc = re.sub(stop, '', doc)
sentences.append(doc.split())
#sentences = [["The", "cat", "sat", "on", "the", "mat"],
# ["I", "love", "green", "eggs", "and", "ham"]] # size嵌入的维度,window窗口大小,workers训练线程数
# 忽略单词出现频率小于min_count的单词
# sg=1使用Skip-Gram,否则使用CBOW
model = Word2Vec(sentences, size=5, window=1, min_count=1, workers=4, sg=1)
print(model.wv['cat'])

训练得到Word2Vec模型后,我们在Keras的Embedding层中使用这个Word2Vec得到的权重

再利用神经网络或其他方法去完成各种文本任务

2.2.Keras的Embedding和Word2Vec

我们去kaggle上下IMDB的电影评论数据集,用这个数据集来学习

因为在自己电脑上跑程序,没有用服务器,本文只取了前100条用来学习

https://www.kaggle.com/c/word2vec-nlp-tutorial/data

下面是kaggle上别人用这个数据集做的实验

https://www.kaggle.com/alexcherniuk/imdb-review-word2vec-bilstm-99-acc/data

import pandas as pd
import re
from gensim.models import Word2Vec
from keras.preprocessing.sequence import pad_sequences
from sklearn.model_selection import train_test_split
from keras.models import Sequential
from keras.layers import Embedding, Flatten, Dense
"""
读取训练集并构造训练样本
"""
def split_sentence(sentence):
stop = '[’!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~]+'
sentence = re.sub(stop, '', sentence)
return sentence.split() data = pd.read_csv(r"F:\pythonWP\keras\blog\labeledTrainData.tsv", sep='\t')
data = data[:100]
sentences = data.review.apply(split_sentence) """
训练Word2Vec
"""
# 嵌入的维度
embedding_vector_size = 10
w2v_model = Word2Vec(
sentences=sentences,
size=embedding_vector_size,
min_count=1, window=3, workers=4) # 取得所有单词
vocab_list = list(w2v_model.wv.vocab.keys())
# 每个词语对应的索引
word_index = {word: index for index, word in enumerate(vocab_list)}
# 序列化
def get_index(sentence):
global word_index
sequence = []
for word in sentence:
try:
sequence.append(word_index[word])
except KeyError:
pass
return sequence
X_data = list(map(get_index, sentences)) # 截长补短
maxlen = 150
X_pad = pad_sequences(X_data, maxlen=maxlen)
# 取得标签
Y = data.sentiment.values
# 划分数据集
X_train, X_test, Y_train, Y_test = train_test_split(
X_pad,
Y,
test_size=0.2,
random_state=42) """
构建分类模型
"""
# 让 Keras 的 Embedding 层使用训练好的Word2Vec权重
embedding_matrix = w2v_model.wv.vectors model = Sequential()
model.add(Embedding(
input_dim=embedding_matrix.shape[0],
output_dim=embedding_matrix.shape[1],
input_length=maxlen,
weights=[embedding_matrix],
trainable=False))
model.add(Flatten())
model.add(Dense(5))
model.add(Dense(1, activation='sigmoid')) model.compile(
loss="binary_crossentropy",
optimizer='adam',
metrics=['accuracy']) history = model.fit(
x=X_train,
y=Y_train,
validation_data=(X_test, Y_test),
batch_size=4,
epochs=10) 

由于训练样本少,得到的模型没有太大意义,波动也大,仅用来学习。整个训练集的使用可以去上面分享的链接去看kaggle上别人的实验

2.3.LSTM和Word2Vec实现电影评论情感分析

数据集还是使用的跟上面是一样的,kaggle 上 IMDB 的电影评论数据集。下面的代码是在服务器上测试的。

https://www.kaggle.com/c/word2vec-nlp-tutorial/data

在建模之前,需要进行简单的数据处理,这是其中一条评论。可以看到,里面还有存在 html 的标签 <br />还有许多标点符号 \\ 、 " 和 () 等等

'<br /><br />This movie is full of references. Like \\Mad Max II\\", \\"The wild one\\" and many others. The ladybug´s face it´s a clear reference (or tribute) to Peter Lorre. This movie is a masterpiece. We´ll talk much more about in the future."'

我们预处理首先就要去掉 html 标签和这些标点符号标点符号保留 “-” 和 “´” 下进行测试

  • 一些缩写会用到上引号,如 We´ll
  • 一些短语会用到小横杆,比如 heavy-handed

另外,为了简化训练词向量和模型训练的过程,还进行了其他处理,比如转换为小写词性还原。然后使用停用词库去除一些对 情感分析 用处不大的词。

比如a, an, the 等

停用词库简单使用了 sklearn 中自带的停用词。预处理代码如下

import pandas as pd
import re
from sklearn.feature_extraction import text
from nltk.stem import WordNetLemmatizer # 读取数据
data = pd.read_csv(r"./data/labeledTrainData.tsv", sep='\t') def clean_review(raw_review: str) -> str:
# 1. 评论是爬虫抓取的,存在一些 html 标签,需要去掉
review_text = raw_review.replace("<br />", '')
# 2. 标点符号只保留 “-” 和 上单引号
review_text = rex.sub(' ', review_text)
# 3. 全部变成小写
review_text = review_text.lower()
# 4. 分词
word_list = review_text.split()
# 5. 词性还原
tokens = list(map(lemmatizer.lemmatize, word_list))
lemmatized_tokens = list(map(lambda x: lemmatizer.lemmatize(x, "v"), tokens))
# 6. 去停用词
meaningful_words = list(filter(lambda x: not x in stop_words, lemmatized_tokens))
return meaningful_words stop_words = set(text.ENGLISH_STOP_WORDS)
rex = re.compile(r'[!"#$%&\()*+,./:;<=>?@\\^_{|}~]+')
lemmatizer = WordNetLemmatizer() sentences = data.review.apply(clean_review)

训练 Word2Vec 获取词向量

from gensim.models import Word2Vec
embedding_vector_size = 256
w2v_model = Word2Vec(
sentences=sentences,
size=embedding_vector_size,
min_count=3, window=5, workers=4)

查看预处理完每句话大概有多少个单词

cal_len = pd.DataFrame()
cal_len['review_lenght'] = list(map(len, sentences))
print("中位数:", cal_len['review_lenght'].median())
print("均值数:", cal_len['review_lenght'].mean())
del cal_len
中位数: 82.0
均值数: 110.52928

用 数字索引 表示原来的句子

from keras.preprocessing.sequence import pad_sequences
from sklearn.model_selection import train_test_split # 取得所有单词
vocab_list = list(w2v_model.wv.vocab.keys())
# 每个词语对应的索引
word_index = {word: index for index, word in enumerate(vocab_list)}
# 序列化
def get_index(sentence):
global word_index
sequence = []
for word in sentence:
try:
sequence.append(word_index[word])
except KeyError:
pass
return sequence
X_data = list(map(get_index, sentences)) # 截长补短
# max_len 根据中位数和平均值得来的
maxlen = 100
X_pad = pad_sequences(X_data, maxlen=maxlen)
# 取得标签
Y = data.sentiment.values
# 划分数据集
X_train, X_test, Y_train, Y_test = train_test_split(
X_pad,
Y,
test_size=0.2,
random_state=42)

构建和训练模型

from keras.models import Sequential
from keras.layers import Embedding, Bidirectional, LSTM, Dropout, Dense # 让 Keras 的 Embedding 层使用训练好的Word2Vec权重
embedding_matrix = w2v_model.wv.vectors model = Sequential()
model.add(Embedding(
input_dim=embedding_matrix.shape[0],
output_dim=embedding_matrix.shape[1],
input_length=maxlen,
weights=[embedding_matrix],
trainable=False))
model.add(Bidirectional(LSTM(128, recurrent_dropout=0.1)))
model.add(Dropout(0.25))
model.add(Dense(128, activation='sigmoid'))
model.add(Dropout(0.3))
model.add(Dense(1, activation='sigmoid')) model.compile(
loss="binary_crossentropy",
optimizer='adam',
metrics=['accuracy']
) history = model.fit(
x=X_train,
y=Y_train,
validation_data=(X_test, Y_test),
batch_size=50,
epochs=8
)

实验结果,准确率81左右

Embedding和Word2Vec实战的更多相关文章

  1. embedding与word2vec

    embedding是指将目标向量化,常用于自然语言处理(如:Word2Vec).这种思想的意义在于,可以将语义问题转换为数值计算问题,从而使计算机能够便捷处理自然语言问题.如果采用传统的One-hot ...

  2. Word Embedding与Word2Vec

    http://blog.csdn.net/baimafujinji/article/details/77836142 一.数学上的“嵌入”(Embedding) Embed这个词,英文的释义为, fi ...

  3. 无所不能的Embedding 1 - Word2vec模型详解&amp;代码实现

    word2vec是google 2013年提出的,从大规模语料中训练词向量的模型,在许多场景中都有应用,信息提取相似度计算等等.也是从word2vec开始,embedding在各个领域的应用开始流行, ...

  4. word2vec和word embedding有什么区别?

    word2vec和word embedding有什么区别? 我知道这两个都能将词向量化,但有什么区别?这两个术语的中文是什么? from: https://www.zhihu.com/question ...

  5. 用gensim学习word2vec

    在word2vec原理篇中,我们对word2vec的两种模型CBOW和Skip-Gram,以及两种解法Hierarchical Softmax和Negative Sampling做了总结.这里我们就从 ...

  6. 学习笔记CB011:lucene搜索引擎库、IKAnalyzer中文切词工具、检索服务、查询索引、导流、word2vec

    影视剧字幕聊天语料库特点,把影视剧说话内容一句一句以回车换行罗列三千多万条中国话,相邻第二句很可能是第一句最好回答.一个问句有很多种回答,可以根据相关程度以及历史聊天记录所有回答排序,找到最优,是一个 ...

  7. Python gensim库word2vec 基本用法

    ip install gensim安装好库后,即可导入使用: 1.训练模型定义 from gensim.models import Word2Vec   model = Word2Vec(senten ...

  8. Word Embedding理解

    一直以来感觉好多地方都吧Word Embedding和word2vec混起来一起说,所以导致对这俩的区别不是很清楚. 其实简单说来就是word embedding包含了word2vec,word2ve ...

  9. tensorflow加载embedding模型进行可视化

    1.功能 采用python的gensim模块训练的word2vec模型,然后采用tensorflow读取模型可视化embedding向量 ps:采用C++版本训练的w2v模型,python的gensi ...

随机推荐

  1. appfuse:Excel导出

    1.pom.xml <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi< ...

  2. 6_PHP AJAX MYSQL

    XAMPP套装软件: 包含Apache.MySQL.PHP等多个开源软件的集合. https://www.apachefriends.org/zh_cn/index.html 监听完整相应消息: Wi ...

  3. mybatis中crud操作范例

    <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-/ ...

  4. 黑客长期摇号不中&quot;黑&quot;掉北京小客车摇号网

    新闻链接:http://www.2cto.com/News/201310/248936.html 新闻时间:2013-10-11 新闻正文: 为发泄长期摇号不中的不满,同时也为自己研发的软件打广告,硕 ...

  5. alter语法的简单的使用

    用alter语法来新增列名,修改列名,删除列

  6. java中计算两个日期之间天数的程序设计。

    //用java编写出一个以下方法计算两个日期之间天数的程序设计. import java.util.regex.Matcher; import java.util.regex.Pattern; pub ...

  7. find the nth digit(二分查找)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1597 find the nth digit Time Limit: 1000/1000 MS (Jav ...

  8. Python hashlib 无法打印

    # !/user/bin/python # -*- coding: utf-8 -*- import hashlib # 可提供MD5算法 , 防止内页被篡改 (若内页未被篡改, MD5的值是不变的) ...

  9. 设计通用的Adapter

    2019年3月18日 10:53:27 参照博文:Android 快速开发系列 打造万能的ListView GridView 适配器 一 BaseViewHolder public class Bas ...

  10. html模板输头部出现&quot;&amp;#65279&quot;