IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> 文本分类入门实战 -> 正文阅读

[人工智能]文本分类入门实战

多模态情感分析——文本分类入门实战

环境:python3.8
CSDN训练数据地址:还在审核中。
gitee地址为:https://gitee.com/huadeng863/text-classification-practice
有两个版本,一个是没有运行过的,可以运行体验一下,一般一个py文件要运行5-6分钟。
还有一个是将预处理全部做完的了,可以对照文章截图理解一下自然语言处理的实际操作。
为了方便立即将文章分为几个部分来讲解。

第一步:划分训练集和测试集(choosed.py)

数据已经全部放入data文件夹中,data文件夹下有九大类新闻文本,
在这里插入图片描述
每个新闻分类中是他的所有新闻样例,一条新闻单独一个txt文件,文件均有序号标注。
在这里插入图片描述
通过对所有数据样本进行统计:
在这里插入图片描述
可以发现样本成不均匀分布,为了保证训练模型中不会偏向某个分类,因此要保证不同分类的训练样本数目一致,所以,最后随机从每个分类中取5000条。并最终以8:2划分训练集和测试集。
实现代码及注释如下:

import os
import random
import shutil
path='./data/'
cate_list = os.listdir(path)  # 获取未分词语料库中所有类别
for mydir in cate_list:
    train_dir = './train_corpus/' + mydir + "/"  # 拼出训练集存贮的对应目录路径如:train_corpus/体育/
    if not os.path.exists(train_dir):  # 是否存在分词目录,如果没有则创建该目录
        os.makedirs(train_dir)

    test_dir = './test_corpus/' + mydir+'/' # 拼出测试存贮的对应目录路径如:test_corpus/体育/
    if not os.path.exists(test_dir):
        os.makedirs(test_dir)
    class_path=path+mydir+'/' # 生成当前类别的目录 如 data/体育/
    file_list=os.listdir(class_path) # 生成分类下文本名称列表
    length=len(file_list)
    print(mydir,length)
    res = random.sample(range(1, length+1), 5000) #在所有文件中随机选取五千个生成索引列表,乱序
    train=res[0:4000]#训练集占80%,4000条
    test=res[4000:5000]#测试集占20%,1000条
    #print(len(train),len(test))
    for file_path in file_list:
        fullname = class_path + file_path  # 拼出文件名全路径如:data/体育/21.txt
        #print(file_path)
        x=int(file_path.split('.')[0].split('_')[1])#将文件名中的序号取出
        if x in train:
           shutil.copyfile(fullname, train_dir+file_path)#将前面的文件复制到后面的目录中
        if x in test:
           shutil.copyfile(fullname, test_dir + file_path)

执行choosed.py文件划分前:
在这里插入图片描述
划分后将data文件分成两部分(训练集和测试集):
在这里插入图片描述

第二步:语料分词(corpus_segment.py)

之前已经介绍过分词的jieba库,所以直接上手就可以了。
实现代码及注释如下:

import os
import jieba
from Tools import savefile, readfile

def corpus_segment(corpus_path, seg_path):
    catelist = os.listdir(corpus_path)  # 获取corpus_path下的所有子目录
    #print(catelist)
    '''
    其中子目录的名字就是类别名,例如:
    train_corpus/体育/21.txt中,'train_corpus/'是corpus_path,'体育'是catelist中的一个成员
    '''
    # 获取每个目录(类别)下所有的文件
    for mydir in catelist:
        class_path = corpus_path + mydir + "/"  # 拼出分类子目录的路径如:train_corpus/体育/
        seg_dir = seg_path + mydir +  "/" # 拼出分类分词目录的路径如:train_seg/体育/
        if not os.path.exists(seg_dir):  # 是否存在分词目录
            os.makedirs(seg_dir)        #如果没有则创建该目录

        file_list = os.listdir(class_path)  # 获取未分词语料库中某一类别中的所有文本
        for file_path in file_list:  # 遍历类别目录下的所有文件
            fullname = class_path + file_path  # 拼出文件名全路径如:train_corpus/art/21.txt
            content = readfile(fullname)  # 读取文件内容
            '''此时,content里面存贮的是原文本的所有字符,例如多余的空格、空行、回车等等,
            接下来,我们需要把这些无关痛痒的字符统统去掉,变成只有标点符号做间隔的紧凑的文本内容
            为了保证大量文本的读取速度,Tools封装的readfiles为rb方法,也就是二进制的读写,所以需要转成'utf-8'编码
            '''
            content = content.replace('\r\n'.encode('utf-8'), ''.encode('utf-8')).strip()  # 删除换行
            content = content.replace(' '.encode('utf-8'), ''.encode('utf-8')).strip()  # 删除空行、多余的空格
            content_seg =jieba.cut(content) # 为文件内容分词
            savefile(seg_dir + file_path, ' '.join(content_seg).encode('utf-8'))  # 将处理后的文件保存到分词后语料目录

if __name__ == "__main__":

    seg_path = "./train_corpus_seg/"#分词之后的语料库储存路径
    corpus_path = "./train_corpus/"#需要分词的语料库路径
    corpus_segment(corpus_path, seg_path)
    print("训练语料分词结束!!!")
    seg_path = "./test_corpus_seg/"  # 分词之后的语料库储存路径
    corpus_path = "./test_corpus/"  # 需要分词的语料库路径
    corpus_segment(corpus_path, seg_path)
    print("测试语料分词结束!!!")

执行corpus_segment.py.py文件分词前:
在这里插入图片描述
分词后(将训练预料和测试语料分词后放入seg文件夹中):
在这里插入图片描述

第三步:bunch化操作(corpus2Bunch.py)

Bunch本质上的数据类型是dict字典类型,在这里为了方便处理将每个文本的分类类别,文件名路径,文件内容(已分词)转换成一个个的字典类型方便后续处理。
实现代码及注释如下:

import os
import pickle
from sklearn.datasets._base import Bunch
from Tools import readfile

def corpus2Bunch(wordbag_path, seg_path):
    catelist = os.listdir(seg_path)  # 获取seg_path下的所有子目录,也就是分类信息
    # 创建一个Bunch实例
    bunch = Bunch(target_name=[], label=[], filenames=[], contents=[])
    bunch.target_name.extend(catelist)
    '''
    extend(addlist)是python list中的函数,意思是用新的list(addlist)去扩充
    原来的list
    '''
    # 获取每个目录下所有的文件
    for mydir in catelist:
        class_path = seg_path + mydir + "/"  # 拼出分类子目录的路径
        file_list = os.listdir(class_path)  # 获取class_path下的所有文件
        for file_path in file_list:  # 遍历类别目录下文件
            fullname = class_path + file_path  # 拼出文件名全路径
            bunch.label.append(mydir)
            bunch.filenames.append(fullname)
            bunch.contents.append(readfile(fullname))  # 读取文件内容
            '''append(element)是python list中的函数,意思是向原来的list中添加element,注意与extend()函数的区别'''
    # 将bunch存储到wordbag_path路径中

    with open(wordbag_path, "wb") as file_obj:
        pickle.dump(bunch, file_obj)
    print("构建文本对象结束!!!")


if __name__ == "__main__":
    # 对训练集进行Bunch化操作:
    wordbag_path = "train_word_bag/train_set.dat"  # Bunch存储路径
    if not os.path.exists("train_word_bag"):  # 是否存在分词目录,如果没有则创建该目录
        os.makedirs("train_word_bag")
    seg_path = "train_corpus_seg/"  # 分词后分类语料库路径
    corpus2Bunch(wordbag_path, seg_path)

    # 对测试集进行Bunch化操作:
    wordbag_path = "test_word_bag/test_set.dat"  # Bunch存储路径
    if not os.path.exists("test_word_bag"):  # 是否存在分词目录,如果没有则创建该目录
        os.makedirs("test_word_bag")
    seg_path = "test_corpus_seg/"  # 分词后分类语料库路径
    corpus2Bunch(wordbag_path, seg_path)

执行corpus2Bunch.py,bunch前:
在这里插入图片描述
bunch化后多出两个词袋文件夹,里面存放的是所有训练集、测试集集成好得一个dat文件,方便了后续的处理、
在这里插入图片描述

第四步:构建TF-IDF向量空间(TFIDF_space.py)

这一步包括了去停用词,特征工程和特征选择。这部分的理论在上一篇文章做了简单的介绍,而且这个方法已经在python的sklearn中封装好了方法。
实现代码及注释如下:

from sklearn.datasets._base import Bunch
from sklearn.feature_extraction.text import TfidfVectorizer
from Tools import readfile, readbunchobj, writebunchobj

def vector_space(stopword_path, bunch_path, space_path, train_tfidf_path=None):
    stpwrdlst = readfile(stopword_path).splitlines()
    bunch = readbunchobj(bunch_path)
    tfidfspace = Bunch(target_name=bunch.target_name, label=bunch.label, filenames=bunch.filenames, tdm=[],
                       vocabulary={})

    if train_tfidf_path is not None:
        trainbunch = readbunchobj(train_tfidf_path)
        tfidfspace.vocabulary = trainbunch.vocabulary
        vectorizer = TfidfVectorizer(stop_words=stpwrdlst, sublinear_tf=True, max_df=0.5,
                                     vocabulary=trainbunch.vocabulary)
        '''
        #.stop_words=list类型,直接过滤指定的停用词。
        # sublinear_tf:,计算tf值采用亚线性策略。比如,我们以前算tf是词频,现在用1+log(tf)来充当词频。
        #max_df,过滤出现在超过max_df=0.5比例的句子中的词语,当他在全文档出现的频次过多>50%时我们认为他太过常见而不具备代表性
        # .vocabulary: dict类型,只使用特定的词汇,为了避免在测试集中出现训练集中没有出现的词汇而造成困扰所以一般会用这个,但是如果训练集足够大可以不用
        '''
        tfidfspace.tdm = vectorizer.fit_transform(bunch.contents)

    else:
        vectorizer = TfidfVectorizer(stop_words=stpwrdlst, sublinear_tf=True, max_df=0.5)
        '''
        #.stop_words=list类型,直接过滤指定的停用词。
        # sublinear_tf:,计算tf值采用亚线性策略。比如,我们以前算tf是词频,现在用1+log(tf)来充当词频。
        # max_df,过滤出现在超过max_df=0.5比例的句子中的词语,当他在全文档出现的频次过多>50%时我们认为他太过常见而不具备代表性
        '''
        tfidfspace.tdm = vectorizer.fit_transform(bunch.contents)
        tfidfspace.vocabulary = vectorizer.vocabulary_

    writebunchobj(space_path, tfidfspace)
    print("if-idf词向量空间实例创建成功!!!")


if __name__ == '__main__':
    stopword_path = "hit_stopwords.txt"
    bunch_path = "train_word_bag/train_set.dat"
    space_path = "train_word_bag/tfdifspace.dat"
    vector_space(stopword_path, bunch_path, space_path)

    bunch_path = "test_word_bag/test_set.dat"
    space_path = "test_word_bag/testspace.dat"
    train_tfidf_path = "train_word_bag/tfdifspace.dat"
    vector_space(stopword_path, bunch_path, space_path, train_tfidf_path)

执行后会在对应词袋文件中生成TF-IDF向量空间实例,嫌麻烦就不展示了。

第五步:训练模型

在sklearn中已经封装好的库直接调用就可以了。

from sklearn.linear_model import LogisticRegression
from sklearn.naive_bayes import MultinomialNB  # 导入多项式贝叶斯算法
from sklearn import metrics
from Tools import readbunchobj
import os

# 导入训练集
trainpath = "train_word_bag/tfdifspace.dat"
train_set = readbunchobj(trainpath)

# 导入测试集
testpath = "test_word_bag/testspace.dat"
test_set = readbunchobj(testpath)

# 训练分类器:输入词袋向量和分类标签,alpha:0.001 alpha越小,迭代次数越多,精度越高
clf = MultinomialNB(alpha=0.001).fit(train_set.tdm, train_set.label)
#clf = LogisticRegression(C=1000.0).fit(train_set.tdm, train_set.label)
print("训练完毕!!!")
# 预测分类结果
predicted = clf.predict(test_set.tdm)

print("预测完毕!!!")


# 计算分类精度:

def metrics_result(actual, predict):
    print('精度:{0:.3f}'.format(metrics.precision_score(actual, predict, average='weighted')))
    print('召回:{0:0.3f}'.format(metrics.recall_score(actual, predict, average='weighted')))
    print('f1-score:{0:.3f}'.format(metrics.f1_score(actual, predict, average='weighted')))


metrics_result(test_set.label, predicted)

之前理论介绍的是朴素贝叶斯模型,但是走到这一步发现朴素贝叶斯和TF-IDF的相适性并不好,至少逻辑回归比他更合适。但是都走到这一步我是不想换模型的。先试一下贝叶斯的效果。
在这里插入图片描述

再看看逻辑回归的效果:
在这里插入图片描述
精确度上全面溃败。但是你实际运行会发现贝叶斯运行的比逻辑回归要快很多,虽然精确度才是王道。

  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2021-11-23 12:20:39  更:2021-11-23 12:24:21 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/27 4:24:46-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码