Python-基于向量机SVM的文本分类
项目代码见 Github:
1.算法介绍
2.代码所用数据
详情参见http://qwone.com/~jason/20Newsgroups/
文件结构
├─doc_classification.py 
├─stopwords.txt 
├─vocabulary.txt 
├─train.data 
├─train.label 
├─train.map 
├─test.data 
├─test.label 
└─test.map
python代码
需要安装的库:
pandas, liblinearutil
注:Windows平台下 liblinearutil 安装包(32/64)
# doc_classification.py
import pandas as pd
import math
from liblinearutil import *
import time
# 读取数据
def loadOriginData(src='train'):
    # train.data
    dataSrc = r'%s.data' % src
    # train.label
    labelSrc = r'%s.label' % src
    label = pd.read_table(labelSrc, sep=' ', names=['label'])
    # train.map
    mapSrc = r'%s.map' % src
# 每个文档拥有的terms
    doc2term = {}
    # 每个term出现在哪些文档
    term2doc = {}
    # 每个类别下有哪些docs
    cate2docs = {}
    # TF值
    TF = {}
    with open(dataSrc, 'r') as f:
        for line in f:
            str_docIdx, str_wordIdx, str_cnt = line.split()
            docIdx = int(str_docIdx)
            wordIdx = int(str_wordIdx)
            cnt = int(str_cnt)
            # update 数据结构
            doc2term.setdefault(docIdx, []).append(wordIdx)
            term2doc.setdefault(wordIdx, []).append(docIdx)
            TF.setdefault(docIdx, {})[wordIdx] = cnt
    # 统计每个类别下有哪些文档
    with open(labelSrc, 'r') as f:
        for line_index, line in enumerate(f, 1):
            labelVal = int(line.strip())
            cate2docs.setdefault(labelVal, []).append(line_index)
    return TF, doc2term, term2doc, cate2docs, label
#  特征选择
def featureSel(doc2term, term2doc, cate2docs):
    # CHI衡量的是特征项ti和类别Cj之间的关联程度, A,B, C, D是四个统计量
    CHI_cat2term = {}
    # N:total  number of documents
    N = len(doc2term)
    # A + B + C + D = N
    # A: term出现在某类别中的文档总数
    A = {}
    # B: term出现在除某类别外的其他文档数
    B = {}
    # C:  该类别中不包含term的文档总数
    C = {}
    # D: 其他类别中不包含term的文档总数
    D = {}
    DF = {}
    # 所有类别
    categories = list(cate2docs.keys())
    # 停用词词汇表
    stopwords = {}
    stopwordsSrc = r'stopwords.txt'
    with open(stopwordsSrc) as f:
        for line in f:
            stopwords[line.strip()] = True
    # 训练数据数据词汇表
    vocSrc = r'vocabulary.txt'
    voc = pd.read_table(vocSrc, names=['voc'])
    # 保存所有的特征
    features = set()
    # 计算一个类别标签下各个词的CHI
    for category in categories:
        # 属于第category类的文档为docs
        docs = cate2docs[category]
        sumVal = 0
        for term in term2doc:
            # 如果是停用词, 则将CHI置零
            if stopwords.get(voc['voc'][term - 1], False):
                CHI_cat2term.setdefault(category, {})[term] = 0
                continue
            # 属于某类且包含term
            AVal = len(set(term2doc[term]).intersection(set(docs)))
            # 不属于某类但包含term
            BVal = len(term2doc[term]) - AVal
            # 属于某类,但不包含term
            CVal = len(docs) - AVal
            # 不属于某类, 不包含term
            DVal = N - AVal - BVal - CVal
            CHIVal = N * (AVal * DVal - CVal * BVal)**2 / ((AVal + CVal) * (BVal + DVal) * (AVal + BVal) * (CVal + DVal))
            # CHIVal = math.log(AVal * N / ((AVal + CVal) * (AVal + BVal)))
            A.setdefault((term, category), AVal)
            B.setdefault((term, category), BVal)
            C.setdefault((term, category), CVal)
            D.setdefault((term, category), DVal)
CHI_cat2term.setdefault(category, {})[term] = CHIVal
            DF[term] = AVal + BVal
            sumVal += CHIVal
        # 选出类别中CHI高于平均值的词
        terms = CHI_cat2term[category]
        meanVal = sumVal / len(terms)
        for term in terms:
            if CHI_cat2term[category][term] > meanVal:
                features.add(term)
    # for feature in features:
    #     print(voc['voc'][feature])
    print('There are %d features in VSM model.\n' % len(features))
    return features,  DF
def buildSVMData(TF, DF, features, N, label, cate2docs, doc2terms):
    isFeatures = dict(zip(features, [True] * len(features)))
    categories = list(cate2docs.keys())
    # 如果是训练样本, 则计算归一化缩放因子,并返回
    # y: label值
    y = [0] * N
    # x: 稀疏矩阵
    x = []
    for i in range(N):
        x.append({})
    for category in categories:
        for doc in cate2docs[category]:
            # 给y进行标记类别
            y[doc - 1] = label.iat[doc - 1, 0]
            scale_factor = -100
            for term in doc2terms[doc]:
                if isFeatures.get(term, False):  # 如果term是特征
                    # TF值
                    TFVal = TF[doc].get(term, 0)
                    # TF-IDF值
                    tf_idf = TFVal * math.log(N / DF[term])
                    x[doc - 1][term] = tf_idf
                    # 更新特征最大值
                    if scale_factor < tf_idf:
                        scale_factor = tf_idf
            alpha = 0
            # 按一篇文档中特征词最大的tf-idf, 对该文档中的所有特征词进行归一化
            for term in doc2terms[doc]:
                if isFeatures.get(term, False):  # 如果term是特征
                    # x[doc - 1][term] = alpha + (1 - alpha) * x[doc - 1][term] / scale_factor
                    x[doc - 1][term] /= scale_factor
    print("Data for SVM has been built.\n")
    return x, y
# 计算DF
def getDF(doc2term, term2doc, cate2docs):
    DF = {}
    for term in term2doc:
        DF[term] = len(term2doc[term])
    return DF
if __name__ == '__main__':
    start = time.time()
    # # 主程序
    TF, doc2term, term2doc, cate2docs, label = loadOriginData()
    # 特征选择
    features, DF = featureSel(doc2term, term2doc, cate2docs)
    # 读取数据(train.data)
    TF, doc2term, term2doc, cate2docs, label = loadOriginData()
    # 特征选择
    features, DF = featureSel(doc2term, term2doc, cate2docs)
    # build SVM model
    x, y = buildSVMData(TF, DF, features, len(doc2term), label, cate2docs, doc2term)
    # 读取测试数据(test.data)
    TF_test, doc2term_test, term2doc_test, cate2docs_test, label_test = loadOriginData(src='test')
    DF_test = getDF(doc2term_test, term2doc_test, cate2docs_test)
    # TF, DF, features, len(doc2term), label, cate2docs, doc2term, scales)
    x_test, y_test = buildSVMData(TF_test, DF_test, features, len(doc2term_test), label_test, cate2docs_test, doc2term_test)
print("处理数据使用了 %s s时间。\n" % (time.time() - start))
    # # 调用 liblinear 库进行分类
    prob = problem(y, x)
    param = parameter('-s 0 -c 4 -B 1')
    # 训练
    m = train(prob, param)
    # 预测test.data
    p_label, p_acc, p_vals = predict(y_test, x_test, m, '-b 1')
    # 评价
    ACC, MSE, SCC = evaluations(y_test, p_label)
    print('ACC:\n', ACC)
    print('MSE', MSE)
    print('SCC', SCC)
    # 统计每类中错误率
    categoriesErrs = {}
    for doc_index, doc_label in enumerate(y_test):
        if doc_label != int(p_label[doc_index]):
            cateogory = label_test.iat[doc_index, 0]
            categoriesErrs.setdefault(cateogory, []).append(doc_index + 1)
    # with open('outcome.txt', 'wb') as f:
    print("错误分类的样本为:\n")
    for categoryErr in categoriesErrs:
        numOfErr = len(categoriesErrs[categoryErr])
        print('第%d类共 %d样本, 被错分的个数为 %d, 比例为 %f %%.\n' % (categoryErr,len(cate2docs_test[categoryErr]), numOfErr, numOfErr/len(cate2docs_test[categoryErr])))
end = time.time()
    print("Total time cost is  %s s.\n" % (end - start))
Python-基于向量机SVM的文本分类的更多相关文章
- 基于Text-CNN模型的中文文本分类实战 流川枫  发表于AI星球订阅
		
Text-CNN 1.文本分类 转眼学生生涯就结束了,在家待就业期间正好有一段空闲期,可以对曾经感兴趣的一些知识点进行总结. 本文介绍NLP中文本分类任务中核心流程进行了系统的介绍,文末给出一个基于T ...
 - 基于Text-CNN模型的中文文本分类实战
		
Text-CNN 1.文本分类 转眼学生生涯就结束了,在家待就业期间正好有一段空闲期,可以对曾经感兴趣的一些知识点进行总结. 本文介绍NLP中文本分类任务中核心流程进行了系统的介绍,文末给出一个基于T ...
 - Chinese-Text-Classification,用卷积神经网络基于 Tensorflow 实现的中文文本分类。
		
用卷积神经网络基于 Tensorflow 实现的中文文本分类 项目地址: https://github.com/fendouai/Chinese-Text-Classification 欢迎提问:ht ...
 - 机器学习实战笔记(Python实现)-05-支持向量机(SVM)
		
--------------------------------------------------------------------------------------- 本系列文章为<机器 ...
 - class-支持向量机SVM全析笔记
		
support vector machines,SVM是二类分类模型.定义在特征空间上间隔最大的线性分类器,由于包括核技巧实质上成为非线性分类器.学习策略是间隔最大化,可形式化为求解凸二次规划问题(c ...
 - 走过路过不要错过 包你一文看懂支撑向量机SVM
		
假设我们要判断一个人是否得癌症,比如下图:红色得癌症,蓝色不得. 看一下上图,要把红色的点和蓝色的点分开,可以画出无数条直线.上图里黄色的分割更好还是绿色的分割更好呢?直觉上一看,就是绿色的线更好.对 ...
 - 基于Naive Bayes算法的文本分类
		
理论 什么是朴素贝叶斯算法? 朴素贝叶斯分类器是一种基于贝叶斯定理的弱分类器,所有朴素贝叶斯分类器都假定样本每个特征与其他特征都不相关.举个例子,如果一种水果其具有红,圆,直径大概3英寸等特征,该水果 ...
 - 8.支撑向量机SVM
		
1.什么是SVM 下面我们就来介绍一些SVM(Support Vector Machine),首先什么是SVM,它是做什么的?SVM,中文名是支撑向量机,既可以解决分类问题,也可以解决回归问题,我们来 ...
 - 模式识别笔记3-支持向量机SVM
		
1. 线性SVM 对两类点的划分问题,这里对比下逻辑回归和SVM的区别: 逻辑回归的思想是,将所有点到决策平面的距离作为损失来进行训练,目标是到决策平面的距离和最小 SVM的思想是,只关注支持向量(图 ...
 
随机推荐
- Linux 设置服务开机启动
			
首先来了解一下 service命令是Redhat Linux兼容的发行版中用来控制系统服务的实用工具,它以启动.停止.重新启动和关闭系统服务,还可以显示所有系统服务的当前状态. service +(自 ...
 - Unity Editor已停止工作
			
在更换系统之后,可能会出现打开刚安装好的Unity,显示Unity Editor已停止工作,这时候我们考虑是系统win7的问题.可以在原系统上升级,也可以重新安装,升级.文中所涉及到的软件,可在右侧加 ...
 - CopyOnWriteArrayList笔记
			
CopyOnWriteArrayList笔记 一.前言 Java 5.0 在java.util.concurrent 包中提供了多种并发容器类来改进同步容器的性能. ConcurrentHashMap ...
 - 【朝花夕拾】Handler篇(二)
			
前言 一年前写过一篇文章[朝花夕拾]Handler篇,随着这一年来对Handler更多的认识和理解,本文对Handler知识点做的一些补充. 一.为什么要引入Handler Handler的主要作用是 ...
 - Django之使用中间件解决前后端同源策略问题
			
问题描述 前端时间在公司的时候,要使用angular开发一个网站,因为angular很适合前后端分离,所以就做了一个简单的图书管理系统来模拟前后端分离. 但是在开发过程中遇见了同源策略的跨域问题,页面 ...
 - 基于Taro与Typescript开发的网易云音乐小程序
			
基于Taro与网易云音乐api开发,技术栈主要是:typescript+taro+taro-ui+redux,目前主要是着重小程序端的展示,主要也是借此项目强化下上述几个技术栈的使用,通过这个项目也可 ...
 - 深度解密Go语言之 scheduler
			
目录 前置知识 os scheduler 线程切换 函数调用过程分析 goroutine 是怎么工作的 什么是 goroutine goroutine 和 thread 的区别 M:N 模型 什么是 ...
 - spring-cloud-kubernetes背后的三个关键知识点
			
在<你好spring-cloud-kubernetes>一文中,对spring-cloud-kubernetes这个SpringCloud官方kubernetes服务框架有了基本了解,今天 ...
 - H5调用相机和相册更换头像
			
需求:H5调用手机的相机和相册从而实现更换头像的功能 这个功能是很常用的一个功能,因此做一个记录. 1.在头像img下加一个文件输入框 <input type="file" ...
 - POJ 2488 A Knight's Journey (DFS)
			
poj-2488 题意:一个人要走遍一个不大于8*8的国际棋盘,他只能走日字,要输出一条字典序最小的路径 题解: (1)题目上说的"The knight can start and end ...