LSI的实现

LSI(潜在语义索引)的python实现

本篇博客记录两种LSI的python实现,一种利用gensim,一种利用sklearn。

使用到的函数工具


def get_data(intro_list):
    # 中文预处理
    new_list = []
    for intro in intro_list:
        new_list.append(format_str(intro))

    # 进行分词
    fenci_list = []
    fenci_list = fenci(new_list)

    # 去除停用词
    with open('./stopwords.txt', 'r', encoding='utf-8') as f:
        stopwords_list = []
        for line in f.readlines():
            stopwords_list.append(line.strip())

    clean_list = drop_stopwords(fenci_list, stopwords_list)
    return clean_list

# 中文文本预处理
def is_cnen(uchar):
    # 只保留汉字与英文,去掉了数字标点和特殊字符
    if (uchar >= u'\u4e00' and uchar <= u'\u9fa5') or (uchar >= u'\u0041' and uchar <= u'\u005A') or (uchar >= u'\u0061' and uchar <= u'\u007A'):
        return True
    else:
        return False

def format_str(content):
    content_str = ''
    for i in content:
        if is_cnen(i):
            content_str = content_str + i
    return content_str

# 分词
def fenci(new_list):
    cut_words = map(lambda s: list(jieba.cut(s)), new_list)
    return list(cut_words)

# 去除停用词
def drop_stopwords(fenci_list, stopwords):
    fenci_list_clean = []
    for line in fenci_list:
        line_clean = []
        for word in line:
            if word in stopwords:
                continue
            line_clean.append(word)
        fenci_list_clean.append(line_clean)
    return fenci_list_clean


def cos_sim(vector_a, vector_b):
    """
    计算两个向量之间的余弦相似度
    :param vector_a: 向量 a 
    :param vector_b: 向量 b
    :return: sim
    """
    vector_a = np.mat(vector_a)
    vector_b = np.mat(vector_b)
    num = float(vector_a * vector_b.T)
    denom = np.linalg.norm(vector_a) * np.linalg.norm(vector_b)
    cos = num / denom
    sim = 0.5 + 0.5 * cos
    return sim

gensim方法

import jieba
import gensim
from gensim import corpora
from gensim import similarities
import pandas as pd
from utils import *


# 读取数据,进行中文预处理,得到词语字典,将文档变成DT矩阵
# 读取frame中的app概要说明
game_frame = pd.read_csv("../data/game.csv")
intro_list = game_frame['概要说明'].values.tolist()


# 得到的clean_list是预处理完成的词语列表
# get_data函数对读入数据进行预处理,保留汉字与英文字母,分词,去除停用词
clean_list = get_data(intro_list)

# 下一步准备 Document-Term 矩阵
# 创建语料的词语词典,每个单独的词语都会被赋予一个索引
dictionary = corpora.Dictionary(clean_list)


# 使用上面的词典,将转换文档列表(语料)变成 DT 矩阵
doc_term_matrix = [dictionary.doc2bow(doc) for doc in clean_list]

# 创建tfidf对象
# LSI LDA 等模型通常用bow向量或是tfidf向量作为语料输入,上面的doc_term_matrix就是bow向量
tfidf = gensim.models.TfidfModel(doc_term_matrix)
corpus_tfidf = tfidf[doc_term_matrix]


# 构建LDA模型进行训练
Lda = gensim.models.ldamodel.LdaModel
ldamodel = Lda(corpus_tfidf, num_topics=3, id2word=dictionary, passes=50)


# 构建LSI模型进行训练
Lsi = gensim.models.LsiModel
lsimodel = Lsi(corpus_tfidf, id2word=dictionary, num_topics=100)


# 用待检索的文档向量初始化一个相似度计算的对象
index = similarities.MatrixSimilarity(lsimodel[corpus_tfidf])


# 保存相似度矩阵,index中每一行表示一篇文档,列表示主题,列数与前面定义的num_topics数是一致的
index.save('./sim_mat.index')
index = similarities.MatrixSimilarity.load('./sim_mat.index')


# 计算一篇文档与现有语料中所有文档的(余弦)相似度
# 这里先取语料中的第一篇文档试验一下

query_bow = dictionary.doc2bow(clean_list[0])

# tfidf向量化
query_tfidf = tfidf[query_bow]

# 用之前训练好的LSI模型将其映射到topic空间
query_vec = lsimodel[query_tfidf]

# 检查query在index中的相似度
sim = index[query_vec]
print(list(enumerate(sim)))

sklearn方法

# --*--conding:utf-8 --*--

import jieba
import jieba.analyse
import json
import numpy as np
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.decomposition import TruncatedSVD
from sklearn.preprocessing import Normalizer
from sklearn.pipeline import make_pipeline
from utils import *


# 读取数据
game_frame = pd.read_csv("../data/game.csv")
intro_list = game_frame['概要说明'].values.tolist()
name_list = game_frame['name'].values.tolist()

# 利用get_data函数得到预处理后的数据
clean_intro_list = get_data(intro_list)

# 把所以文档整理到一个列表中,列表中的每一项是字符串,表示一篇文档,文档中的分词之间用空格隔开
str_intro_list = []
for doc in clean_intro_list:
    doc_str = ' '.join(doc)
    str_intro_list.append(doc_str)


# 建立tfidf对象。这里可以添加停用词,由于前面做文本预处理的时候已经做过了,所以这里可以忽略
vec = TfidfVectorizer(ngram_range=(1, 1), use_idf=True, smooth_idf=True, sublinear_tf=True, stop_words=None)

# 将对象应用在存文档的列表上,得到带有权重的词表
keywords = vec.fit_transform(str_intro_list)

# 建立svd对象
svd = TruncatedSVD(n_components=100)

# 将svd与正则化
norm = Normalizer(copy=False)

# Pipeline里面需要一个列表,列表里元素是一个个元组,每个元组代表对数据的处理,元组的第一个参数是处理的别名,随便取,第二个参数是处理的函数。这里的第一项任务是svd,第二步正则化,使用pipeline的时候sklearn会顺序执行这些步骤,相当于将几步任务串行顺序运算。而这里的make_pipeline是简化版的Pipeline,不需要也不允许为函数命名。
# 这一步手工构建了lsi对象
lsi = make_pipeline(svd, norm)

# 将tfidf后的文档fit到lsi模型中
all_topic_vector = lsi.fit_transform(keywords)

# 把游戏名和对应的主题向量存到字典里,key是游戏名,value是主题向量
# 建立字典,用于存储向量
topic_vector = {}
for i in range(len(name_list)):
    topic_vector[name_list[i]] = all_topic_vector[i]

for name in topic_vector:
    sim = 0
    for same_name in topic_vector:
        # cos_sim 是自己定义的计算余弦相似度的函数
        o_sim = cos_sim(topic_vector[name], topic_vector[same_name])
        if o_sim > sim and o_sim != 1:
            sim = o_sim
            sim_name = same_name
    print(name, sim_name)

总结

gensim的方法需要建立字典映射,将每个分好的词建立索引,根据字典,把文档变成bow向量的形式,进一步可以用tfidf,再将向量作为lsi的参数。gensim的包里都有对应的工具,可以很容易的建立字典、形成向量、建立lsi模型、生成相似度矩阵等等。

sklearn的方法需要手工搭建lsi,利用TfidfVectorize函数得到tfidf向量(而且这个函数好像是自动建立了字典映射),再构建svd降维和正则化,将向量作为参数导入进去,得到了每篇文档的主题向量。

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
vc++全版本组件大全 VC++运行时(Visual C++ Runtime)是VC++开发环境中用于支持C和C++程序运行的基础库集合。这些库包含了执行C/C++程序所必需的基本函数和数据结构,例如内存管理、字符串操作、输入输出处理、异常处理等。VC++运行时库分为静态库和动态库两种形式,以适应不同类型的项目需求。 静态链接库 vs 动态链接库 静态链接库(Static Linking Libraries):在编译时,静态库的代码会被直接嵌入到最终生成的可执行文件中。这意味着每个使用静态库的程序都会包含库代码的一个副本,导致最终程序的体积较大,但不需要外部库文件支持即可独立运行。在VC++中,静态链接库的例子有LIBC.lib(用于单线程程序)和LIBCMT.lib(用于多线程程序)。 动态链接库(Dynamic Link Libraries):与静态链接相反,动态库的代码并不直接加入到应用程序中,而是在程序运行时被加载。这使得多个程序可以共享同一份库代码,节省了系统资源。VC++的动态运行时库主要通过msvcrt.dll(或其变体,如MSVCRTD.dll用于调试版本)实现,与之配套的导入库(Import Library)如CRTDLL.lib用于链接阶段。 运行时库的版本 VC++运行时库随着Visual Studio版本的更新而发展,每个版本都可能引入新的特性和优化,同时保持向后兼容性。例如,有VC++ 2005、2008、2010直至2019等多个版本的运行时库,每个版本都对应着特定的开发环境和Windows操作系统。 重要性 VC++运行时对于确保程序正确运行至关重要。当程序在没有安装相应运行时库的计算机上执行时,可能会遇到因缺失DLL文件(如MSVCP*.dll, VCRUNTIME*.dll等)而导致的错误。因此,开发完成后,通常需要分发相应的VC++ Redistributable Packages给最终用户安装,以确保程序能够在目标系统上顺利运行。 安装与部署 安装VC++运行时库通常是通过Microsoft提供的Redistributable Packages完成的,这是一个简单的过程,用户只需运行安装程序即可自动安装所需组件。对于开发者而言,了解和管理不同版本的运行时库对于确保应用程序的广泛兼容性和可靠性是必要的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值