介绍
Gensim是一个用于从文档中自动提取语义主题的Python库,足够智能,堪比无 痛人流。
Gensim可以处理原生,非结构化的数值化文本(纯文本)。Gensim里面的算法,比如Latent Semantic Analysis(潜在语义分析LSA),Latent Dirichlet Allocation,Random Projections,通过在语料库的训练下检验词的统计共生模式(statistical co-occurrence patterns)来发现文档的语义结构。这些算法是非监督的,也就是说你只需要一个语料库的文档集。
当得到这些统计模式后,任何文本都能够用语义表示(semantic representation)来简洁的表达,并得到一个局部的相似度与其他文本区分开来。
核心概念
Corpus
数字化文档的集合,被用于自动推断文档的结构和主题等。由此,corpus也称作training corpus,被推断的这些潜在结构用于给新的文档分配主题,无需人为介入,比如给文档打标签,不存在的。
Vector
在向量空间模型中,每个文档被表示成了一组特征,比如,一个单一的特征可能被视为一个问答对。
1.How many times does the word splonge appear in the document? Zero.
2.How many paragraphs does the document consist of? Two.
3.How many fonts does the document use? Five.
问题通常被表示成整数ID,在这里就是1,2,3.所以这篇文档就表示成了(1, 0.0), (2, 2.0), (3, 5.0). 如果我们提前知道所有问题,那我们可能会省略他们,然后简单的写成(0.0, 2.0, 5.0).答案的序列被视为一个向量(这个例子里是三维向量),出于实际考虑,我们只考虑那些答案可以转换成一个单一实数的问题。
Sparse Vector
通常,大部分问题的答案都是0,为了节约空间,我们会从文档表示中省略他们,只写成(2, 2.0), (3, 5.0) (去掉 (1, 0.0)). 既然问题提前知道,那文档中所有稀疏表示的丢失特征都是0.
Gensim不会指定任何特定的Corpus格式,不管Corpus是怎样的格式,迭代时回一次产生这些Sparse Vector
Model
我们用model将一个文档的表示转换成另一个。Gensim中文档表示成向量,所以model可以看成是两个向量空间的转换。转换的细节从training corpus中学习
语料(Corpus):一组原始文本的集合,用于无监督地训练文本主题的隐层结构。语料中不需要人工标注的附加信息。在Gensim中,Corpus通常是一个可迭代的对象(比如列表)。每一次迭代返回一个可用于表达文本对象的稀疏向量。 向量(Vector):由一组文本特征构成的列表。是一段文本在Gensim中的内部表达。 稀疏向量(Sparse Vector):通常,我们可以略去向量中多余的0元素。此时,向量中的每一个元素是一个(key, value)的tuple。 模型(Model):是一个抽象的术语。定义了两个向量空间的变换(即从文本的一种向量表达变换为另一种向量表达)。
学习Gensim
学习gensim首先得安装:
pip install gensim
接下来我们结合案例做一个简单的学习
import jieba # 语料库 from gensim import corpora # 导入语言模型 from gensim import models # 稀疏矩阵相识度 from gensim import similarities # 语料库 l1 = ["你的名字是什么", "你今年几岁了", "你有多高你手多大", "你手多大"] # 用户问的问题 a = "你今年多大了" all_doc_list = [] # for doc in l1: # 利用jieba分词将语料库中的每一个问题切割 doc_list = [word for word in jieba.cut(doc)] all_doc_list.append(doc_list) print(all_doc_list) # [['你', '的', '名字', '是', '什么'], ['你', '今年', '几岁', '了'], ['你', '有', '多', '高', '你', '手多大'], ['你', '手多大']] # 利用jieba分词将要问的问题切割 doc_test_list = [word for word in jieba.cut(a)] print(doc_test_list) # ['你', '今年', '多大', '了'] ==>1685 # 制作语料库 dictionary = corpora.Dictionary(all_doc_list) # 制作词袋 # 词袋:是根据当前所有的问题即列表all_doc_list中每一个列表中的每一个元素(就是字)为他们做一个唯一的标志,形成一个key:velue的字典 print("token2id", dictionary.token2id) # print("dictionary", dictionary, type(dictionary)) # token2id {'什么': 0, '你': 1, '名字': 2, '是': 3, '的': 4, '了': 5, '今年': 6, '几岁': 7, '多': 8, '手多大': 9, '有': 10, '高': 11} # ['你', '的', '名字', '是', '什么'] ==>14230 # ['你', '今年', '几岁', '了'] ==>1675 # 制作语料库 # 这里是将all_doc_list 中的每一个列表中的词语 与 dictionary 中的Key进行匹配 # doc2bow文本变成id,这个词在当前的列表中出现的次数 # ['你', '的', '名字', '是', '什么'] ==>(1,1),(4,1),(2,1),(3,1),(0,1) # 1是你 1代表出现一次, 4是的 1代表出现了一次, 以此类推 2是名字 , 3是是,0是什么 corpus = [dictionary.doc2bow(doc) for doc in all_doc_list] print("corpus", corpus, type(corpus)) # corpus [[(0, 1), (1, 1), (2, 1), (3, 1), (4, 1)], [(1, 1), (5, 1), (6, 1), (7, 1)], [(1, 2), (8, 1), (9, 1), (10, 1), (11, 1)], [(1, 1), (9, 1)]] <class 'list'> # ['你', '今年', '多大', '了'] 词袋中没有多大165 # 所以需要词向量化 # 将需要寻找相似度的分词列表 做成 语料库 doc_test_vec # ['你', '今年', '多大', '了'] (1, 1), (5, 1), (6, 1) doc_test_vec = dictionary.doc2bow(doc_test_list) print("doc_test_vec", doc_test_vec, type(doc_test_vec)) # doc_test_vec [(1, 1), (5, 1), (6, 1)] <class 'list'> # 将corpus语料库(初识语料库) 使用Lsi模型进行训练,将语料库变成计算机可识别可读的数字 lsi = models.LsiModel(corpus) print("lsi", lsi, type(lsi)) # lsi[corpus] <gensim.interfaces.TransformedCorpus object at 0x000001D92EEB43C8> # 语料库corpus的训练结果 print("lsi[corpus]", lsi[corpus]) # lsi[corpus] <gensim.interfaces.TransformedCorpus object at 0x000001D92EEB43C8> # 将问题放到放到已经训练好的语料库模型一个一个匹配,获取匹配分值 # 获得语料库doc_test_vec 在 语料库corpus的训练结果 中的 向量表示 print("lsi[doc_test_vec]", lsi[doc_test_vec]) # lsi[doc_test_vec] [(0, 0.9910312948854694), (1, 0.06777365757876067), (2, 1.1437866478720622), (3, -0.015934342901802588)] # 排过序,数字表示相识度,负数表示无限不接近 # 文本相似度 # 稀疏矩阵相似度 将 主 语料库corpus的训练结果 作为初始值 # 举例:匹配5*5的正方形 # 目前有[(3,3),(3,5),(4,5),(6,6)] # 设定-(1形状相似2.周长相识3面积相似),根据选定设定好的条件匹配最相似的,涉及算法 # lsi[corpus]==>Lsi训练好的语料库模型 # index是设定的匹配相识度的条件 index = similarities.SparseMatrixSimilarity(lsi[corpus], num_features=len(dictionary.keys())) print("index", index, type(index)) # 将 语料库doc_test_vec 在 语料库corpus的训练结果 中的 向量表示 与 语料库corpus的 向量表示 做矩阵相似度计算 gongyinshi = lsi[doc_test_vec] print(gongyinshi) sim = index[gongyinshi] print("sim", sim, type(sim)) # 对下标和相似度结果进行一个排序,拿出相似度最高的结果 # cc = sorted(enumerate(sim), key=lambda item: item[1],reverse=True) cc = sorted(enumerate(sim), key=lambda item: -item[1]) print(cc) text = l1[cc[0][0]] if cc[0][1] > 0: print(a, text)