【人工智能】Sklearn的模型 和 CountVectorizer 、Transformer 保存 和 使用

1、简述

如果用到TF-IDF,sklearn中经常会用CountVectorizer与TfidfTransformer两个类。我们总是需要保存TF-IDF的词典,然后计算测试集的TF-IDF,这里要注意sklearn中保存有两种方法:pickle与joblib。这里,我们可以用pickle保存特征,用joblib保存模型。

2、 CountVectorizer 和 Transformer保存和加载

2.1、TF-IDF词典的保存

 train_content = segmentWord(X_train)
 test_content = segmentWord(X_test)
 # replace 必须加,保存训练集的特征
 vectorizer = CountVectorizer(decode_error="replace")
 tfidftransformer = TfidfTransformer()
 # 注意在训练的时候必须用vectorizer.fit_transform、tfidftransformer.fit_transform
 # 在预测的时候必须用vectorizer.transform、tfidftransformer.transform
 vec_train = vectorizer.fit_transform(train_content)
 tfidf = tfidftransformer.fit_transform(vec_train)

 # 保存经过fit的vectorizer 与 经过fit的tfidftransformer,预测时使用
 feature_path = 'models/feature.pkl'
 with open(feature_path, 'wb') as fw:
     pickle.dump(vectorizer.vocabulary_, fw)
 
 tfidftransformer_path = 'models/tfidftransformer.pkl'
 with open(tfidftransformer_path, 'wb') as fw:
     pickle.dump(tfidftransformer, fw)

注意:vectorizer 与tfidftransformer都要保存,而且只能 fit_transform 之后保存,表示vectorizer 与tfidftransformer已经用训练集训练好了。

2.2、TF-IDF加载,测试新数据

# 加载特征
feature_path = 'models/feature.pkl'
loaded_vec = CountVectorizer(decode_error="replace", vocabulary=pickle.load(open(feature_path, "rb")))
# 加载TfidfTransformer
tfidftransformer_path = 'models/tfidftransformer.pkl'
tfidftransformer = pickle.load(open(tfidftransformer_path, "rb"))
#测试用transform,表示测试数据,为list
test_tfidf = tfidftransformer.transform(loaded_vec.transform(test_content))

3、模型的保存和加载

3.1、模型的保存

# clf_model为生成的模型,利用joblib的dump保存
    clf_model = trainModel()  
    joblib.dump(clf_model, "model_"+path) 

3.2、模型的加载

# clf_model为模型,利用joblib的load加载
    clf_model = joblib.load(model_path)

4、例子

举了一个简单的例子,可以学一下这里到底怎么使用

"""
Author:沙振宇
Time:20191112
Info:简单的情绪识别
"""
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.feature_extraction.text import CountVectorizer
from sklearn import svm
from sklearn.metrics import accuracy_score
import joblib
import os
import jieba
import datetime
import warnings # 忽略警告
import pickle
warnings.filterwarnings("ignore", category=FutureWarning, module="sklearn", lineno=196)

m_list_allText = []# 全部内容(包含重复标签,顺序)
m_list_allL4ID = []# 全部标签(包含重复标签,顺序)
m_list_allLabel = [] # 模型全部标签(不包含重复标签,顺序)
m_map_id_score = {} # id对应的分值

# 读取文件里面数据,获取标签和内容
def getFile(filename, count = -1):
    with open(filename, 'r' ,encoding='utf-8') as fp:
        global m_list_allL4ID,m_list_allText
        m_list_allL4ID = []
        m_list_allText = []
        tmp_text = []
        m_file_text = fp.readlines()
        tmp_lines = len(m_file_text)
        for i in range(tmp_lines):
            text = m_file_text[i]
            if ":" in text:
                L4ID = text.split(":")[-2]
                Msg = text.split(":")[-1]
                m_list_allL4ID.append(L4ID)
                m_list_allText.append(Msg)
                if L4ID not in m_list_allLabel:
                    m_list_allLabel.append(L4ID)
                    tmp_text = []
                tmp_text.append(Msg)

# jieba分词
def jiabaToVector(list, isTest, isTFIDF = False):
    tmp_list = []
    for sentence in list:
        tmp_list.append(" ".join(jieba.cut(sentence.strip())))
    # 利用TFIDF生成词向量
    transformer = TfidfTransformer()
    if isTest:
        if isTFIDF:
            tfidf = transformer.fit_transform(vectorizer.transform(tmp_list))
        else:
            tfidf = vectorizer.transform(tmp_list)
    else:
        if isTFIDF:
            tfidf = transformer.fit_transform(vectorizer.fit_transform(tmp_list))
        else:
            tfidf = vectorizer.fit_transform(tmp_list)
    return tfidf

# 创建默认的参数
def predict_4(X, Y):
    clf = svm.LinearSVC()
    clf = clf.fit(X, Y)
    return clf

# 将L4转换为整形
def L4ToInt(m_label_l4):
    m_label_l4New = []
    for i in range(len(m_label_l4)):
        m_label_l4New.append(int(m_label_l4[i][1:]))
    # print("m_label_l4New:",m_label_l4New)
    return m_label_l4New

# 训练SVM模型
def trainSVM(path, linecount = -1):
    getFile(path, linecount)

    vectorizer = CountVectorizer(decode_error="replace")  # 全局向量, replace 必须加,保存训练集的特征
    vector_train = jiabaToVector(m_list_allText, False, True)# 生成训练向量

    lenall = len(m_list_allText)# 数据大小
    print("总集大小:", lenall)# print("总集大小:", lenall)

    startT_Train = datetime.datetime.now()# 训练
    clf = predict_4(vector_train, m_list_allL4ID)
    endT_Train = datetime.datetime.now()
    print("训练Time:", (endT_Train - startT_Train).microseconds)
    return clf,vectorizer

# 查看完全匹配
def completeLabelDataMatch(path , query):
    outList = {}
    file_train = os.path.join(path)
    with open(file_train, 'r', encoding='UTF-8')as fp:
        textlist = fp.readlines()
        for text in textlist:
            if ":" in text:
                conditionId = text.split(":")[-2]
                Msg = text.split(":")[-1]
                message = Msg.strip("\n")
                if query == message:
                    outList["conditionId"] = conditionId
                    outList["Score"] = 1
                    print("Complete labelData match work: %s:%s"%(conditionId,message))
                    return outList
    return False

# 查看query的分值
def SVMMain(path, clf, query, score):
    outList = completeLabelDataMatch(path, query)
    if outList:
        print("outList[\"conditionId\"]:", outList["conditionId"])
        print("outList[\"Score\"]:", outList["Score"])
    else:
        outList = useSVM(clf, query)

    if outList["Score"] > score:
        return emotionAnalysis(outList["conditionId"])
    else:
        return "normal"

# 运用SVM模型
def useSVM(clf, query):
    outList = {}
    querylist = []
    querylist.append(query)
    vector_test = jiabaToVector(querylist, True, True) # 生成测试向量
    startT = datetime.datetime.now()
    percent = clf.decision_function(vector_test)
    scorelist = []
    if len(percent[0]):
        scorelist = percent[0]

    if len(m_list_allLabel) == len(scorelist):
        for i in range(len(scorelist)):
            m_map_id_score[m_list_allLabel[i]] = scorelist[i]

    pVallist = sorted(scorelist,reverse=True)
    percent = max(pVallist)
    conditionID = ""
    for item in range (len(m_map_id_score)):
        if m_map_id_score[m_list_allLabel[item]] == percent:
            conditionID = m_list_allLabel[item]

    endT = datetime.datetime.now()
    print("测试Time:", (endT - startT).microseconds)
    outList["conditionId"] = conditionID
    outList["Score"] = percent
    print("outList[\"conditionId\"]:", outList["conditionId"])
    print("outList[\"Score\"]:", outList["Score"])
    return outList

# 情绪识别
def emotionAnalysis(label):
    negtiveId = ['4000447','4000448','4000453','4000449','4000450','4000451', '4000452','4000454','4000459','4000458','4002227','4000461','4000460','4000465','4000464','4000803','4000468'] # 消极
    positiveId = ['4000439','4000440','4000441','4000442','4000462','4000467','4000469','4000496','4000497'] # 积极
    print("negtiveId:",negtiveId)
    print("positiveId:",positiveId)
    if label in negtiveId:
        return "negtive"
    elif label in positiveId:
        return "positive"
    else:
        return "normal"

# 保存模型和特征
def saveModel(path):
    clf, vectorizer = trainSVM(path, -1)
    feature_path = path
    if "/" in path:
        joblib.dump(clf, "model_" + path.split("/")[1])
        if ".txt" in path:
            feature_path = 'feature_' + path.split("/")[1].split(".txt")[0] + '.pkl'
    else:
        joblib.dump(clf, "model_" + path)
        if ".txt" in path:
            feature_path = 'feature_' + path.split(".txt")[0] + '.pkl'
    print("模型已经保存,开始保存特征")

    with open(feature_path, 'wb') as fw:
        pickle.dump(vectorizer.vocabulary_, fw)
    print("特征已经保存。。。")

# 使用模型和特征
def useModel(model_path, feature_path):
    # 加载模型
    clf = joblib.load(model_path)
    # 加载特征
    loaded_vec = CountVectorizer(decode_error = "replace", vocabulary = pickle.load(open(feature_path, "rb")))
    return clf, loaded_vec

if __name__ =="__main__":
    path = "../rg_train_20171230_1000008.txt"
    # 保存模型
    # saveModel(path)

    # 加载模型
    global vectorizer
    clf, vectorizer = useModel("model_rg_train_20171230_1000008.txt","feature_rg_train_20171230_1000008.pkl")

    source = "我很开心"
    source = source.replace("\r", "")
    source = source.replace("\n", "")
    source = source.lower()
    source = source[0:256]
    print("开始匹配")
    result = SVMMain(path , clf, source, 0.6)

    if result == "normal":
        print("中性情绪")
    elif result == "negtive":
        print("负向情绪")
    elif result == "positive":
        print("正向情绪")

<think>嗯,用户问的是关于TF-IDF Transformer使用方法实现原理。首先,我需要回忆一下TF-IDF的基本概念。根据引用中的资料,TF-IDF是Term Frequency-Inverse Document Frequency的缩写,用来衡量词语在文档中的重要性。TF是词频,IDF是逆文档频率,两者的乘积就是TF-IDF值。 用户可能已经知道TF-IDF是什么,但需要了解如何具体应用,特别是结合Transformer的部分。在sklearn中,TfidfTransformer通常CountVectorizer一起使用,这点在引用5中提到过。我应该先解释TfidfTransformer的作用,它是将词频矩阵转换为TF-IDF矩阵的步骤。 接下来,使用方法部分需要给出代码示例。引用45都提到了sklearn中的TfidfVectorizerTfidfTransformer,但用户可能更关心如何分步骤使用。比如,先用CountVectorizer生成词频矩阵,再用TfidfTransformer计算TF-IDF值。需要确保代码示例正确,并且符合用户的场景,比如处理中文可能需要分词,但用户的问题可能更关注流程而不是具体分词处理。 实现原理方面,要详细说明TFIDF的计算公式,引用2、3、5中的公式需要整合。比如,TF的计算是某个词在文档中的出现次数除以文档总词数,而IDF是对总文档数除以包含该词的文档数取对数。这里要注意平滑参数,可能引用中提到过,sklearn的默认参数可能有所不同,需要指出。 可能用户在使用时会遇到问题,比如如何处理不同的文档集,或者参数调整的影响。例如,smooth_idf参数的作用,或者norm参数用于归一化。这些在引用5的代码示例中可能没有详细说明,需要进一步解释。 另外,用户可能混淆TfidfVectorizerTfidfTransformer的区别。TfidfVectorizer相当于CountVectorizer加上TfidfTransformer,所以如果已经有用CountVectorizer生成的矩阵,可以直接用Transformer转换。需要明确这一点,避免用户混淆。 关于原理部分,需要强调TF-IDF如何突出重要词汇,抑制常见词。引用5中提到过,TF-IDF值高的词对文档更重要,同时去除常用词。这点在解释时需要强调,帮助用户理解为什么使用TF-IDF。 最后,相关问题部分需要引导用户深入,比如与其他方法的对比,参数调优,或者结合机器学习模型的应用。根据引用中的资料,可以提出特征选择、与Word2Vec的对比,或者优化方法如sublinear_tf的作用。 需要确保回答结构清晰,分步骤说明使用方法原理,代码示例正确,并且引用相关引用资料来支持解释。同时检查是否符合LaTeX格式要求,数学公式用$$包围,行内公式用$符号。例如,TF-IDF的公式应该用独立公式块,而TFIDF的公式可以分别列出。</think>### TF-IDF Transformer 实现原理与使用方法 #### 一、TF-IDF Transformer 实现原理 TF-IDF Transformer 是 scikit-learn 中用于将**词频矩阵**(由 `CountVectorizer` 生成)转换为 **TF-IDF 矩阵**的工具。其核心计算步骤如下: 1. **词频(TF)计算** 对于某个词语 $t$ 在文档 $d$ 中的词频,计算公式为: $$ \text{TF}(t, d) = \frac{\text{词语 } t \text{ 在文档 } d \text{ 中的出现次数}}{\text{文档 } d \text{ 的总词数}} $$ 例如,若“算法”在文档中出现 5 次,文档总词数为 100,则 TF 值为 $0.05$[^2]。 2. **逆文档频率(IDF)计算** IDF 用于衡量词语的全局重要性,公式为: $$ \text{IDF}(t) = \log \frac{\text{文档总数} + 1}{\text{包含词语 } t \text{ 的文档数} + 1} + 1 $$ scikit-learn 默认使用平滑后的 IDF 公式,避免分母为零的情况[^5]。 3. **TF-IDF 权重计算** 最终权重为 TF 与 IDF 的乘积: $$ \text{TF-IDF}(t, d) = \text{TF}(t, d) \times \text{IDF}(t) $$ 高 TF-IDF 值的词语对当前文档更重要,同时能过滤常见词(如“的”“了”)[^3]。 #### 二、TF-IDF Transformer 使用方法 ##### 场景示例:处理中文文本 1. **生成词频矩阵** 使用 `CountVectorizer` 将文本转换为词频矩阵: ```python from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer corpus = ["自然语言处理 是 人工智能 的 重要分支", "TF-IDF 是 文本特征 提取 的 经典方法"] vectorizer = CountVectorizer(token_pattern=r"(?u)\b\w+\b") # 适配中文分词 X_counts = vectorizer.fit_transform(corpus) ``` 2. **转换为 TF-IDF 矩阵** 通过 `TfidfTransformer` 计算 TF-IDF 权重: ```python transformer = TfidfTransformer(smooth_idf=True, use_idf=True) X_tfidf = transformer.fit_transform(X_counts) ``` 3. **查看结果** ```python print(vectorizer.get_feature_names_out()) # 输出特征词列表 print(X_tfidf.toarray()) # 输出 TF-IDF 矩阵 ``` ##### 关键参数说明 - `smooth_idf=True`:平滑 IDF,避免除零错误。 - `use_idf=True`:启用 IDF 计算(若为 False,则仅计算 TF)。 - `norm='l2'`:默认对向量进行 L2 归一化,使不同文档的向量可比[^4]。 #### 三、与 TfidfVectorizer 的区别 `TfidfVectorizer` 是 `CountVectorizer + TfidfTransformer` 的组合工具,适用于直接输入原始文本: ```python from sklearn.feature_extraction.text import TfidfVectorizer tfidf_vectorizer = TfidfVectorizer() X_tfidf = tfidf_vectorizer.fit_transform(corpus) ``` #### 四、应用场景 - **文本聚类**:将 TF-IDF 矩阵输入 K-Means 等算法(如引用5中的实现)[^5]。 - **分类任务**:作为 SVM、朴素贝叶斯等模型的输入特征。 - **信息检索**:通过 TF-IDF 权重排序文档相关性。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

沙振宇

你的鼓励将是我创作的最大动力~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值