一个较为形象化的解释是:
机器不懂人类的自然语言,我们要将自然语言转换为机器易于理解的“语言”。转换成机器容易理解的语言就是说“机话”,变成一连串有阿拉伯数字构成的字符串,且这些字符串尽量保留原来人类语言的语义。举个例子,我们让机器理解一句话 --- “我们今天要去吃披萨”,进行转换后,可能出现部分的语义信息损失,比如机器会理解为“我们要去吃饭”,这在某些场合是可以接受的,但不能让机器理解为“我们要去打游戏”,这就离原始的语义信息偏离太远了。
正式开始前,设置日志,培养码代码的好习惯,打印程序运行中的细节,以便后面找到报错。
import logging
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
工作路径查询:
import tempfile
import os.path
TEMP_FOLDER = tempfile.gettempdir()
print('文件夹"{}" 将被用来存储语料和临时性的字典'.format(TEMP_FOLDER))
文件夹"C:\Users\hp\AppData\Local\Temp" 将被用来存储语料和临时性的字典
在上一篇文章《文本挖掘从小白到精通(二)---语料库和词向量空间》中,我们以向量流的形式创建了一个文档语料库。这次,笔者将继续使用该语料库:
from gensim import corpora, models, similarities
if os.path.isfile(os.path.join(TEMP_FOLDER, 'deerwester.dict')):
dictionary = corpora.Dictionary.load(os.path.join(TEMP_FOLDER, 'deerwester.dict'))
corpus = corpora.MmCorpus(os.path.join(TEMP_FOLDER, 'deerwester.mm'))
print("使用前面教程中产生的语料文件。")
else:
print("请运行前面的教程,以生成语料文件。")
2019-05-09 10:15:55,630 : INFO : 'pattern' package not found; tag filters are not available for English
2019-05-09 10:15:55,637 : INFO : loading Dictionary object from C:\Users\hp\AppData\Local\Temp\deerwester.dict
2019-05-09 10:15:55,642 : INFO : loaded C:\Users\hp\AppData\Local\Temp\deerwester.dict
2019-05-09 10:15:55,646 : INFO : loaded corpus index from C:\Users\hp\AppData\Local\Temp\deerwester.mm.index
2019-05-09 10:15:55,647 : INFO : initializing cython corpus reader from C:\Users\hp\AppData\Local\Temp\deerwester.mm2019-05-09 10:15:55,649 : INFO : accepted corpus with 12 documents, 12 features, 35 non-zero entries
使用前面教程中产生的语料文件。
前面教程的语料库由这些文档构成:
商业新知:知识图谱为内核,构建商业创新服务完整生态。
如何更好利用知识图谱技术做反欺诈? 360金融首席数据科学家沈赟开讲。
知识管理 | 基于知识图谱的国际知识管理领域可视化分析。
一文详解达观数据知识图谱技术与应用。
知识图谱技术落地金融行业的关键四步。
一文读懂知识图谱的商业应用进程及技术背景。
海云数据CPO王斌:打造大数据可视分析与AI应用的高科技企业。
智能产业|《人工智能标准化白皮书2018》带来创新创业新技术标准。
国家语委重大科研项目“中华经典诗词知识图谱构建技术研究”开题。
最全知识图谱介绍:关键技术、开放数据集、应用案例汇总
中译语通Jove Mind知识图谱平台 引领企业智能化发展。
知识图谱:知识图谱赋能企业数字化转型,为企业升级转型注入新能量。
查看保存字典(Dictionary)中的前3个词汇:
print(dictionary[0])
print(dictionary[1])
print(dictionary[2])
创新
商业
知识图谱
准备工作做好了,下面要进入正题了,笔者将重点展示如何将文档从一个向量表示(Vector Representation )是转换为另一个向量表示。 在此过程中,会涉及到两个目标:
挖掘语料库中潜藏的结构,发现词汇之间的关联性。前一篇文章中提到的词袋模型/表示,并不能很好的挖掘语料中的词序特征(语句中词汇的先后顺序)和语义特征(上下文、词性搭配等),进行文本数据转换后则可以一种更加反映语义相关性的方式来表征文档,以提高后续文本聚类、文本分类等高阶文本挖掘应用的效果。
使文档表示更紧凑。 这既提高了效率(新的文档表示会消耗更少的计算资源,转换过程会更快),也提升了效果(边际数据的趋势被忽略,也就是语料中的超低频和超高频词汇对语料的影响被削弱,从而达到数据降噪的目的,更能抓住文本中的重要特征)。
下面进入实际的代码操作:
TF-IDF模型用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度,它是一个标准的Python对象,可通过对语料库训练进行初始化。
step 1 -- 初始化模型:
tfidf = models.TfidfModel(corpus)
2019-05-09 10:16:04,390 : INFO : collecting document frequencies
2019-05-09 10:16:04,393 : INFO : PROGRESS: processing document #0
2019-05-09 10:16:04,395 : INFO : calculating IDF weights for 12 documents and 11 features (35 matrix non-zeros)
通过打印出的日志可以看到,该TF-IDF转换模型在这12个经词袋表示的文档中抽取出了11个特征。
值得注意的是,不同的转换可能需要不同的初始化参数 --- 在TF-IDF的情境下,“训练”仅包括通过一次性提供语料库并计算其所有特征的文档频率,模型不需要额外设置参数。训练其他文本转换模型,比如潜在语义分析模型(Latent Semantic Analysis,LSI)或隐含狄利克雷分布模型(Latent Dirichlet Allocation),可能复杂很多,会涉及更多的参数设置,同时也需要更多的时间进行训练。
注意:
(文本数据)转换总是在两个特定的向量空间(Two Specific Vector Spaces)之间进行。必须使用相同的向量空间(即同一组特征id)进行模型训练和后续的向量转换。如果不能使用相同的输入特征空间(Input Feature Space),例如使用不同的字符串进行预处理,或者使用不同的特征ID,抑或本应使用TF-IDF向量却采用词袋表示来输入向量,这些“误操作”将产生转换期间的特征不匹配,进而导致错误的运行结果或产生异常。
step 2 -- 使用模型对词袋表示向量进行转换:
doc_bow = [(0, 3), (1, 5)]
print(tfidf[doc_bow])
[(0, 0.5144957554275265), (1, 0.8574929257125441)]
或者,直接对整个(训练)语料库进行特征转换:
corpus_tfidf = tfidf[corpus]
for doc in corpus_tfidf:
print(doc)
[(0, 0.4467512594633994), (1, 0.8935025189267988), (2, 0.045459441696222264)]
[(2, 0.07982263066186342), (3, 0.38329103210095783), (4, 0.48098603643475885), (5, 0.7844544378738532)]
[(2, 0.025128868703899597), (6, 0.24695318119778994), (7, 0.6849754251993109), (8, 0.6849754251993109)]
[(2, 0.07982263066186342), (3, 0.38329103210095783), (4, 0.48098603643475885), (9, 0.7844544378738532)]
[(2, 0.0910460341905888), (3, 0.43718339178067905), (5, 0.8947520894690928)]
[(1, 0.6668011702142979), (2, 0.06785075201967737), (3, 0.32580465658435587), (9, 0.6668011702142979)]
[(4, 0.6962169034343767), (6, 0.5677404313752555), (10, 0.4392639593161345)]
[(0, 1.0)]
[(2, 0.20388162893651843), (3, 0.9789955471717897)]
[(2, 0.16371704169295062), (4, 0.9865073391816752)]
[(2, 0.13039433685974838), (10, 0.9914622115415728)][(2, 0.06394369208554566), (10, 0.4862002131078655), (11, 0.8715047659171663)]
可以看到,每个转换后的语句中,单个词汇的表示由整数型数值的词汇计数转变成了浮点型的词汇权重。该权重表示字词对于该语句的重要性程度,数值越大,则重要性程度越高,反之越小,对于其原理,可以进行如此直觉性的理解:
字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。
比如,示例语料库中的第一句话 --- '商业新知:知识图谱为内核,构建商业创新服务完整生态。',它原先可由词袋模型表征为
[(0, 1), (1, 2), (2, 1)]
经过TF-IDF转换模型转换后则变为:
[(0, 0.4467512594633994), (1, 0.8935025189267988), (2, 0.045459441696222264)]
请注意,这里0,1,2在字典中分别对应‘创新'、'商业'、'知识图谱' 这3个词汇,根据这3个词的权重大小可知,对于这句话,最重要(最能代表这句话含义)的词汇是“商业”,其次是“创新”,最次是“知识图谱”。这很符合直觉:这12句话中都包含“知识图谱”,因此该词对各个文档/语句的代表性很弱。
此外,因为是示例数据,我们用这12个文档训练出TF-IDF模型后,又用这训练出来的模型对这12个文档的词袋表示进行转换。但在实际应用中,该模型可以对训练语料之外的语料/语句进行转换。当然,用于转换的语料/语句中的若干词汇不在模型的词汇表中,那么该语料/语句的部分信息会缺失。所以说,实际任务中,训练语料能大则大,绝对是“大力出奇迹”!
注意:
调用
model[corpus]
在已有的语料库文档流上创建一个包装器(Wrapper) --- 实际的文本数据转换在文档迭代期间即时完成(Done on-the-Fly)。我们无法在调用corpus_transformed = model [corpus]
时转换整个语料库 --- 因为这意味着结果将会存储在本地内存中,这与gensim的内存独立(Memory-Independence)的目标相悖。如果你将多次迭代待转换的corpus_transformed,且转换代价较高,请先将生成的语料库序列化(Serialize)到本地,以便后续使用。
转换后的结果也可以序列化,它将一层层嵌套。
step 3 --- 基于前面的特征,进行LSI模型构建
lsi = models.LsiModel(corpus_tfidf, id2word=dictionary, num_topics=3) # 初始化 LSI 转换
corpus_lsi = lsi[corpus_tfidf] #在原始语料词袋表示的基础上创建一个双包装器(Double Wrapper):bow-> tfidf-> lsi
2019-05-09 10:16:29,942 : INFO : using serial LSI version on this node
2019-05-09 10:16:29,947 : INFO : updating model with new documents
2019-05-09 10:16:29,950 : INFO : preparing a new chunk of documents
2019-05-09 10:16:29,951 : INFO : using 100 extra samples and 2 power iterations
2019-05-09 10:16:29,951 : INFO : 1st phase: constructing (12, 103) action matrix
2019-05-09 10:16:29,989 : INFO : orthonormalizing (12, 103) action matrix
2019-05-09 10:16:30,045 : INFO : 2nd phase: running dense svd on (12, 12) matrix
2019-05-09 10:16:30,061 : INFO : computing the final decomposition
2019-05-09 10:16:30,061 : INFO : keeping 3 factors (discarding 45.442% of energy spectrum)
2019-05-09 10:16:30,171 : INFO : processed documents up to #12
2019-05-09 10:16:30,175 : INFO : topic #0(1.715): -0.590*"数据" + -0.540*"技术" + -0.406*"金融" + -0.316*"一文" + -0.169*"商业" + -0.163*"企业" + -0.160*"知识图谱" + -0.109*"分析" + -0.041*"创新" + -0.036*"转型"
2019-05-09 10:16:30,176 : INFO : topic #1(1.382): 0.565*"企业" + 0.449*"数据" + -0.385*"商业" + -0.351*"技术" + 0.217*"分析" + -0.216*"创新" + -0.215*"一文" + 0.208*"转型" + -0.146*"金融" + 0.038*"管理"
2019-05-09 10:16:30,178 : INFO : topic #2(1.302): 0.580*"商业" + 0.468*"创新" + -0.444*"金融" + 0.330*"企业" + 0.264*"一文" + -0.198*"技术" + 0.150*"转型" + 0.075*"分析" + 0.026*"数据" + 0.018*"知识图谱"
在这里,我们通过潜在语义索引(Latent Semantic Indexing)(http://en.wikipedia.org/wiki/Latent_semantic_indexing) 将前面转换得到的TF-IDF语料库转换到潜在的3-D空间(3-D因为笔者在这里设置了num_topics = 3)。现在你可能想知道:这3个潜在的维度代表什么?让我们用models.LsiModel.show_topics()
一探究竟:
lsi.show_topics()
[(0,
'-0.590*"数据" + -0.540*"技术" + -0.406*"金融" + -0.316*"一文" + -0.169*"商业" + -0.163*"企业" + -0.160*"知识图谱" + -0.109*"分析" + -0.041*"创新" + -0.036*"转型"'),
(1,
'0.565*"企业" + 0.449*"数据" + -0.385*"商业" + -0.351*"技术" + 0.217*"分析" + -0.216*"创新" + -0.215*"一文" + 0.208*"转型" + -0.146*"金融" + 0.038*"管理"'),
(2,
'0.580*"商业" + 0.468*"创新" + -0.444*"金融" + 0.330*"企业" + 0.264*"一文" + -0.198*"技术" + 0.150*"转型" + 0.075*"分析" + 0.026*"数据" + 0.018*"知识图谱"')]
再看看语料库中的文档,并给每个文档加上序号,便于索引。根据上述主题及主题词构成,即可发现文档的主题归属:
1 商业新知:知识图谱为内核,构建商业创新服务完整生态。
2 如何更好利用知识图谱技术做反欺诈? 360金融首席数据科学家沈赟开讲。
3 知识管理 | 基于知识图谱的国际知识管理领域可视化分析。
4 一文详解达观数据知识图谱技术与应用。
5 知识图谱技术落地金融行业的关键四步。
6 一文读懂知识图谱的商业应用进程及技术背景。
7 海云数据CPO王斌:打造大数据可视分析与AI应用的高科技企业。
8 智能产业|《人工智能标准化白皮书2018》带来创新创业新技术标准。
9 国家语委重大科研项目“中华经典诗词知识图谱构建技术研究”开题。
10 最全知识图谱介绍:关键技术、开放数据集、应用案例汇总
11 中译语通Jove Mind知识图谱平台 引领企业智能化发展。
12 知识图谱:知识图谱赋能企业数字化转型,为企业升级转型注入新能量。
因为我们的语料库较小,方便起见,仅查看每个主题的前3个最具代表性的主题词。
根据LSI的原理可知,“数据”、“技术”和“金融”都是相关词(并且对第一个主题的方向贡献最大),可大体推测该主题跟数据技术在金融领域的应用有关,那么,文档2、5跟该主题的相关性最大;根据第二个主题的TOP3主题词(“企业”、“数据”、“商业”)可知,该主题主要谈论企业将数据应用于商业实践,那么,文档1、6、7、10、12跟该主题的相关性最大;以此类推,第三个主题讨论的主要是(借助数据技术)在商业领域的创新,尤其是金融方面的,那么,文档1、8跟该主题相关性最大。由于LSI、LDA等主题模型在本质上属于软聚类(Soft Clustering),也就是说,每个主题上的概率就是文章对于这个主题的隶属度,同一个文档可能夹杂着多个主题,只是对应的各个主题的概率不同罢了。 上述文档对应的主题应该是混合的,每个主题的概率大小不尽相同,在实际应用中,我们一般找出其中概率最大的一个主题。
for doc in corpus_lsi: # bow->tfidf转换 和 tfidf->lsi转换实际上是在这里即时完成的
print(doc)
[(0, -0.17690867499072602), (1, -0.44016836447597885), (2, 0.7284335174782008)]
[(0, -0.821902042820486), (1, -0.03184788440523527), (2, -0.4098203903108002)]
[(0, -0.045384645077792767), (1, 0.10578780781807381), (2, 0.042559710380774426)]
[(0, -0.7515191768805072), (1, -0.08599404650088843), (2, 0.1452967034805242)]
[(0, -0.6136428537043512), (1, -0.28286688523868675), (2, -0.4818653950021932)]
[(0, -0.5104995586789475), (1, -0.5136313252286587), (2, 0.49976771121730945)]
[(0, -0.5441363960445108), (1, 0.6841975713452622), (2, 0.20580754225199666)]
[(0, -0.040719186823048786), (1, -0.21597858129605113), (2, 0.46786434413537753)]
[(0, -0.5608211518743773), (1, -0.3417930476335039), (2, -0.18966593031566448)]
[(0, -0.6084914634082519), (1, 0.44488378344921975), (2, 0.028910120373434968)]
[(0, -0.18200362025117117), (1, 0.5612899057224641), (2, 0.32933606191854775)][(0, -0.12032756763512721), (1, 0.4568857150530911), (2, 0.2925478388144471)]
TF-IDF和LDA等模型也可以用先前的方法进行本地化存储:
lsi.save(os.path.join(TEMP_FOLDER, 'model.lsi'))
lsi = models.LsiModel.load(os.path.join(TEMP_FOLDER, 'model.lsi'))
2019-05-09 10:16:46,340 : INFO : saving Projection object under C:\Users\hp\AppData\Local\Temp\model.lsi.projection, separately None
2019-05-09 10:16:46,345 : INFO : saved C:\Users\hp\AppData\Local\Temp\model.lsi.projection
2019-05-09 10:16:46,347 : INFO : saving LsiModel object under C:\Users\hp\AppData\Local\Temp\model.lsi, separately None
2019-05-09 10:16:46,348 : INFO : not storing attribute projection
2019-05-09 10:16:46,349 : INFO : not storing attribute dispatcher
2019-05-09 10:16:46,351 : INFO : saved C:\Users\hp\AppData\Local\Temp\model.lsi
2019-05-09 10:16:46,353 : INFO : loading LsiModel object from C:\Users\hp\AppData\Local\Temp\model.lsi
2019-05-09 10:16:46,356 : INFO : loading id2word recursively from C:\Users\hp\AppData\Local\Temp\model.lsi.id2word.* with mmap=None
2019-05-09 10:16:46,357 : INFO : setting ignored attribute projection to None
2019-05-09 10:16:46,360 : INFO : setting ignored attribute dispatcher to None
2019-05-09 10:16:46,361 : INFO : loaded C:\Users\hp\AppData\Local\Temp\model.lsi
2019-05-09 10:16:46,364 : INFO : loading LsiModel object from C:\Users\hp\AppData\Local\Temp\model.lsi.projection
2019-05-09 10:16:46,366 : INFO : loaded C:\Users\hp\AppData\Local\Temp\model.lsi.projection
看到这里,你可能会问:这些文档之间的相似度怎样?
如何利用LSI产生的文本特征,对给定文档的输入文档(不在模型的训练语料库中),根据文档间的语义相似性对检索结果进行相似度降序排列,并从中找到和输入文档最为相似的文档?
不要着急,笔者将会下面的文章中介绍基于LSI模型文档相似性查询(Similarity Queries Based LSI)。此外,除了用于文档检索任务外,基于LSI模型(LSA和LDA也是一样)提取的文本特征可用于文本分类和文本聚类任务
最后,笔者在梳理下目前比较流行的文本转换模型,它们都可以用gensim的接口实现。
gensim这个库中,有几种常见的词向量空间算法(Vector Space Model Algorithms),下面且听笔者娓娓道来:
TF-IDF模型需要一个基于词袋表示(Bag-of-Words Representation)的训练语料库来进行初始化。在数据转换期间,它采用向量作为输入并返回另一个具有相同维度的向量,只有在训练语料库中出现较少的特征(出现越少对文档的代表性就越强)才能增加该数值。因此,TF-IDF模型将整型向量转换为实值向量(比如[(1,2),(0,10),(4,2),(5,1)]转换为[(1,0.002),(0,0.121),(4,0.0401),(5,0.5241)]),且保持维度的数量不变。值得注意的是,该模型返回的结果还可以将得到的向量归一化为(欧几里得)单位长度,使(词汇权重)值介于0到1之间。
model = models.TfidfModel(corpus, normalize=True)
LSI将文档从词袋表示(Bag-of-Words Representation,优先选择词袋表示,经大量实验,这样得到的效果较好)或者TF-IDF加权空间转换为较低维度的潜在向量空间。对于上面的示例语料库,我们只使用了3个潜在维度(Latent Dimensions),但在实际语料库处理中,建议将200-500的目标维度作为“黄金标准”[详情见参考资料1]。
model = models.LsiModel(corpus_tfidf, id2word=dictionary, num_topics=6)
2019-05-09 10:16:51,102 : INFO : using serial LSI version on this node
2019-05-09 10:16:51,103 : INFO : updating model with new documents
2019-05-09 10:16:51,105 : INFO : preparing a new chunk of documents
2019-05-09 10:16:51,107 : INFO : using 100 extra samples and 2 power iterations
2019-05-09 10:16:51,108 : INFO : 1st phase: constructing (12, 106) action matrix
2019-05-09 10:16:51,108 : INFO : orthonormalizing (12, 106) action matrix
2019-05-09 10:16:51,110 : INFO : 2nd phase: running dense svd on (12, 12) matrix
2019-05-09 10:16:51,111 : INFO : computing the final decomposition
2019-05-09 10:16:51,112 : INFO : keeping 6 factors (discarding 15.684% of energy spectrum)
2019-05-09 10:16:51,113 : INFO : processed documents up to #12
2019-05-09 10:16:51,115 : INFO : topic #0(1.715): 0.590*"数据" + 0.540*"技术" + 0.406*"金融" + 0.316*"一文" + 0.169*"商业" + 0.163*"企业" + 0.160*"知识图谱" + 0.109*"分析" + 0.041*"创新" + 0.036*"转型"
2019-05-09 10:16:51,116 : INFO : topic #1(1.382): -0.565*"企业" + -0.449*"数据" + 0.385*"商业" + 0.351*"技术" + -0.217*"分析" + 0.216*"创新" + 0.215*"一文" + -0.208*"转型" + 0.146*"金融" + -0.038*"知识"
2019-05-09 10:16:51,118 : INFO : topic #2(1.302): 0.580*"商业" + 0.468*"创新" + -0.444*"金融" + 0.330*"企业" + 0.264*"一文" + -0.198*"技术" + 0.150*"转型" + 0.075*"分析" + 0.026*"数据" + 0.018*"知识图谱"
2019-05-09 10:16:51,121 : INFO : topic #3(1.173): 0.561*"数据" + -0.553*"企业" + -0.386*"转型" + -0.326*"金融" + -0.272*"技术" + 0.179*"一文" + 0.095*"分析" + -0.073*"知识图谱" + -0.040*"创新" + 0.034*"知识"
2019-05-09 10:16:51,123 : INFO : topic #4(1.090): 0.685*"创新" + -0.499*"一文" + 0.421*"金融" + -0.221*"技术" + 0.163*"数据" + -0.097*"转型" + -0.095*"企业" + 0.069*"分析" + 0.045*"知识" + 0.045*"管理"
将模型训练得出的主题展示出来:
model.print_topics()
2019-05-09 10:16:53,259 : INFO : topic #0(1.715): 0.590*"数据" + 0.540*"技术" + 0.406*"金融" + 0.316*"一文" + 0.169*"商业" + 0.163*"企业" + 0.160*"知识图谱" + 0.109*"分析" + 0.041*"创新" + 0.036*"转型"
2019-05-09 10:16:53,261 : INFO : topic #1(1.382): -0.565*"企业" + -0.449*"数据" + 0.385*"商业" + 0.351*"技术" + -0.217*"分析" + 0.216*"创新" + 0.215*"一文" + -0.208*"转型" + 0.146*"金融" + -0.038*"知识"
2019-05-09 10:16:53,263 : INFO : topic #2(1.302): 0.580*"商业" + 0.468*"创新" + -0.444*"金融" + 0.330*"企业" + 0.264*"一文" + -0.198*"技术" + 0.150*"转型" + 0.075*"分析" + 0.026*"数据" + 0.018*"知识图谱"
2019-05-09 10:16:53,264 : INFO : topic #3(1.173): 0.561*"数据" + -0.553*"企业" + -0.386*"转型" + -0.326*"金融" + -0.272*"技术" + 0.179*"一文" + 0.095*"分析" + -0.073*"知识图谱" + -0.040*"创新" + 0.034*"知识"
2019-05-09 10:16:53,266 : INFO : topic #4(1.090): 0.685*"创新" + -0.499*"一文" + 0.421*"金融" + -0.221*"技术" + 0.163*"数据" + -0.097*"转型" + -0.095*"企业" + 0.069*"分析" + 0.045*"知识" + 0.045*"管理"
2019-05-09 10:16:53,267 : INFO : topic #5(1.003): -0.670*"知识" + -0.670*"管理" + -0.265*"分析" + 0.141*"数据" + -0.074*"技术" + 0.063*"创新" + 0.037*"转型" + -0.030*"商业" + 0.023*"企业" + -0.012*"知识图谱"
[(0,
'0.590*"数据" + 0.540*"技术" + 0.406*"金融" + 0.316*"一文" + 0.169*"商业" + 0.163*"企业" + 0.160*"知识图谱" + 0.109*"分析" + 0.041*"创新" + 0.036*"转型"'),
(1,
'-0.565*"企业" + -0.449*"数据" + 0.385*"商业" + 0.351*"技术" + -0.217*"分析" + 0.216*"创新" + 0.215*"一文" + -0.208*"转型" + 0.146*"金融" + -0.038*"知识"'),
(2,
'0.580*"商业" + 0.468*"创新" + -0.444*"金融" + 0.330*"企业" + 0.264*"一文" + -0.198*"技术" + 0.150*"转型" + 0.075*"分析" + 0.026*"数据" + 0.018*"知识图谱"'),
(3,
'0.561*"数据" + -0.553*"企业" + -0.386*"转型" + -0.326*"金融" + -0.272*"技术" + 0.179*"一文" + 0.095*"分析" + -0.073*"知识图谱" + -0.040*"创新" + 0.034*"知识"'),
(4,
'0.685*"创新" + -0.499*"一文" + 0.421*"金融" + -0.221*"技术" + 0.163*"数据" + -0.097*"转型" + -0.095*"企业" + 0.069*"分析" + 0.045*"知识" + 0.045*"管理"'),
(5,
'-0.670*"知识" + -0.670*"管理" + -0.265*"分析" + 0.141*"数据" + -0.074*"技术" + 0.063*"创新" + 0.037*"转型" + -0.030*"商业" + 0.023*"企业" + -0.012*"知识图谱"')]
LSI模型训练的独特之处在于:我们可以在任何时间对模型进行再次训练
,只需提供更多用于训练的语料。它通过一种称为在线训练/学习
或
增量训练/学习
(Online Training/Online Learning或者Incremental Training/Incremental Learning)
的过程来完成,该过程对底层模型(Underlying Model)进行增量更新。由于这个特性,输入的文档流(Document Stream)甚至可能是无穷无尽的 --- 只要在LSI模型需要语料时再喂进新文档,对训练模型保持持续性的新文档输入。
增量学习的使用方法说明:
model.add_documents(another_tfidf_corpus) # 现在LSI模型已经在tfidf_corpus + 另一个tfidf_corpus上进行训练了
lsi_vec = model[tfidf_vec] # 将一个新文档转换到LSI空间,但不影响模型
model.add_documents(more_documents) # tfidf_corpus + another_tfidf_corpus + 更多的文档 lsi_vec = model[tfidf_vec]
详情请参阅gensim.models.lsimodel
的接口文档,了解如何使LSI逐渐“忘记”源源不断的文档流中的陈旧信息。调节该接口中的一些参数可能会影响运行的速度、内存的使用率以及LSI算法的数值精度。
gensim在很多模型上使用了一种新颖的在线增量流分布式训练算法(Online Incremental Streamed Distributed Training Algorithm,相当拗口的说辞!),如果想了解该算法的细节,请参看结尾[参考资料5]中的论文。
RP算法旨在减少向量空间的维度。这是一种非常有效的(对内存和CPU友好)方法,通过加入一点随机性来近似表示文档之间的TF-IDF距离。比较推荐的目标维度最好是几百/几千,具体数值取决于语料库的大小。
model = models.RpModel(corpus_tfidf, num_topics=3)
2019-05-09 10:16:56,243 : INFO : no word id mapping provided; initializing from corpus, assuming identity
2019-05-09 10:16:56,248 : INFO : constructing (3, 12) random matrix
model.num_topics #主题数有多少?
3
model.num_terms #主题模型中参与训练的词汇数有多少?
12
LDA是另一种从词袋表示转变为低维度主题空间的文本数据转换模型。LDA是LSA(也称为多项PCA)的概率扩展(Probabilistic Extension),因此LDA的主题可以解释为词汇的概率分布。与LSA一样,这些分布也是从训练语料库中自动推断出来的,不需要人为介入。文档又被解释为这些主题的(软)混合,这跟LSI和LSA一样。
model = models.LdaModel(corpus, id2word=dictionary, num_topics=3)
2019-05-09 10:17:01,014 : INFO : using symmetric alpha at 0.3333333333333333
2019-05-09 10:17:01,017 : INFO : using symmetric eta at 0.3333333333333333
2019-05-09 10:17:01,018 : INFO : using serial LDA version on this node
2019-05-09 10:17:01,020 : INFO : running online (single-pass) LDA training, 3 topics, 1 passes over the supplied corpus of 12 documents, updating model once every 12 documents, evaluating perplexity every 12 documents, iterating 50x with a convergence threshold of 0.001000
2019-05-09 10:17:01,021 : WARNING : too few updates, training might not converge; consider increasing the number of passes or iterations to improve accuracy
2019-05-09 10:17:01,112 : INFO : -3.650 per-word bound, 12.6 perplexity estimate based on a held-out corpus of 12 documents with 42 words
2019-05-09 10:17:01,113 : INFO : PROGRESS: pass 0, at document #12/12
2019-05-09 10:17:01,124 : INFO : topic #0 (0.333): 0.189*"技术" + 0.187*"知识图谱" + 0.167*"一文" + 0.104*"数据" + 0.098*"商业" + 0.075*"创新" + 0.039*"金融" + 0.033*"企业" + 0.027*"分析" + 0.027*"知识"
2019-05-09 10:17:01,125 : INFO : topic #1 (0.333): 0.281*"知识图谱" + 0.101*"企业" + 0.094*"技术" + 0.072*"转型" + 0.072*"管理" + 0.072*"知识" + 0.071*"商业" + 0.070*"数据" + 0.066*"金融" + 0.048*"创新"
2019-05-09 10:17:01,127 : INFO : topic #2 (0.333): 0.271*"数据" + 0.154*"企业" + 0.148*"分析" + 0.064*"知识图谱" + 0.054*"创新" + 0.052*"技术" + 0.047*"商业" + 0.044*"一文" + 0.043*"金融" + 0.041*"知识"
2019-05-09 10:17:01,128 : INFO : topic diff=1.179380, rho=1.000000
展示主题模型中的各个主体及其主题词分布情况:
model.show_topics()
[(0,
'0.189*"技术" + 0.187*"知识图谱" + 0.167*"一文" + 0.104*"数据" + 0.098*"商业" + 0.075*"创新" + 0.039*"金融" + 0.033*"企业" + 0.027*"分析" + 0.027*"知识"'),
(1,
'0.281*"知识图谱" + 0.101*"企业" + 0.094*"技术" + 0.072*"转型" + 0.072*"管理" + 0.072*"知识" + 0.071*"商业" + 0.070*"数据" + 0.066*"金融" + 0.048*"创新"'),
(2,
'0.271*"数据" + 0.154*"企业" + 0.148*"分析" + 0.064*"知识图谱" + 0.054*"创新" + 0.052*"技术" + 0.047*"商业" + 0.044*"一文" + 0.043*"金融" + 0.041*"知识"')]
gensim这个库采用一种叫做在线学习(Online Learning)的策略实现,运行速度较快,它还可以以分布式模式(Distributed Mode)在计算机集群上运行,详情请参看参考文献[2]。
HDP是一种非参数贝叶斯方法(跟其他的主题模型不同,它不需要事先确定主题的数量),它对于想偷懒的同学来说,简直是福音!以下是它的接口调用方法:
model = models.HdpModel(corpus, id2word=dictionary)
2019-05-09 10:17:05,932 : INFO : (0, '0.229*转型 + 0.181*管理 + 0.172*一文 + 0.107*知识 + 0.088*商业 + 0.085*知识图谱 + 0.052*技术 + 0.028*企业 + 0.026*分析 + 0.023*创新')
2019-05-09 10:17:05,936 : INFO : (1, '0.294*创新 + 0.158*转型 + 0.139*知识图谱 + 0.088*知识 + 0.075*金融 + 0.074*管理 + 0.060*商业 + 0.055*数据 + 0.037*一文 + 0.012*技术')
2019-05-09 10:17:05,938 : INFO : (2, '0.381*金融 + 0.140*知识 + 0.129*创新 + 0.103*技术 + 0.093*企业 + 0.050*数据 + 0.034*商业 + 0.031*分析 + 0.024*转型 + 0.006*一文')
2019-05-09 10:17:05,939 : INFO : (3, '0.239*知识 + 0.234*分析 + 0.180*金融 + 0.086*数据 + 0.084*创新 + 0.069*一文 + 0.041*知识图谱 + 0.038*转型 + 0.025*管理 + 0.002*商业')
2019-05-09 10:17:05,941 : INFO : (4, '0.250*转型 + 0.199*管理 + 0.167*技术 + 0.145*企业 + 0.069*商业 + 0.054*一文 + 0.042*知识图谱 + 0.021*创新 + 0.020*金融 + 0.018*数据')
2019-05-09 10:17:05,943 : INFO : (5, '0.205*技术 + 0.166*企业 + 0.124*商业 + 0.118*转型 + 0.107*数据 + 0.069*金融 + 0.068*创新 + 0.046*管理 + 0.034*一文 + 0.027*分析')
2019-05-09 10:17:05,944 : INFO : (6, '0.250*企业 + 0.163*金融 + 0.113*创新 + 0.099*知识 + 0.090*数据 + 0.057*转型 + 0.055*一文 + 0.044*商业 + 0.043*分析 + 0.043*管理')
2019-05-09 10:17:05,948 : INFO : (7, '0.311*一文 + 0.247*创新 + 0.129*金融 + 0.078*知识 + 0.073*商业 + 0.058*数据 + 0.038*技术 + 0.022*分析 + 0.015*管理 + 0.013*转型')
2019-05-09 10:17:05,949 : INFO : (8, '0.156*知识图谱 + 0.144*创新 + 0.142*转型 + 0.102*金融 + 0.089*商业 + 0.071*数据 + 0.059*知识 + 0.057*管理 + 0.056*企业 + 0.050*分析')
2019-05-09 10:17:05,951 : INFO : (9, '0.215*创新 + 0.191*技术 + 0.178*分析 + 0.094*知识 + 0.070*管理 + 0.063*企业 + 0.051*商业 + 0.038*金融 + 0.034*知识图谱 + 0.029*数据')
2019-05-09 10:17:05,952 : INFO : (10, '0.346*一文 + 0.164*商业 + 0.150*管理 + 0.110*分析 + 0.090*知识图谱 + 0.042*企业 + 0.033*数据 + 0.022*创新 + 0.022*技术 + 0.011*金融')
2019-05-09 10:17:05,953 : INFO : (11, '0.216*金融 + 0.165*商业 + 0.140*分析 + 0.082*知识图谱 + 0.079*转型 + 0.074*知识 + 0.068*数据 + 0.059*企业 + 0.042*创新 + 0.035*一文')
2019-05-09 10:17:05,955 : INFO : (12, '0.397*转型 + 0.120*创新 + 0.110*技术 + 0.101*分析 + 0.069*金融 + 0.057*商业 + 0.050*知识 + 0.028*知识图谱 + 0.025*一文 + 0.023*企业')
2019-05-09 10:17:05,956 : INFO : (13, '0.299*分析 + 0.274*一文 + 0.121*数据 + 0.087*创新 + 0.061*金融 + 0.059*企业 + 0.043*知识图谱 + 0.014*知识 + 0.014*管理 + 0.012*商业')
2019-05-09 10:17:05,958 : INFO : (14, '0.185*商业 + 0.144*创新 + 0.108*转型 + 0.100*管理 + 0.098*一文 + 0.092*分析 + 0.072*数据 + 0.060*金融 + 0.053*企业 + 0.036*技术')
2019-05-09 10:17:05,958 : INFO : (15, '0.235*转型 + 0.163*商业 + 0.140*企业 + 0.102*技术 + 0.074*数据 + 0.072*分析 + 0.067*管理 + 0.046*知识 + 0.039*一文 + 0.027*知识图谱')
2019-05-09 10:17:05,959 : INFO : (16, '0.165*商业 + 0.164*管理 + 0.159*分析 + 0.126*数据 + 0.109*创新 + 0.079*企业 + 0.066*知识图谱 + 0.041*技术 + 0.038*知识 + 0.029*一文')
2019-05-09 10:17:05,961 : INFO : (17, '0.204*管理 + 0.193*知识图谱 + 0.166*一文 + 0.163*转型 + 0.088*创新 + 0.048*知识 + 0.045*金融 + 0.038*商业 + 0.020*企业 + 0.016*数据')
2019-05-09 10:17:05,962 : INFO : (18, '0.225*企业 + 0.136*金融 + 0.136*技术 + 0.099*知识 + 0.098*商业 + 0.095*一文 + 0.078*创新 + 0.076*管理 + 0.034*知识图谱 + 0.019*分析')2019-05-09 10:17:05,963 : INFO : (19, '0.232*企业 + 0.205*一文 + 0.121*技术 + 0.089*金融 + 0.076*数据 + 0.076*创新 + 0.075*转型 + 0.069*商业 + 0.017*管理 + 0.016*分析')
model.num_topics # 该模型自动生成 主题数有多少?
20
展示HDP主题模型中的各个主题及其主题词分布情况:
model.show_topics() #
[(0,
'0.229*转型 + 0.181*管理 + 0.172*一文 + 0.107*知识 + 0.088*商业 + 0.085*知识图谱 + 0.052*技术 + 0.028*企业 + 0.026*分析 + 0.023*创新 + 0.008*数据 + 0.000*金融'),
(1,
'0.294*创新 + 0.158*转型 + 0.139*知识图谱 + 0.088*知识 + 0.075*金融 + 0.074*管理 + 0.060*商业 + 0.055*数据 + 0.037*一文 + 0.012*技术 + 0.004*企业 + 0.004*分析'),
(2,
'0.381*金融 + 0.140*知识 + 0.129*创新 + 0.103*技术 + 0.093*企业 + 0.050*数据 + 0.034*商业 + 0.031*分析 + 0.024*转型 + 0.006*一文 + 0.005*知识图谱 + 0.004*管理'),
(3,
'0.239*知识 + 0.234*分析 + 0.180*金融 + 0.086*数据 + 0.084*创新 + 0.069*一文 + 0.041*知识图谱 + 0.038*转型 + 0.025*管理 + 0.002*商业 + 0.001*技术 + 0.001*企业'),
(4,
'0.250*转型 + 0.199*管理 + 0.167*技术 + 0.145*企业 + 0.069*商业 + 0.054*一文 + 0.042*知识图谱 + 0.021*创新 + 0.020*金融 + 0.018*数据 + 0.013*分析 + 0.003*知识'),
(5,
'0.205*技术 + 0.166*企业 + 0.124*商业 + 0.118*转型 + 0.107*数据 + 0.069*金融 + 0.068*创新 + 0.046*管理 + 0.034*一文 + 0.027*分析 + 0.019*知识图谱 + 0.017*知识'),
(6,
'0.250*企业 + 0.163*金融 + 0.113*创新 + 0.099*知识 + 0.090*数据 + 0.057*转型 + 0.055*一文 + 0.044*商业 + 0.043*分析 + 0.043*管理 + 0.039*知识图谱 + 0.004*技术'),
(7,
'0.311*一文 + 0.247*创新 + 0.129*金融 + 0.078*知识 + 0.073*商业 + 0.058*数据 + 0.038*技术 + 0.022*分析 + 0.015*管理 + 0.013*转型 + 0.010*知识图谱 + 0.006*企业'),
(8,
'0.156*知识图谱 + 0.144*创新 + 0.142*转型 + 0.102*金融 + 0.089*商业 + 0.071*数据 + 0.059*知识 + 0.057*管理 + 0.056*企业 + 0.050*分析 + 0.038*技术 + 0.037*一文'),
(9,
'0.215*创新 + 0.191*技术 + 0.178*分析 + 0.094*知识 + 0.070*管理 + 0.063*企业 + 0.051*商业 + 0.038*金融 + 0.034*知识图谱 + 0.029*数据 + 0.019*一文 + 0.017*转型'),
(10,
'0.346*一文 + 0.164*商业 + 0.150*管理 + 0.110*分析 + 0.090*知识图谱 + 0.042*企业 + 0.033*数据 + 0.022*创新 + 0.022*技术 + 0.011*金融 + 0.007*知识 + 0.002*转型'),
(11,
'0.216*金融 + 0.165*商业 + 0.140*分析 + 0.082*知识图谱 + 0.079*转型 + 0.074*知识 + 0.068*数据 + 0.059*企业 + 0.042*创新 + 0.035*一文 + 0.032*管理 + 0.009*技术'),
(12,
'0.397*转型 + 0.120*创新 + 0.110*技术 + 0.101*分析 + 0.069*金融 + 0.057*商业 + 0.050*知识 + 0.028*知识图谱 + 0.025*一文 + 0.023*企业 + 0.019*数据 + 0.001*管理'),
(13,
'0.299*分析 + 0.274*一文 + 0.121*数据 + 0.087*创新 + 0.061*金融 + 0.059*企业 + 0.043*知识图谱 + 0.014*知识 + 0.014*管理 + 0.012*商业 + 0.009*转型 + 0.009*技术'),
(14,
'0.185*商业 + 0.144*创新 + 0.108*转型 + 0.100*管理 + 0.098*一文 + 0.092*分析 + 0.072*数据 + 0.060*金融 + 0.053*企业 + 0.036*技术 + 0.032*知识 + 0.020*知识图谱'),
(15,
'0.235*转型 + 0.163*商业 + 0.140*企业 + 0.102*技术 + 0.074*数据 + 0.072*分析 + 0.067*管理 + 0.046*知识 + 0.039*一文 + 0.027*知识图谱 + 0.025*创新 + 0.010*金融'),
(16,
'0.165*商业 + 0.164*管理 + 0.159*分析 + 0.126*数据 + 0.109*创新 + 0.079*企业 + 0.066*知识图谱 + 0.041*技术 + 0.038*知识 + 0.029*一文 + 0.014*金融 + 0.011*转型'),
(17,
'0.204*管理 + 0.193*知识图谱 + 0.166*一文 + 0.163*转型 + 0.088*创新 + 0.048*知识 + 0.045*金融 + 0.038*商业 + 0.020*企业 + 0.016*数据 + 0.015*分析 + 0.004*技术'),
(18,
'0.225*企业 + 0.136*金融 + 0.136*技术 + 0.099*知识 + 0.098*商业 + 0.095*一文 + 0.078*创新 + 0.076*管理 + 0.034*知识图谱 + 0.019*分析 + 0.004*数据 + 0.001*转型'),
(19,'0.232*企业 + 0.205*一文 + 0.121*技术 + 0.089*金融 + 0.076*数据 + 0.076*创新 + 0.075*转型 + 0.069*商业 + 0.017*管理 + 0.016*分析 + 0.012*知识图谱 + 0.012*知识')]
从上面的示例中可以看到,添加新的向量空间转换(Vetor Space Modle Transformations)(比如不同的加权策略)相当简单; 有关更多信息和示例,请参阅gensim的API参考或参阅各类库的源代码。
值得重申的是,这些都是独特的增量实现,不需要一次性将整个训练语料库载入到本地内存中。另外,如果你有多个CPU和较大的内存,你可以采用分布式计算,最大限度的提高计算效率。好了,打了这么多的基础以后,我们可以进入到第一个实际应用的环节 - 相似文本检索,给定一个待查语句和一系列的相关文档,从这些文档中找到和待查语句相似度最高的一个来。
在下一篇文章中,笔者会接着本次的主题,聊聊基于LSI模型抽取的文本特征进行文档相似性检索,也就是给定一个新文档,在已有的语料库中找到和它语义或主题最为相似的文档。
参考资料:
[1] Bradford. 2008. An empirical study of required dimensionality for large-scale latent semantic indexing applications.
[2] Hoffman, Blei, Bach. 2010. Online learning for Latent Dirichlet Allocation.
[3] Wang, Paisley, Blei. 2011. Online variational inference for the hierarchical Dirichlet process.
[4] Halko, Martinsson, Tropp. 2009. Finding structure with randomness.
[5] Řehůřek. 2011. Subspace tracking for Latent Semantic Analysis.
推荐阅读
征稿启示| 200元稿费+5000DBC(价值20个小时GPU算力)
文本自动摘要任务的“不完全”心得总结番外篇——submodular函数优化
斯坦福大学NLP组Python深度学习自然语言处理工具Stanza试用
关于AINLP
AINLP 是一个有趣有AI的自然语言处理社区,专注于 AI、NLP、机器学习、深度学习、推荐算法等相关技术的分享,主题包括文本摘要、智能问答、聊天机器人、机器翻译、自动生成、知识图谱、预训练模型、推荐系统、计算广告、招聘信息、求职经验分享等,欢迎关注!加技术交流群请添加AINLPer(id:ainlper),备注工作/研究方向+加群目的。
阅读至此了,分享、点赞、在看三选一吧🙏