机器学习—— SVM分类垃圾短信

本文介绍了一个基于Python的垃圾短信分类项目,利用scikit-learn和jieba库,通过SVM进行文本分类。文章详细阐述了数据处理、特征提取、SVM线性和非线性分类器的训练及评估,展示了模型在训练集和测试集上的性能。
摘要由CSDN通过智能技术生成

机器学习—— SVM分类算法

垃圾短信分类问题

Python语言凭借其强大的特性,其众多的外部库支持下,在机器学习和数据挖掘等领域发挥着强大的作用。本文基于python的机器学习库scikit-learn和完备的中文分词工具jieba 来对垃圾短信信息进行分类。完整代码位于Github(https://github.com/ZPdesu/Junk-Message-Classifier-sklearn)

分类样本

垃圾短信分类的样本数据分为带标签数据和不带标签数据。其中带标签数据用于模型训练和测试,不带标签数据用于线上模拟。样本数据类型如下

训练数据

0 xx计算机单招班彭雯同学表示将不负学校的培育
0 但是没有首都的在CBD一家好吃
0 今天给大家介绍一款Bookbook电脑包
1 亲爱的家长朋友你们好,我是张老师:新学期现在开始报名啦!本学期对老生家长的义务宣传有个回馈活动,老生带一个新生报名,赠送老生二百元兴趣
0 浙江宁波市马路突然爆裂
1 各位亲们好,新世纪奉节店迎接三八节,贝因美奶粉全场x.x折,欢迎惠额。活动时间x月x日至x月x日。
0 一架小型飞机在伦敦西南部一停车场坠毁

测试数据

刚刚坐电梯突然脚下踏板一软
佰特机器人俱乐部第七期大课堂在昨天圆满落幕了

训练集的标签域0代表是正常短信,1代表垃圾短信

  • 可以看出短信分类的最大问题在于语意的理解。对中英文数字夹杂的语句进行分词,去除无意义的词汇,生成语意明确的等长词向量显得尤为重要。在词向量的特征提取过程中也可以采用TF-IDF等方式,来权衡每个词的相对重要性。

1 数据初步处理

1.1 数据集读取和存储

原始短信数据共有数十万条,为了便于快速检验模型正确性,我们暂且取出其中的10000条左右用于训练和验证。对于大数据量情况,则可以使用数据库来代替文件,以同样的方式进行训练判别。处理前的第一步需要从存储信息的原始txt文档中,分割出文本域和标签域。作为content 和label分别存入对应的json文件中。

  • 以下代码用于将Raw_data文件夹下的txt文档信息转入对应的json文件中。
# -*- coding: utf-8 -*-
from numpy import *
import json

# 加载原始数据,进行分割
def load_message():
    content = []
    label = []

    with open('RawData/message.txt') as fr:
        for i in range(10000):
            line = fr.readline()
            lines.append(line)
        num = len(lines)
        for i in range(num):
            message = lines[i].split('\t')
            label.append(message[0])
            content.append(message[1])
    return num, content, label

# 将分割后的原始数据存到json
def data_storage(content, label):
    with open('RawData/train_content.json', 'w') as f:
        json.dump(content, f)
    with open('RawData/train_label.json', 'w') as f:
        json.dump(label, f)

if '__main__' == __name__:
    num, content, label = load_message()
    data_storage(content, label)

1.2 词向量生成(特征提取)

数据读取后下一步需要进行文本域的分词,在使用jieba进行精准模式分词之前需要对一些非规范数据进行,如对电话号码xxx,特殊字符&“】等进行统一转换。对一些反复出现的无意义词汇,如‘的’等当用词进行筛选。
这里首先介绍一下jieba分词的样式规范
In

# encoding=utf-8
import jieba

seg_list = jieba.cut("我来到北京清华大学", cut_all=True)
print("Full Mode: " + "/ ".join(seg_list))  # 全模式

seg_list = jieba.cut("我来到北京清华大学", cut_all=False)
print("Default Mode: " + "/ ".join(seg_list))  # 精确模式

seg_list = jieba.cut("他来到了网易杭研大厦")  # 默认是精确模式
print(", ".join(seg_list))

seg_list = jieba.cut_for_search("小明硕士毕业于中国科学院计算所,后在日本京都大学深造")  # 搜索引擎模式
print(", ".join(seg_list))

Out

【全模式】: 我/ 来到/ 北京/ 清华/ 清华大学/ 华大/ 大学

【精确模式】: 我/ 来到/ 北京/ 清华大学

【新词识别】:他, 来到, 了, 网易, 杭研, 大厦    (此处,“杭研”并没有在词典中,但是也被Viterbi算法识别出来了)

【搜索引擎模式】: 小明, 硕士, 毕业, 于, 中国, 科学, 学院, 科学院, 中国科学院, 计算, 计算所, 后, 在, 日本, 京都, 大学, 日本京都大学, 深造

生成词向量方式是建立词表,通过统计词表中词汇的出现次数来构建向量。但这种构建向量的方式,会导致每个词的重要过于均衡,无法体现词向量中词汇的重要性,导致分类结果不理想。因此改进中采用了TF-IDF方式来构建词向量。

  • 这里要注意,词向量中的元素是通过TF-IDF方式生成的,因此每个元素转换成了float型。因为整个训练集的词向量数量庞大,为了便于后续处理可以先将其存储为csr型的稀疏矩阵到mtx文件中,便于后续模型训练和验证。
# -*- coding: utf-8 -*-
import numpy as np
import jieba
import jieba.posseg as pseg
import sklearn.feature_extraction.text
import json
import re
from scipy import sparse, io
import load_data

# 将连续的数字转变为长度的维度
def process_cont_numbers(content):
    digits_features = np.zeros((len(content), 16))
    for i, line in enumerate(content):
        for digits in re.findall(r'\d+', line):
            length = len(digits)
            if 0 < length <= 15:
                digits_features[i, length-1] += 1
            elif length > 15:
                digits_features[i, 15] += 1
    return process_cont_numbers

# 正常分词,非TFID
class MessageCountVectorizer(sklearn.feature_extraction.text.CountVectorizer):
    def build_analyzer(self):
        
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值