过去的NLP实验人员发现了一种揭示词组合的意义的算法,该算法通过计算向量来表示上述词组合的意义。它被称为隐语义模型(latent semantic analysis,LSA)。当使用该工具时,我们不仅可以把词的意义表示为向量,还可以用向量来表示整篇文档的意义。
在本章中,我们将学习这些语义或主题向量。我们将使用TF

目录

  • 1.TF-IDF向量及词形归并
  • 2.主题向量
  • 3.思想实验
  • 4.一个主题评分算法
  • 5.一个LDA分类器

1.TF-IDF向量及词形归并

TF-IDF向量会对文档中词项的准确拼写形式进行计数。因此,如果表达相同含义的文本使用词的不同拼写形式或使用不同的词,将会得到完全不同的TF-IDF向量表示。
在之前的学习中,我们对词尾进行了归一化处理,使那些仅仅最后几个字符不同的词被归并到同一个词条。我们使用了归一化方法(如词干还原和词形归并)来创建拼写相似、含义通常也相似的小型的词集合。我们用这些词集合的词元或词干来标记这些小型的词集合,然后处理这些新的词条而不是原始词。
上述分析中,词形归并的方法将拼写相似的词放在一起,但是这些词的意义不一定相似。显然,它无法成功处理大多数同义词对,也无法将大多数同义词配对。同义词的区别通常不仅仅是词形归并和词干还原处理的词尾不同。更糟糕的是,词形归并和词干还原有时会错误地将反义词归并在一起。
上述词形归并造成的最终结果是,在我们得到的TF-IDF向量空间模型下,如果两段文本讨论的内容相同,但是使用了不同的词,那么它们在此空间不会”接近“。而有时,两个词形归并后的TF-IDF向量虽然相互接近,但在意义上根本不相似。


2.主题向量

当我们对TF-IDF向量进行数学运算(加法、减法)时,这些和与差告诉我们的只是参与运算的向量表示的文档中词的使用频率。上述数学运算并没有告诉我们这些词背后的含义。通过将TF-IDF矩阵与自身相乘,可以计算词与词的TF-IDF向量(词共现或关联向量)。但是利用这些稀疏的高维向量进行”向量推理“效果并不好。这是因为当我们将这些向量相加或相减时,它们并不能很好地表示一个已有的概念、词或主题。
因此,我们需要一种方法来从词的统计数据中提取一些额外的信息,即意义信息。我们想用一个像TF-IDF一样的向量来表示意义,但是需要这个向量表示更紧凑、更有意义。
我们称这些紧凑的意义向量为”词-主题向量“(word-topic vector),称文档的意义向量为”文档-主题向量“(document-topic vector)。
处理完语料库后,语料库中的每篇文档将会对应一个文档-主题向量。而且,更重要的是,对于一个新文档或短语,我们不必重新处理整个语料库就可以计算得到其对应的新主题向量。词汇表中的每个词都会有一个主题向量,我们可以使用这些词-主题向量来计算词汇表中部分词构成的任何文档的主题向量。
我们需要找到属于用一个主题的那些词维度,然后对这些词维度的TF-IDF值求和,以创建一个新的数值来表示文档中该主题的权重。我们甚至可以对词维度进行加权以衡量它们对主题的重要度,以及我们所希望的每个词对这个组合(混合)的贡献度。我们也可以用负权重来表示词,从而降低文本与该主题相关的可能性。


3.思想实验

假设我们在处理一些关于纽约(NYC)中央公园中宠物的句子。我们创建了3个主题:一个与宠物有关,称为”petness“;一个与动物有关,称为”animalness“;一个与城市有关,称为”cityness“。因此,”prtness“会给”cat“和”dog“这样的词打高分,但很可能忽略”NYC“和”apple“这样的词。接下来我们简单的对数据赋予一些权重:

import numpy as np
topic = {}
tfidf = dict(list(zip('cat dog apple lion NYC love'.split(), np.random.rand(6))))
topic['petness'] = (.3 * tfidf['cat'] + .3 * tfidf['dog'] + 0 * tfidf['apple'] + 0 * tfidf['lion'] - .2 * tfidf['NYC'] + .2 * tfidf['love'])
topic['animalness'] = (.1 * tfidf['cat'] + .1 * tfidf['dog'] - .1 * tfidf['apple'] + .5 * tfidf['lion'] + .1 * tfidf['NYC'] - .1 * tfidf['love'])
topic['cityness'] = (0 * tfidf['cat'] - .1 * tfidf['dog'] + .2 * tfidf['apple'] - .1 * tfidf['lion'] + .5 * tfidf['NYC'] + .1 * tfidf['love'])

在上述思想实验中,我们把可能表示每个主题的词频加起来,并根据词与主题关联的可能性对词频(TF-IDF值)加权,同样,对于那些可能在某种意义上与主题相反的词,我们也会做类似的事,只不过这次是减而不是加。
这里,我们只是很随意地选择将词和文档分解为3个主题。同时,我们这里的词汇量也极其有限,只有6各词。
一旦确定了3个要建模的主题,就必须确定这些主题中每个词的权重。主题建模转换是一个36的比例矩阵(权重),代表3个主题与6个词之间的关联。用这个矩阵乘以一个假想的61TF-IDF向量,就得到了该文档的一个31的主题向量。
在阅读上述向量时,大家可能已经意识到词和主题之间的关系可以翻转。3个主题向量组成的3
6矩阵可以转置,从而为词汇表中的每个词生成主题权重。

我们语料库中的文档可能会使用更多的词,但是这个特定的主题向量模型只会受到这6个词的用法的影响。我们可以将这种办法扩展到尽可能多的词,只要我们有足够的耐心(或算法)。只要模型还需要根据3个不同的维度或主题来区分文档,词汇表就可以像我们希望的那样不断增长。在上述思想实验中,我们将6维(TF-IDF归一化频率)压缩为3维(主题)。


4.一个主题评分算法

20世纪的英国语言学家J.R.Firth研究了如何估计一个词或语素的含义。1957年,他给出了一条如何计算词主题的线索,他写道:可以通过词的上下文来理解它。
最直接的方法是计算词和上下文在同一文档中的共现次数。LSA是一种分析TF-IDF矩阵的算法,它将词分组到主题中。LSA也可以对词袋向量进行处理,但是TF-IDF向量给出的结果稍好。
LSA还对这些主题进行了优化,以保持主题维度的多样性。当使用这些新主题而不是原始词时,我们仍然可以捕获文档的大部分含义(语义)。该模型中用于捕获文档含义所需的主题数量远远少于TF-IDF向量词汇表中的词的数量。因此,LSA通常被认为是一种降维技术。LSA减少了捕获文档含义所需的维数。
有两种算法与LSA相似,它们也有相似的NLP应用:

  • 线性判别分析(linear discriminant analysis,LDA)
  • 隐性狄利克雷分布(latent Dirichlet allocation,LDiA)
    LDA将文档分解到单个主题中,而LDiA则更像LSA,因为它可以将文档分解到任意多个主题中

5.一个LDA分类器

LDA是最直接也是最快速的降维和分类模型之一,LDA分类器是一种有监督算法,因此需要对文档的类进行标注。
在本例中,我们给出了LDA的一个简单的实现版本,该实现无法在scikit-learn中找到。模型训练只有3个步骤,我们可以直接使用python来实现

  1. 计算某个类(如垃圾短消息类)中所有TF-IDF向量的平均位置(质心)
  2. 计算不在该类(如非垃圾短消息类)中的所有TF-IDF向量的平均位置(质心)
  3. 计算上述两个质心之间的向量差(即链接这两个向量的直线)
import pandas as pd
from nlpia.data.loaders import get_data
pd.options.display.width = 120
sms = get_data('sms-spam')
print(sms)
index = ['sms{}{}'.format(i, "!" * j) for (i, j) in zip(range(len(sms)), sms.spam)]
sms = pd.DataFrame(sms.values, columns=sms.columns, index=index)
sms['spam'] = sms.spam.astype(int)
print(len(sms))
print(sms.spam.sum())
print(sms.head())


上述数据集中有4837条短消息,其中638条被标注为二类标签“spam”(垃圾类)
下面我们就对所有这些短消息进行分词,并将它们转换为TF-IDF向量:

from sklearn.feature_extraction.text import TfidfVectorizer
from nltk.tokenize.casual import casual_tokenize
tfidf_model = TfidfVectorizer(tokenizer=casual_tokenize)
tfidf_docs = tfidf_model.fit_transform(raw_documents=sms.text).toarray()
print(tfidf_docs.shape)

Out[1]:(4837, 9232)
经过casual_tokenize处理后的词汇表包含9232个词。词的数量几乎是短消息数的两倍,是垃圾短消息数的十倍。因此,模型不会有很多有关垃圾短消息指示词的信息。通常,当词汇表的规模远远大于数据集中标注的样本数量时,朴素贝叶斯分类器就不是很奏效,而这种情况下语义分析技术就可以提供帮助
下面先从最简单的语义分析技术LDA开始,我们可以在sklearn.discriminant_analysis.LinearDiscriminantAnalysis中使用LDA模型。但是,为了训练这个模型,只需要计算两个类(垃圾类和非垃圾类)的质心,因此我们可以直接这样做:

mask = sms.spam.astype(bool).values
# 因为TF-IDF向量是行向量,所以需要确保numpy使用axis=0独立计算每一列的平均值
spam_centroid = tfidf_docs[mask].mean(axis=0)
ham_centroid = tfidf_docs[~mask].mean(axis=0)
print(spam_centroid.round(2))
print(ham_centroid.round(2))

Out[1]:[0.06 0. 0. … 0. 0. 0. ]
Out[2]:[0.02 0.01 0. … 0. 0. 0. ]
现在可以用一个质心向量减去另一个质心向量从而得到分类线:

# 该点积计算的是每个向量在质心连线上的“阴影”投影
spamminess_score = tfidf_docs.dot(spam_centroid - ham_centroid)
print(spamminess_score.round(2))

Out[1]:[-0.01 -0.02 0.04 … -0.01 -0. 0. ]
这个原始的spamminess_score得分是非垃圾类质心到垃圾类质心的直线距离。我们用点积将每个TF-IDF向量投影到质心之间的连线上,从而计算出这个得分。
注意:点乘的几何意义是:是一条边向另一条边的投影乘以另一条边的长度。

LDA线性判别原理解析<数学推导>
在理想情况下,我们希望上述评分就像概率那样取值在0-1之间,sklearnMinMaxScaler可以帮我们做到这一点:

from sklearn.preprocessing import MinMaxScaler
sms['lda_score'] = MinMaxScaler().fit_transform(spamminess_score.reshape(-1,1))
sms['lda_predict'] = (sms.lda_score > .5).astype(int)
print(sms['spam lda_predict lda_score'.split()].round(2).head())

Out[1]:

上面的结果看起来不错,当将阈值设置为50%时,前5条消息都被正确分类。我们接下来看看它在训练集其余部分的表现:

print((1 - (sms.spam - sms.lda_predict).abs().sum() / len(sms)).round(3))

Out[1]:0.977
这个简单的模型对97.7%的消息进行了正确分类。
这就是语义分析方法的威力,与朴素贝叶斯或对率回归(logistic regression)模型不同,语义分析并不依赖独立的词。语义分析会聚合语义相似的词(如spamminess)并将它们一起使用。
现在,我们已经准备好学习可以计算多维语义向量而不仅仅时一维语义得分的模型,到目前为止,一维向量“理解”的唯一事情就是词和文档的垃圾行,我们希望它能够学习更多的词上的细微差别,并提供一个多维向量来捕捉词的含义

NLP自然语言处理实战(三):词频背后的语义--1.从词频到主题得分相关推荐

  1. NLP自然语言处理实战(三):词频背后的语义--4.隐性狄利克雷分布(LDiA)

    对大多数主题建模,语义搜索或基于内容的推荐引擎来说,LSA应该是我们的首选方法.它的数学机理直观.有效,它会产生一个线性变换,,可以应用于新来的自然语言文本而不需要训练过程,并几乎不会损失精确率.但是 ...

  2. NLP自然语言处理实战(三):词频背后的语义--3.主成分分析

    当SVD用于降维时,主成分分析(PCA)是SVD的另一个叫法.scikit-learn中的PCA模型对SVD做了一些调整,这将提高NLP流水线的精确率. 一方面,sklearn.PCA自动通过减去平均 ...

  3. NLP自然语言处理实战(三):词频背后的语义--5.距离和相似度反馈及改进

    目录 1.距离和相似度 2.反馈及改进 线性判别分析 1.距离和相似度 我们可以使用相似度评分(或距离),根据两篇文档的表达向量间的相似度(或距离)来判断文档间有多相似. LSA能够保持较大的距离,但 ...

  4. NLP 自然语言处理实战

    前言 自然语言处理 ( Natural Language Processing, NLP) 是计算机科学领域与人工智能领域中的一个重要方向.它研究能实现人与计算机之间用自然语言进行有效通信的各种理论和 ...

  5. 【nlp自然语言处理实战】案例---FastText模型文本分类

    目录 1.案例简介 2 代码 2.1 load_data.py 2.2 load_data_iter.py 2.3 FastText.py 2.4 train.py 2.5 predict.py 2. ...

  6. NLP自然语言处理实战(一):利用分词器构建词汇表

    在NLP中,分词(tokenization,也称分词)是一种特殊的文档切分(segmentation)过程.而文档切分能够将文本拆分成更小的文本块或片段,其中含有更集中的信息内容.文档切分可以是将文档 ...

  7. 《自然语言处理实战入门》 第三章 :中文分词原理及相关组件简介 ---- 语言学与分词技术简介

    文章大纲 0.内容梗概 1. 汉语语言学简介 1.1 汉语与汉字的起源 1.2 汉字的统一与演变 1.3 印欧语系与汉藏语系 1.4 语言区别对于NLP 的影响 2. 词汇与分词技术简介 2.1 汉语 ...

  8. NLP自然语言处理系列-音乐推荐系统实战 - 数据处理

    NLP自然语言处理系列-音乐推荐系统实战 - 数据处理 本文进行音乐推荐系统案例实战,对音乐数据集进行数据清洗和特征提取,基于矩阵分解进行音乐推荐. 数据处理 读取音乐数据集,统计数据指标,选择文本信 ...

  9. NLP自然语言处理系列-基于知识图谱的电影推荐实战

    NLP自然语言处理系列-基于知识图谱的电影推荐实战 kaggle数据集 https://www.kaggle.com/netflix-inc/netflix-prize-data?select=com ...

最新文章

  1. 项目总监批评程序员穿大裤衩上班情商低!程序员一气之下要离职!项目已到一半了,总监着急发帖求助!...
  2. python处理excel文件的模块_python处理Excel文件的几个模块
  3. Huffman(哈夫曼)编码--又称最佳编码(最有效的二进制编码)
  4. python unitest框架_python单元测试框架Unitest
  5. @description iPhoneX炫彩渐变背景实现
  6. 用友云开发者中心助你上云系列之在线调试
  7. STS创建Spring Boot项目实战(Rest接口、数据库、用户认证、分布式Token JWT、Redis操作、日志和统一异常处理)
  8. 携程专车入局:牌照在手,说走就走
  9. java怎么使用floor_Java NavigableSet floor()用法及代码示例
  10. final关键字多态
  11. IKVM.NET_第二篇_应用
  12. 自己动手写操作系统(三)
  13. win10安装双系统
  14. 【MIUI9】小米平板1MIPAD1欧版ROM历史ROM下载地址-另附挥泪典藏版V9系统
  15. 10年外贸人工具:邮件群发软件工具哪个好?
  16. html字母输出空格,如何在网页中插入html中文空格与英文空格
  17. mac小白的实用技巧
  18. 基于图像的火焰识别调研总结
  19. 天仙般的王祖贤和林青霞,她们都是用AI修复的
  20. 计算机职业生涯规划书素材,职业生涯规划书封面素材

热门文章

  1. 【游戏面包屑】图片自定义裁剪
  2. oracle数据库审计os,审计Oracle数据库的使用
  3. 2007中国软件开发者大型有奖调查
  4. 十进制转二进制(简单)
  5. 慕课网:Web前端面试题目及答案汇总
  6. mysql数据迁移到teradata_Teradata SQL Assistant工具导入与导出
  7. Ajax技术详解(一)
  8. Figma#2:工具
  9. Cortex-A8存储器管理
  10. kinect v2 移动电源配置