NLP----词向量的训练方法CBOW、Skip-Gram

本文深入探讨了搜索引擎的工作原理,重点介绍了TF-IDF算法如何将文本转化为向量表示。同时,讲解了词向量训练方法CBOW和Skip-Gram,它们利用上下文关系学习词的向量表示,以提高精度。通过实例展示了如何使用Python实现这些技术,并讨论了它们在速度和准确性上的权衡。

1.搜索引擎的原理----TF-IDF

网页变成索引,存到搜索引擎的数据库里,等待被搜索

多模态搜索: 用文字搜索视频,用图片搜索视频,用图片搜索文字,等等
将图片,视频转化为数字,与其他转化为数字的视频,文字,视频进行匹配

BigData --> 批量召回 --> 粗排 --> 精排
层层筛选过滤,使用时间消耗较少的方法
将深度学习放在最后精排,使其时间消耗更短

TF-IDF: TF词频(Term Frequency) IDF逆文本频率指数(Inverse Document Frequency)
词频,就是词在文章中出现的频率,次数。 文章信息的局部信息
逆文本频率指数,指一个词在文本中的区分力大小,避免了常用词,如你我他词频太高带来的影响。 系统的全局信息
一般用TF * IDF来表示文章,表示文章的关键内容

使用IDF时,可以在专一的某一个领域下训练出一个特定的IDF值,比范领域下的IDF精确度要好。

把文章或者视频,语句转化为向量,用向量的相似性来匹配最相似的文章,cos距离计算。

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity


docs = [
        "it is a good day,I like to stay here",
        "I am happy to be here",
        "I am bob",
        "it is sunny today",
        "I have a party today",
        "it is a dog and that is a cat",
        "there are dog and cat on the tree",
        "I study hard this morning",
        "today is a good day",
        "tomorrow will be a good day",
        "I like coffee,I like book and I like apple",
        "I do not like it",
        "I am kitty,I like bob",
        "I do not care who like bob, but I like kitty",
        "It is coffee time, bring your cups",
        ]

vectorizer = TfidfVectorizer()
# 直接调用TfidfVectorizer的fit_transformer方法就可以得到tf-idf值了
tf_idf = vectorizer.fit_transform(docs)
print("idf: ",[(n,idf) for idf,n in zip(vectorizer.idf_,vectorizer.get_feature_names())])

计算出来idf如下所示:
在这里插入图片描述
idf也可以单独提取出来,用去其他的操作和使用,如果有相同类型的文章集合也可以不用再去训练idf了

然后打印出每个单词对应的索引print("v2i:",vectorizer.vocabulary_)
在这里插入图片描述
那如果再来一个文本,就可以通过它的tf-idf向量与文本库里面的向量进行比对,找出最适合的向量

qtf_idf = vectorizer.transform([q])
res = cosine_similarity(tf_idf,qtf_idf)

把匹配结果按照分数高低进行排序

res = res.ravel().argsort()[-3:] # 只取最匹配的前三名
print("\ntop 3 docs for '{}':\n{}".format(q,[docs[i] for i in res[::-1]]))

在这里插入图片描述
在这里插入图片描述
tf-idf匹配流程:
1.实例化TfidfVectorizer()对象
2.输入若干条文本,transform成tf-idf向量
3.用cosin距离进行计算最匹配的文本

可以看到这里每个文本都变成了一个44维的向量
在这里插入图片描述
在这里插入图片描述
为什么都是44维呢,因为每个词有一个tf,有一个idf,那这总共的文本就一共有44维向量

BERT 注意力机制
集群版搜索引擎 ElasticSearch
搜索引擎流程:
Query --> 分词、敏感词过滤、纠错、拼音识别、查询改写、查询补全…–>ElasticSearch、热度召回、地理信息召回、…–>搜索结果

2.词向量训练方法----CBOW,skip-gram

深度学习的技术CBOW,非深度学习的技术TF-IDF,一个精度更高,一个更快。

中性词:区分力不大的词,“在”,“是”… 这些

One-hot represention 将词汇用二进制向量表示,这个向量表示的词汇,仅仅在词汇表中的索引位置处为1,其他地方都为0。
在这里插入图片描述
这样的缺点其实是很多的,所以有一种embedding的方法:
在这里插入图片描述
Word Embedding得到的向量维度远小于词汇表的个数,通过词向量之间的距离可以度量他们之间的关系。

训练词向量
非监督学习,取一小段文本,计算词向量,用整个向量预测最中间的那个词,依次类推,计算机就能搞清楚前后文关系,距离越近的词,关系越亲密。

输入[‘我’][‘中国’]
输出[‘爱’]

同样也可以用中间词预测前后文

CBOW(Continuous Bag of Words)
tf-idf算法是通过一种统计学的方式来用文章中的词的重要程度,转化成向量来表示一篇文章的。速度较快,但是准确率不如深度学习的方法

CBOW就是挑一个要预测的词,来学习这个词前后文中词语和预测词的关系,那每个词都可以在一个空间中表示出来,可以通过空间位置知道词语之间的对应关系,理论上,语义越相近的词语将会距离更近

corpus = [
    # numbers
    "5 2 4 8 6 2 3 6 4",
    "4 8 5 6 9 5 5 6",
    "1 1 5 2 3 3 8",
    "3 6 9 6 8 7 4 6 3",
    "8 9 9 6 1 4 3 4",
    "1 0 2 0 2 1 3 3 3 3 3",
    "9 3 3 0 1 4 7 8",
    "9 9 8 5 6 7 1 2 3 0 1 0",

    # alphabets, expecting that 9 is close to letters
    "a t g q e h 9 u f",
    "e q y u o i p s",
    "q o 9 p l k j o k k o p",
    "h g y i u t t a e q",
    "i k d q r e 9 e a d",
    "o p d g 9 s a f g a",
    "i u y g h k l a s w",
    "o l u y a o g f s",
    "o p i u y g d a s j d l",
    "u k i l o 9 l j s",
    "y g i s h k j l f r f",
    "i o h n 9 9 d 9 f a 9",
]

例如这里又字母也有数字,假设他们都是单词,那根据前后文关系,其实应该是学到字母们在向量空间上的位置更相近,而数字的位置更相近,对于数字9这个与字母也前后文关系密切,与数字也前后文关系密切的,应该空间上离两者都很近

构造模型的训练集,这里是将一句话中滑动移动5个单词的窗口,以前后两个,共四个单词作为训练数据的特征,中间那个词作为训练数据的标签

# 3.定义产生训练数据的方法
class Dataset:
    def __init__(self, x, y, v2i, i2v):
        self.x, self.y = x, y
        self.v2i, self.i2v = v2i, i2v
        self.vocab = v2i.keys()

    def sample(self, n):
        b_idx = np.random.randint(0, len(self.x), n) # 产生随机数
        bx, by = self.x[b_idx], self.y[b_idx] # 使顺序打散训练,这样每一次调用,都会产生shuffle的数据
        return bx, by

    @property
    def num_word(self):
        return len(self.v2i)


def process_w2v_data(corpus, skip_window=2, method="skip_gram"):
    all_words = [sentence.split(" ") for sentence in corpus]
    all_words = np.array(list(itertools.chain(*all_words))) # 连成一条
    # vocab sort by decreasing frequency for the negative sampling below (nce_loss).
    vocab, v_count = np.unique(all_words, return_counts=True) # 统计有多少种不同的词,以及个数
    vocab = vocab[np.argsort(v_count)[::-1]] # 按照个数从多到少排序

    print("all vocabularies sorted from more frequent to less frequent:\n", vocab)
    v2i = {
   
   v: i for i, v in enumerate(vocab)} # 单词即对应的索引,从大到小拍多少号
    i2v = {
   
   i: v for v, i in v2i.items()}  # 从索引找到单词

    # pair data
    pairs = []
    js = [i for i in range(-skip_window, skip_window + 1) if i != 0]
    # -2到2一共五个单词,去掉最中间的,窗口大小为5

    for c in corpus:
        words = c.split(" ")
        w_idx = [v2i[w] for w in words] # 把每一行文本的单词都换成索引放在列表里
        if method == "skip_gram":
            for i in range(len(w_idx)):
                for j in js:
                    if i + j < 0 or i + j >= len(w_idx):
                        continue
                    pairs.append((w_idx[i], w_idx[i + j]))  # (center, context) or (feature, target)
        elif method.lower() == "cbow":
            for i in range(skip_window, len(w_idx) - skip_window): # 在这一行列表上开始滑动窗口,每一次华东都包含5个单词
                context = [] # 装每个窗口的五个单词的索引,context里面装的是前后共四个
                for j in js:
                    context.append(w_idx[i + j])
                pairs.append(context + [w_idx[i]])  # (contexts, center) or (feature, target)
        else:
            raise ValueError
    pairs = np.array(pairs)
    print("5 example pairs:\n", pairs[:5])
    if method.lower() == "skip_gram":
        x, y = pairs[:, 0], pairs[:, 1]
    elif method.lower() == "cbow":
        x, y = pairs[:, :-1], pairs[:, -1]
    else:
        raise ValueError
    return Dataset(x, y, v2i, i2v)

首先是把所有的单词进行一个词频的统计以及排序,为他们安排一个索引
在这里插入图片描述
所有的单词排序从出现词频最多的到最低的,同时每个词具有了一个索引,把上述的整段文本,用索引来转化
在这里插入图片描述

然后对每一句话开始以窗口为5划窗,中间的摘出来作为标签,那么特征就是:
[16, 14, 12, 3]
[14, 9, 3, 14]
[9, 12, 14, 1]
[12, 3, 1, 3]
[3, 14, 3, 9]
[9, 12, 3, 0]
[12, 16, 0, 16]
[16, 3, 16, 16]
[3, 0, 16, 3]
[5, 5, 14, 1]
[5, 16, 1, 1]
[16, 14, 1, 12]
[1, 3, 3, 12]
[3, 0, 12, 25]
[0, 3, 25, 9]
[3, 12, 9, 3]
[12, 25, 3, 1]
[12, 0, 3, 5]
[0, 0, 5, 9]
[0, 3, 9, 1]
[3, 5, 1, 9]
[5, 23, 23, 14]
[23, 14, 14, 5]
[14, 23, 5, 1]
[23, 14, 1, 1]
[14, 5, 1, 1]
[5, 1, 1, 1]
[1, 1, 1, 1]
[0, 1, 23, 5]
[1, 1, 5, 9]
[1, 23, 9, 25]
[23, 5, 25, 12]

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值