使用python语言编写常见的文本分类算法

使用python语言编写常见的文本分类算法    自然语言处理中一个很常见的操作就是文本分类,比如一组新闻文本,通过分类模型,将新闻文本分为政治、体育、军事、娱乐、财经等等几大类。那么分类第一步就是文本向量化,前一篇博客讲了一些,本文可以说是前文的实践版本。本文主要介绍一些常见的文本分类模型,说是介绍,其实主要以代码和结果为主,并不会详细的介绍每个算法的思想、原理、推导过程等,那样的话,估计可以写一个7、8篇的系列了,另外我也发现很…

大家好,又见面了,我是你们的朋友全栈君。

       自然语言处理中一个很常见的操作就是文本分类,比如一组新闻文本,通过分类模型,将新闻文本分为政治、体育、军事、娱乐、财经等等几大类。那么分类第一步就是文本向量化,前一篇博客讲了一些,本文可以说是前文的实践版本。本文主要介绍一些常见的文本分类模型,说是介绍,其实主要以代码和结果为主,并不会详细的介绍每个算法的思想、原理、推导过程等,那样的话,估计可以写一个7、8篇的系列了,另外我也发现很多博客都是理论为主,代码非常少,给人的感觉就是这件事我弄明白了,但具体如何干不知道,讲的似乎很难、很神秘,没有相应代码,让人望而生畏。所以本文还是偏工程一些,阅读本文的同学希望已经有了这些文本分类算法的理论基础。先说说我用的数据,约20万短文本,包含8个大类,分别为:餐饮、交通、购物、娱乐、居家等,每个大类约25000条数据,文本平均20个字左右,最短的文本仅有2个字。如下面所示:

__label__1    天猫 超市 慕滋 五谷 无 添加 糖 粗粮 杂粮 消化 饼干 g 代 早餐 糕点
__label__1    天猫 超市 满 减 云南 红 提 kg 提子 葡萄 新鲜 水果
__label__1    天猫 超市 原装 进口 嘘 嘘 乐 成长 裤 纸尿裤 拉拉 裤 L19 片 Kg
__label__1    天猫 超市 卫龙 小 面筋 g 零食 辣条 辣片 麻辣 素食 豆干 制品 大刀 肉
__label__1    天猫 超市 康师傅 矿物质 水 ml 瓶 整箱 饮用水
__label__1    天猫 超市 红牛 维生素 功能 饮料 整箱 装 原味 型 ml 罐 箱
__label__1    天猫 超市 香楠 蛋羹 味 麻薯 夹心 麻 糬 糕点 休闲 零食 小吃 g
__label__1    天猫 超市 蒙牛 特仑苏 醇 纤 牛奶 ml 盒 平衡 搭档 平衡 好搭档
__label__1    天猫 超市 味全 每日 C 纯 果汁 胡萝卜 果蔬汁 ml16 截单
__label__1    天猫 超市 金 菜地 豆干 五香 茶 干 g 豆腐干 特色 休闲 零食 豆制品
__label__1    天猫 超市 新 希望 牛奶 香蕉 牛奶 ml 盒 箱 甜蜜 好 滋味
__label__1    天猫 超市 良品 铺子 爆浆 麻薯 抹 茶味 g 糕点 点心 零食 特产 小吃
__label__1    天猫 超市 森永 嗨 酸酸 哒 酸果 软糖 青 柠味 g 维 c 水果 糖果 零食
__label__1    天猫 超市 桂格 即食 纯 燕麦片 粗粮 原味 冲 饮 谷物 早餐 g 袋装
__label__1    天猫 超市 满 减 挪威 冰冻 青花鱼 柳 g 包 冷冻 海鲜 鱼肉 鲭 鱼
__label__1    天猫 超市 甘 竹牌 豆豉 鲮鱼 罐头 g 盒 下 饭菜 特产 小吃 休闲 食品
__label__1    天猫 超市 姚 太太 青口 梅 g 蜜饯 果脯 话梅 肉 梅子 青梅 酸甜 凉果
__label__1    天猫 超市 蒙牛 特仑苏 醇 纤 牛奶 ml 盒 平衡 搭档 平衡 好搭档

       很多文本内容都是淘宝体,也就是商品标题,当然上面仅仅是个示例。我这里已经分好词,并且为了方便后面使用fastText分类模型,已经按照fastText格式做了排版,也就是第一项__label__1是标签, 后面是文本正文,这个训练集需要人工标记好,这是一件费时费力的事情。下面是不同分类模型代码,因为加了注释,所以这里就不一一解释了。
import random
import fasttext
import numpy as np
import tensorflow as tf
from sklearn.svm import SVC
from sklearn.naive_bayes import MultinomialNB
from sklearn.neighbors import KNeighborsClassifier
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer

# 朴素贝叶斯算法
def nb_model(train, train_label, test, test_label):
    clf_model = MultinomialNB(alpha=0.01)
    clf_model.fit(train, train_label)
    predict_results = clf_model.predict(test)

    count = 0
    predict_list = predict_results.tolist()
    for i, pred in enumerate(predict_list):
        if (pred == test_label[i]):
            count += 1

    print("nb_model_precision_score: " + str(float(count) / len(predict_list)))


# K近邻算法
def knn_model(train, train_label, test, test_label):
    knn_model = KNeighborsClassifier(n_neighbors=8)
    knn_model.fit(train, train_label)
    predict_results = knn_model.predict(test)

    count = 0
    predict_list = predict_results.tolist()
    for i, pred in enumerate(predict_list):
        if (pred == test_label[i]):
            count += 1

    print("knn_model_precision_score: " + str(float(count) / len(predict_list)))
    

# 支持向量机算法
def svm_model(train, train_label, test, test_label):
    svm_clf = SVC(kernel="linear", verbose=False)
    svm_clf.fit(train, train_label)
    predict_results = svm_clf.predict(test)

    count = 0
    predict_list = predict_results.tolist()
    for i, pred in enumerate(predict_list):
        if (pred == test_label[i]):
            count += 1

    print("svm_model_precision_score: " + str(float(count) / len(predict_list)))
        

# 使用传统方法的文本分类
def text_classification():
    count = 0
    test_text_list = []
    train_text_list = []
    test_label_list = []
    train_label_list = []
    total_text_list = []
    total_label_list = []

    print("start loading data...")
    finput = open("data/filter_total_half.txt", encoding='utf-8')
    for line in finput:
        count += 1
        text_array = line.split("\t", 1)
        if (len(text_array) != 2):
            continue

        # 保存全部样本
        total_text_list.append(text_array[1])
        total_label_list.append(text_array[0])

        # 划分训练集和测试集
        probability = random.random()
        if (probability > 0.2):
            train_text_list.append(text_array[1])
            train_label_list.append(text_array[0])
        else:
            test_text_list.append(text_array[1])
            test_label_list.append(text_array[0])
    finput.close()
    print("load data is finished...")

    print("start building vector model...")
    # 构建词典
    vec_total = CountVectorizer()
    vec_total.fit_transform(total_text_list)

    # 基于构建的词典分别统计训练集/测试集词频, 即每个词出现1次、2次、3次等
    vec_train = CountVectorizer(vocabulary=vec_total.vocabulary_)
    tf_train = vec_train.fit_transform(train_text_list)

    vec_test = CountVectorizer(vocabulary=vec_total.vocabulary_)
    tf_test = vec_test.fit_transform(test_text_list)

    # 进一步计算词频-逆文档频率
    tfidftransformer = TfidfTransformer()
    tfidf_train = tfidftransformer.fit(tf_train).transform(tf_train)
    tfidf_test = tfidftransformer.fit(tf_test).transform(tf_test)
    print("building vector model is finished...")

    # 朴素贝叶斯算法
    nb_model(tfidf_train, train_label_list, tfidf_test, test_label_list)
    # K近邻算法
    knn_model(tfidf_train, train_label_list, tfidf_test, test_label_list)
    # 支持向量机算法
    svm_model(tfidf_train, train_label_list, tfidf_test, test_label_list)
    print("building predict model is finished...")
    
    
# 使用fastText的文本分类
def fastText_model():
    foutput_test = open("data/data_test.txt", 'w', encoding='utf-8')
    foutput_train = open("data/data_train.txt", 'w', encoding='utf-8')
    with open("data/filter_total_half.txt", encoding='utf-8') as finput:
        for line in finput:
            probability = random.random()
            if (probability > 0.2):
                foutput_train.write(line.strip() + "\n")
            else:
                foutput_test.write(line.strip() + "\n")
    foutput_train.flush()
    foutput_train.close()
    foutput_test.flush()
    foutput_test.close()
    
    classifier = fasttext.supervised("data/data_train.txt", "data/cooking_fasttext_bkk.model", 
                          label_prefix="__label__", lr=0.25, dim=100,
                          silent=False, epoch=25, word_ngrams=3, loss="hs", bucket=2000000)
    
    result = classifier.test("data/data_test.txt")
    print(result.precision)


if __name__ == '__main__':
    print("\n传统方法文本分类...")
    text_classification()
    print("\n----------------------------------------------\n")
    print("FastText文本分类...")
    fastText_model()

       程序运行结果如下:

使用python语言编写常见的文本分类算法

       我还写了一个基于卷积神经网络的版本,修改自github,由于公司也有在用,这里就不把代码贴出来了。总体看,cnn的准确度最高,fastText次之。不过基于cnn的方法,需要事先训练词向量,训练过程也比较慢。而传统方法,如svm,准确度达0.95,已经很高了,从这一点也说明,不管是基于深度学习的卷积神经网络分类方法,还是传统的分类方法,其实模型反而是其次,最重要的是数据集的质量,模型选择和模型调参,对最终精度提升都是小幅度的,而数据集的质量高低则是精度提升的瓶颈,有时真得不怕麻烦,整理出一份高质量的数据集,才能训练出精度更准、召回更高的模型。看到这里,是不是很多同学觉得文本分类其实没什么神秘的,有现成的训练框架使用,如:sklearn,还有那么多文献资料可供查阅,唯独没有适合自己业务的训练集,整理训练集,这可能是整个模型训练过程中最花时间的事情了。当然,这里面也涉及很多模型调参细节,需要深入算法原理才能真正玩转。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/134689.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • c++虚函数详解(你肯定懂了)

    c++虚函数详解(你肯定懂了)转自:c++虚函数 大牛的文章,就是通俗易懂,言简意赅。前言C++中的虚函数的作用主要是实现了多态的机制。关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数。这种技术可以让父类的指针有“多种形态”,这是一种泛型技术。所谓泛型技术,说白了就是试图使用不变的代码来实现可变的算法。比如:模板技术,RTTI技术,虚函数技术,要么是试图做到在编译时决议…

    2022年7月26日
    10
  • 详细AutoEventWireup <@ Page language=c# AutoEventWireup=”false”和“True”>的研究

    详细AutoEventWireup <@ Page language=c# AutoEventWireup=”false”和“True”>的研究@Page里面的属性是ASP.NET页面中最基础的组成部分。可也包涵了很多麻烦在里面,因为种种原因导致必须研究一下这个属性AutoEventWireupAutoEventWireup用我的理解方式是这样:(Auto解释是自动,Event解释是事件,Wire解释关联结构模式,up解释是在上面)个人理解的方式来推断这个属性所实现的功能。首先,从浏览器触发的事件不能理科在本地得

    2022年5月27日
    34
  • 函数模板参数(函数参数在哪)

    C++模板实参的省略下面列举的几种情况不能省略模板实参:1)从模板函数实参表获得的信息有矛盾之处。template<typenameT>voidfun(Tconst&a,Tconst&b);但是你调用时却是fun(250,250.4);那你就必须写成fun<int>(250,250.4);2)需要获得特定类型的返回值,而不管参数…

    2022年4月15日
    59
  • 编程中的卫语句

    什么是卫语句在《阿里巴巴Java开发手册》中提到,多层条件语句建议使用卫语句、策略模式、状态模式等方式重构。那么,什么是卫语句呢?在中文维基百科中是这样介绍的在计算机程序设计中,卫(guard)是布尔表达式,其结果必须为真,程序才能执行下去。卫语句(guardcode或guardclause)用于检查先决条件。卫语句的用途,例如:引用(reference)使用前检查是否为空引用;处置模式使用一个布尔域,使得释放资源操作成为幂等运算,即多次释放资源等效于只释放一次。卫语句可用于子进程的提前

    2022年4月7日
    332
  • 1、win10下的python3.5.4安装

    现在越来越多人入坑python了,当然我也不例外。作为一个java程序员的我,在空余时间就慢慢学习python了 。第一件事就是安装Python啦。(主要以Python 3.5.4为例)一、官网下载安装包官网地址:https://www.python.org/downloads/windows/ 都说越新越好嘛,其实我觉得都差不多,但是3.6跟3.5还是有点区别的嘛,所以我…

    2021年11月30日
    61
  • 防止黑客入侵网站

    防止黑客入侵网站你的网站是否经常被黑客入侵?站长怎样防止自己的网站被黑客入侵?黑客入侵现在最普遍的是利用注入来到达入侵的目的。站长怎样防止自己的网站被黑客入侵?以下是我的经验之谈,大家可以参考下!  黑客入侵的网站首选的大部分都是流量高的网站,怎样避免呢?个人认为必要做好已下步骤!  一:注入漏洞必须补上  什么是注入漏洞,怎么产生的,这些我也不好意思在这说了,百度上很多关于这方面的介绍。比如说你的网

    2022年7月15日
    20

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号