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))

原文地址:https://www.cnblogs.com/btsn/p/10960730.html

时间: 2024-10-13 03:06:55

Python-基于向量机SVM的文本分类的相关文章

机器学习经典算法详解及Python实现---朴素贝叶斯分类及其在文本分类、垃圾邮件检测中的应用

摘要: 朴素贝叶斯分类是贝叶斯分类器的一种,贝叶斯分类算法是统计学的一种分类方法,利用概率统计知识进行分类,其分类原理就是利用贝叶斯公式根据某对象的先验概率计算出其后验概率(即该对象属于某一类的概率),然后选择具有最大后验概率的类作为该对象所属的类.总的来说:当样本特征个数较多或者特征之间相关性较大时,朴素贝叶斯分类效率比不上决策树模型:当各特征相关性较小时,朴素贝叶斯分类性能最为良好.另外朴素贝叶斯的计算过程类条件概率等计算彼此是独立的,因此特别适于分布式计算.本文详述了朴素贝叶斯分类的统计学

基于朴素贝叶斯分类器的文本分类算法

源代码下载:NaviveBayesClassify.rar Preface 文本的分类和聚类是一个比较有意思的话题,我以前也写过一篇blog<基于K-Means的文本聚类算法>,加上最近读了几本数据挖掘和机器学习的书籍,因此很想写点东西来记录下学习的所得. 在本文的上半部分<基于朴素贝叶斯分类器的文本分类算法(上)>一文中简单介绍了贝叶斯学习的基本理论,这一篇将展示如何将该理论运用到中文文本分类中来,具体的文本分类原理就不再介绍了,在上半部分有,也可以参见代码的注释. 文本特征向量

基于朴素贝叶斯的文本分类

前言:学习机器学习的过程意识到,数学是工科的基石.很多数学公式似懂非懂,因此有了这篇博客,想在学习每个模型的过程中搞懂其中的数学理论. 贝叶斯决策论 1.前置知识:先验概率与后验概率 先验概率P(B):根据以往经验和分析得到的概率 先验概率是一种常识性.经验性认知,比如抛硬币正反面的概率是1/2. 后验概率P(A|B):某个因素的到来影响了对某个结果发生可能性的判断 后验概率是基于已知,对结果发生的可能性一种推测. 比如:文本分类中,假设文章类别为3类,没有数据时,观测到类别c的概率是先验概率P

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

support vector machines,SVM是二类分类模型.定义在特征空间上间隔最大的线性分类器,由于包括核技巧实质上成为非线性分类器.学习策略是间隔最大化,可形式化为求解凸二次规划问题(convex quadratic programming).求解算法是求解凸二次规划的最优化算法. SVM学习方法分为线性可分支持向量机(linear support vector machine in linearly separable case).线性支持向量机(linear support v

基于Naive Bayes算法的文本分类

理论 什么是朴素贝叶斯算法? 朴素贝叶斯分类器是一种基于贝叶斯定理的弱分类器,所有朴素贝叶斯分类器都假定样本每个特征与其他特征都不相关.举个例子,如果一种水果其具有红,圆,直径大概3英寸等特征,该水果可以被判定为是苹果.尽管这些特征相互依赖或者有些特征由其他特征决定,然而朴素贝叶斯分类器认为这些属性在判定该水果是否为苹果的概率分布上独立的. 朴素贝叶斯分类器很容易建立,特别适合用于大型数据集,众所周知,这是一种胜过许多复杂算法的高效分类方法. 贝叶斯公式提供了计算后验概率P(X|Y)的方式: 其

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

假设我们要判断一个人是否得癌症,比如下图:红色得癌症,蓝色不得. 看一下上图,要把红色的点和蓝色的点分开,可以画出无数条直线.上图里黄色的分割更好还是绿色的分割更好呢?直觉上一看,就是绿色的线更好.对吧. 为啥呢?考虑下图,新来了一个黑色点,明显靠蓝色点更近,如果用黄线分割,却把它划分到了红色点这个类别里. 现在细想一下为什么绿线比黄线分隔效果更好? 黄色线太贴近蓝色点 绿色线到红色点群和蓝色点群距离大致相等.恰好位于两个点群中间的位置 由此我们就引申出了SVM的理论基础:使得距离决策边界最近的

支撑向量机 SVM(一)

本文总结支撑向量机的基础知识,加入一点个人的直观理解.个人比较不太喜欢照搬书里的东西,而是喜欢自己推导然后时不时闭上研究回忆,想方设法用自己的方式简单理解. 1. 分类支撑向量机         1.1 可分SVM与间隔最大化:                   对于二分类SVM,一种直观的理解就是要寻找一条有宽度的带子来分开两类数据,而不是一条线.为何要这样呢? 如果仅仅是一条线的话,那么例如上图中,这条边界并不唯一,那么模型的鲁棒性成问题.但是如果是找一条边界带,那么可能可以找到一条宽度最

基于朴素贝叶斯分类器的文本分类

实验要求 题目要求 1.用MapReduce算法实现贝叶斯分类器的训练过程,并输出训练模型: 2.用输出的模型对测试集文档进行分类测试.测试过程可基于单机Java程序,也可以是MapReduce程序.输出每个测试文档的分类结果: 3.利用测试文档的真实类别,计算分类模型的Precision,Recall和F1值. 2.实验环境 实验平台:VMware Workstation10 虚拟机系统:Suse11 集群环境:主机名master  ip:192.168.226.129 从机名slave1 

SVM-支持向量机(一)线性SVM分类

SVM-支持向量机 SVM(Support Vector Machine)-支持向量机,是一个功能非常强大的机器学习模型,可以处理线性与非线性的分类.回归,甚至是异常检测.它也是机器学习中非常热门的算法之一,特别适用于复杂的分类问题,并且数据集为小型.或中型的数据集. 这章我们会解释SVM里的核心概念.原理以及如何使用. 线性SVM分类 我们首先介绍一下SVM里最基本的原理.这里先看一张图: 这个是Iris数据集中的部分数据,可以看到这两个类别可以由一条直线很简单地直接分开(也可以说它们是线性可