# -*- coding: UTF-8 -*- # !/usr/bin/python # @time :2019/9/2 10:33 # @author :Mo # @function :topic model of NMF from nlg_yongzhuo.data_preprocess.text_preprocess import extract_chinese from nlg_yongzhuo.data_preprocess.text_preprocess import cut_sentence from nlg_yongzhuo.data_preprocess.text_preprocess import jieba_cut from nlg_yongzhuo.data.stop_words.stop_words import stop_words # sklearn from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.decomposition import NMF import numpy as np def tfidf_fit(sentences): """ tfidf相似度 :param sentences: :return: """ # tfidf计算 model = TfidfVectorizer(ngram_range=(1, 2), # 3,5 stop_words=[' ', '\t', '\n'], # 停用词 max_features=10000, token_pattern=r"(?u)\b\w+\b", # 过滤停用词 min_df=1, max_df=0.9, use_idf=1, # 光滑 smooth_idf=1, # 光滑 sublinear_tf=1, ) # 光滑 matrix = model.fit_transform(sentences) return matrix class NMFSum: def __init__(self): self.stop_words = stop_words.values() self.algorithm = 'lsi' def summarize(self, text, num=8, topic_min=3, judge_topic="all"): """ :param text: text or list, input docs :param num: int, number or amount of return :param topic_min: int, topic number :param judge_topic: str, calculate ways of topic :return: """ # 切句 if type(text) == str: self.sentences = cut_sentence(text) elif type(text) == list: self.sentences = text else: raise RuntimeError("text type must be list or str") # 切词 sentences_cut = [[word for word in jieba_cut(extract_chinese(sentence)) if word.strip()] for sentence in self.sentences] len_sentences_cut = len(sentences_cut) # 去除停用词等 self.sentences_cut = [list(filter(lambda x: x not in self.stop_words, sc)) for sc in sentences_cut] self.sentences_cut = [" ".join(sc) for sc in self.sentences_cut] # 计算每个句子的tfidf sen_tfidf = tfidf_fit(self.sentences_cut) # 主题数, 经验判断 topic_num = min(topic_min, int(len(sentences_cut) / 2)) # 设定最小主题数为3 nmf_tfidf = NMF(n_components=topic_num, max_iter=320) res_nmf_w = nmf_tfidf.fit_transform(sen_tfidf.T) # 基矩阵 or 权重矩阵 res_nmf_h = nmf_tfidf.components_ # 系数矩阵 or 降维矩阵 if judge_topic: ### 方案一, 获取最大那个主题的k个句子 ################################################################################## topic_t_score = np.sum(res_nmf_h, axis=-1) # 对每列(一个句子topic_num个主题),得分进行排序,0为最大 res_nmf_h_soft = res_nmf_h.argsort(axis=0)[-topic_num:][::-1] # 统计为最大每个主题的句子个数 exist = (res_nmf_h_soft <= 0) * 1.0 factor = np.ones(res_nmf_h_soft.shape[1]) topic_t_count = np.dot(exist, factor) # 标准化 topic_t_count /= np.sum(topic_t_count, axis=-1) topic_t_score /= np.sum(topic_t_score, axis=-1) # 主题最大个数占比, 与主题总得分占比选择最大的主题 topic_t_tc = topic_t_count + topic_t_score topic_t_tc_argmax = np.argmax(topic_t_tc) # 最后得分选择该最大主题的 res_nmf_h_soft_argmax = res_nmf_h[topic_t_tc_argmax].tolist() res_combine = {} for l in range(len_sentences_cut): res_combine[self.sentences[l]] = res_nmf_h_soft_argmax[l] score_sen = [(rc[1], rc[0]) for rc in sorted(res_combine.items(), key=lambda d: d[1], reverse=True)] ##################################################################################### else: ### 方案二, 获取最大主题概率的句子, 不分主题 res_combine = {} for i in range(len_sentences_cut): res_row_i = res_nmf_h[:, i] res_row_i_argmax = np.argmax(res_row_i) res_combine[self.sentences[i]] = res_row_i[res_row_i_argmax] score_sen = [(rc[1], rc[0]) for rc in sorted(res_combine.items(), key=lambda d: d[1], reverse=True)] num_min = min(num, len(self.sentences)) return score_sen[0:num_min] if __name__ == '__main__': nmf = NMFSum() doc = "多知网5月26日消息,今日,方直科技发公告,拟用自有资金人民币1.2亿元," \ "与深圳嘉道谷投资管理有限公司、深圳嘉道功程股权投资基金(有限合伙)共同发起设立嘉道方直教育产业投资基金(暂定名)。" \ "该基金认缴出资总规模为人民币3.01亿元。" \ "基金的出资方式具体如下:出资进度方面,基金合伙人的出资应于基金成立之日起四年内分四期缴足,每期缴付7525万元;" \ "各基金合伙人每期按其出资比例缴付。合伙期限为11年,投资目标为教育领域初创期或成长期企业。" \ "截止公告披露日,深圳嘉道谷投资管理有限公司股权结构如下:截止公告披露日,深圳嘉道功程股权投资基金产权结构如下:" \ "公告还披露,方直科技将探索在中小学教育、在线教育、非学历教育、学前教育、留学咨询等教育行业其他分支领域的投资。" \ "方直科技2016年营业收入9691万元,营业利润1432万元,归属于普通股股东的净利润1847万元。(多知网 黎珊)}}" doc = "和投票目标的等级来决定新的等级.简单的说。" \ "是上世纪90年代末提出的一种计算网页权重的算法! " \ "当时,互联网技术突飞猛进,各种网页网站爆炸式增长。" \ "业界急需一种相对比较准确的网页重要性计算方法。" \ "是人们能够从海量互联网世界中找出自己需要的信息。" \ "百度百科如是介绍他的思想:PageRank通过网络浩瀚的超链接关系来确定一个页面的等级。" \ "Google把从A页面到B页面的链接解释为A页面给B页面投票。" \ "Google根据投票来源甚至来源的来源,即链接到A页面的页面。" \ "一个高等级的页面可以使其他低等级页面的等级提升。" \ "具体说来就是,PageRank有两个基本思想,也可以说是假设。" \ "即数量假设:一个网页被越多的其他页面链接,就越重)。" \ "质量假设:一个网页越是被高质量的网页链接,就越重要。" \ "总的来说就是一句话,从全局角度考虑,获取重要的信。" doc = '早年林志颖带kimi上《爸爸去哪儿》的时候,当时遮遮掩掩的林志颖老婆低调探班,总让人觉得格外神秘,大概是特别不喜欢' \ '在公众面前曝光自己日常的那种人。可能这么些年过去,心态不断调整过了,至少在微博上,陈若仪越来越放得开,晒自己带' \ '娃照顾双子星的点滴,也晒日常自己的护肤心得,时不时安利一些小东西。都快晚上十点半,睡美容觉的最佳时候,结果才带' \ '完一天娃的陈若仪还是不忘先保养自己,敷起了面膜。泡完澡,这次用的是一个稍微平价的面膜,脸上、甚至仔细到脖子上都' \ '抹上了。陈若仪也是多此一举,特别说自己不是裸体,是裹着浴巾的,谁在意这个呀,目光完全被你那又长又扑闪的睫毛给吸' \ '引住了。这也太吓人吧,怎么能够长那么长那么密那么翘。嫉妒地说一句,真的很像种的假睫毛呐。陈若仪的睫毛应该是天生' \ '的基础好吧,要不然也不会遗传给小孩,一家子都是睫毛精,几个儿子现在这么小都是长睫毛。只是陈若仪现在这个完美状态,' \ '一定是后天再经过悉心的呵护培养。网友已经迫不及待让她教教怎么弄睫毛了,陈若仪也是答应地好好的。各种私人物品主动' \ '揭秘,安利一些品牌给大家,虽然一再强调是自己的日常小物,还是很让人怀疑,陈若仪是不是在做微商当网红呐,网友建议' \ '她开个店,看这回复,也是很有意愿了。她应该不缺这个钱才对。隔三差五介绍下自己用的小刷子之类,陈若仪乐于向大家传' \ '授自己的保养呵护之道。她是很容易就被晒出斑的肤质,去海岛参加婚礼,都要必备这几款超爱用的防晒隔离。日常用的、太' \ '阳大时候用的,好几个种类,活得相当精致。你们按照自己的需要了解一下。画眉毛,最爱用的是intergrate的眉笔。也是个' \ '念旧的人,除了Dior,陈若仪的另一个眉粉其中一个是她高中就开始用的Kate。一般都是大学才开始化妆修饰自己,感受得到' \ '陈若仪从小就很爱美。各种小零小碎的化妆品,已经买过七八次的粉红胡椒抛光美体油,每天洗完澡陈若仪都会喷在肚子、大' \ '腿、屁股和膝盖手肘,说是能保持肌肤的平滑紧致程度。每安利一样东西,总有网友要在下面问其他问题咋个办,真是相当信' \ '任陈若仪了。每次她也很耐心的解答,"去黑头我用的是SUQQU洁面去角质按摩膏磨砂洁面洗面奶,"一定要先按摩再用。她自己' \ '已经回购过好几次,意思是你们再了解一下。了解归了解,买不买随意。毕竟像她另一个爱用的达尔肤面膜,效果好是好,价' \ '格据说比sk2都还要贵,不是大多数人日常能够消费得起的,大家就看个热闹就好了,还是多买多试多用才能找到最适合自己的' \ '护肤方法。' sum = nmf.summarize(doc, num=6) for i in sum: print(i)