项目代码见 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的文本分类的更多相关文章

  1. 基于Text-CNN模型的中文文本分类实战 流川枫 发表于AI星球订阅

    Text-CNN 1.文本分类 转眼学生生涯就结束了,在家待就业期间正好有一段空闲期,可以对曾经感兴趣的一些知识点进行总结. 本文介绍NLP中文本分类任务中核心流程进行了系统的介绍,文末给出一个基于T ...

  2. 基于Text-CNN模型的中文文本分类实战

    Text-CNN 1.文本分类 转眼学生生涯就结束了,在家待就业期间正好有一段空闲期,可以对曾经感兴趣的一些知识点进行总结. 本文介绍NLP中文本分类任务中核心流程进行了系统的介绍,文末给出一个基于T ...

  3. Chinese-Text-Classification,用卷积神经网络基于 Tensorflow 实现的中文文本分类。

    用卷积神经网络基于 Tensorflow 实现的中文文本分类 项目地址: https://github.com/fendouai/Chinese-Text-Classification 欢迎提问:ht ...

  4. 机器学习实战笔记(Python实现)-05-支持向量机(SVM)

    --------------------------------------------------------------------------------------- 本系列文章为<机器 ...

  5. class-支持向量机SVM全析笔记

    support vector machines,SVM是二类分类模型.定义在特征空间上间隔最大的线性分类器,由于包括核技巧实质上成为非线性分类器.学习策略是间隔最大化,可形式化为求解凸二次规划问题(c ...

  6. 走过路过不要错过 包你一文看懂支撑向量机SVM

    假设我们要判断一个人是否得癌症,比如下图:红色得癌症,蓝色不得. 看一下上图,要把红色的点和蓝色的点分开,可以画出无数条直线.上图里黄色的分割更好还是绿色的分割更好呢?直觉上一看,就是绿色的线更好.对 ...

  7. 基于Naive Bayes算法的文本分类

    理论 什么是朴素贝叶斯算法? 朴素贝叶斯分类器是一种基于贝叶斯定理的弱分类器,所有朴素贝叶斯分类器都假定样本每个特征与其他特征都不相关.举个例子,如果一种水果其具有红,圆,直径大概3英寸等特征,该水果 ...

  8. 8.支撑向量机SVM

    1.什么是SVM 下面我们就来介绍一些SVM(Support Vector Machine),首先什么是SVM,它是做什么的?SVM,中文名是支撑向量机,既可以解决分类问题,也可以解决回归问题,我们来 ...

  9. 模式识别笔记3-支持向量机SVM

    1. 线性SVM 对两类点的划分问题,这里对比下逻辑回归和SVM的区别: 逻辑回归的思想是,将所有点到决策平面的距离作为损失来进行训练,目标是到决策平面的距离和最小 SVM的思想是,只关注支持向量(图 ...

随机推荐

  1. springboot之additional-spring-configuration-metadata.json自定义提示

    springboot之additional-spring-configuration-metadata.json自定义提示 简介 additional-spring-configuration-met ...

  2. 迁移桌面程序到MS Store(10)——在Windows S Mode运行

    首先简单介绍Windows 10 S Mode,Windows在该模式下,只能跑MS Store里的软件,不能通过其他方式安装.好处是安全有保障,杜绝一切国产流氓软件.就像iOS一样,APP进商店都需 ...

  3. 深入GPU硬件架构及运行机制

    目录 一.导言 1.1 为何要了解GPU? 1.2 内容要点 1.3 带着问题阅读 二.GPU概述 2.1 GPU是什么? 2.2 GPU历史 2.2.1 NV GPU发展史 2.2.2 NV GPU ...

  4. 从入门到入土的JS 随笔day01

    js 的全称是javascript ,JavaScript一种直译式脚本语言,是一种动态类型.弱类型.基于原型的语言,内置支持类型. 它的解释器被称为JavaScript引擎,为浏览器的一部分,广泛用 ...

  5. [python] - profilers性能分析器

    1. 性能分析器: profile, hotshot, cProfile 2. 作用: 测试函数的执行时间 每次脚本执行的总时间

  6. JS执行机制详解,定时器时间间隔的真正含义

     壹 ❀ 引 通过结果倒推过程是我们常用的思考模式,我在上一篇学习promise笔记中,有少量关于promise执行顺序的例子,通过倒推,我成功让自己对于js执行机制的理解一塌糊涂,js事件机制,事件 ...

  7. 【Redis】主从复制

    一.概述 1.redis的复制功能是支持多个数据库之间的数据同步.一类是主数据库(master)一类是从数据库(slave),主数据库可以进行读写操作,当发生写操作的时候自动将数据同步到从数据库,而从 ...

  8. 适合C++のOIer平日写题的开场模板

    上面的#define还是较充足的,快读模板也有,freopen也提前打好了,比较适合OIer(C++)平时刷题和考试的开场. (纯原版仅供SJZEZのORZ队&AFO队使用) (您老把开头的注 ...

  9. 理解Yarn的执行流程和组件作用

    Yarn引入案例 1.学生找院长报到,院长给学生一个学号 2.院长比较忙,继续找主任处理学生事务 3.系主任找院办给学生分配资源(书本) 4.主任找张老师教授java 5.张老师给学生安排座位 6.学 ...

  10. java解决回文数

    递归解决palindrome问题 如果String仅仅只是一个或者0个字符,则它就是palindrome 否则比较字符串第一个和最后一个字符 如果第一个和最后一个字符不同,那么就不是palindrom ...