K邻近算法实现短信文本分类

首先,导入需要的库

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2022/3/30 21:51

#导包
import warnings
from pandas import DataFrame, concat
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import jieba
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号
warnings.filterwarnings('ignore') #忽视警告

然后定义导入数据的函数。

def get_data(data_file):  #定义一个读取文件的函数
    """
    解析文本数据
    :param data_file: 数据文件
    :return:  分词结果,标记
    """
    target = []
    data = []
    with open(data_file, 'r', encoding='utf-8') as f:  #打开文件
        for line in f.readlines():  #按行读取
            line = line.strip().split("\t")   #滤除行首行尾空格,以\t作为分隔符,对这行进行分解
            if len(line) == 1:
                continue
            target.append(int(line[0]))     #\t之前的是标签
            data.append(line[1])      #\t之后的是文本数据
        # data = list(map(jieba.lcut, data))
        # data = [" ".join(d) for d in data]
    return data, target   #返回文本和标签列表

# 导入数据
print('正在导入数据!')
DATAFILE = "data.txt"
data, target = get_data(DATAFILE)   #读取数据
data = DataFrame(data)   #将文本转换化成表格形式
target = DataFrame(target)   #将标签转化成表格形式
df = concat([data, target], axis=1)   #拼接为一个表格
df.columns = ['text', 'label']
print('数据导入完成!显示前5行数据:')
print(df.head(5))

对数据进行预处理。预处理内容包括用jieba库将句子分词处理成单词,然后再将单词转换为词向量,进而将每句话转换成了一个向量,便于输入网络进行训练。

# 数据预处理
print('开始数据预处理')
print('1、按标签打乱训练数据!')
df = df.sample(frac=1)  # 将正面文本数据与负面文本数据进行打乱
print('数据已按标签打乱!显示前5行:')
print(df.head(5))   #显示前5行

# 分词处理
import jieba
word_cut = lambda x: jieba.lcut(x)
print('2、分词处理!')
df['words'] = df["text"].apply(word_cut)   #分词处理
print('分词已完成!显示前5行:')
print(df.head())

# 去除停用词
with open("hit_stopwords.txt", "r", encoding='utf-8') as f:
    stopwords = f.readlines()

stopwords_list = []
for each in stopwords:
    stopwords_list.append(each.strip('\n'))

# 添加自定义停用词
stopwords_list += ["…", "也", ".", "都", "是", "而", "了"," "]

def remove_stopwords(ls):  # 去除停用词
    return [word for word in ls if word not in stopwords_list]

print('3、去除停用词处理!')
df['去除停用词后的数据'] = df["words"].apply(lambda x: remove_stopwords(x))
print('去除停用词完成!显示前5行:')
print(df.head(5))

# 词词向量处理
from gensim.models.word2vec import Word2Vec
x = df["去除停用词后的数据"]    #处理对象是去除停用词后的数据
# 训练 Word2Vec 浅层神经网络模型
w2v = Word2Vec(vector_size=300,  # 是指特征向量的维度,默认为100。
               min_count=10)  # 可以对字典做截断. 词频少于min_count次数的单词会被丢弃掉, 默认值为5。
w2v.build_vocab(x)
w2v.train(x,
          total_examples=w2v.corpus_count,
          epochs=20)
# 保存 Word2Vec 模型及词向量
w2v.save('w2v_model.pkl')

# 将文本转化为向量
def average_vec(text):
    vec = np.zeros(300).reshape((1, 300))  #每个单词对应一个1行300列的向量
    for word in text:
        try:
            vec += w2v.wv[word].reshape((1, 300))  #每句话的向量等于每个单词的向量相加
        except KeyError:
            continue
    return vec

# 将词向量保存为 Ndarray
print('4、词向量处理!')
x_vec = np.concatenate([average_vec(z) for z in x])  #把训练数据处理成词向量
y = df['label'].values
print('词向量处理完成!')
print('数据预处理完成!')

接下来开始训练我们的网络,这里使用的是sklearn中的K邻近算法。

#划分训练集,测试集
from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test = train_test_split(x_vec,y,test_size=0.3)

####定义模型
from sklearn.metrics import accuracy_score
from sklearn.metrics import mean_squared_error
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split

def train(k=5):  #定义训练函数
    # 创建分类器
    clf = KNeighborsClassifier(n_neighbors=k)  #k取5
    # 训练数据
    clf.fit(X_train, y_train)
    # 测试数据
    print('训练完成!')
    print('开始在验证集测试准确率!')
    predictions = clf.predict(X_test)
    print('Accuracy:', accuracy_score(y_test, predictions))
    return clf,predictions

print('正在训练模型!')
clf,predictions=train(k=6)

模型训练好后,我们拿来测试。

这里使用了两种测试方法,mode=1时我们使用手动输入的方式进行测试 ,这样方便演示这个模型的功能。mode=2时我们可以直接使用test.txt文件中的数据进行识别,并计算准确率和识别消耗的时间。

num=10  #手动输入条数
def one_pridect(text):
    words = word_cut(text)
    words = remove_stopwords(words)
    words = average_vec(words)
    result = clf.predict(words.reshape(1, -1))
    return result

import time
mode=2  #mode=1时手动输入,用于演示,  mode=2时,计算100条测试样本
if mode == 1:
    result_list=[]
    time_all=0
    correct=0
    for i in range(num):
        a=input('测试数据:')
        time_start = time.time()  # 记录开始时间
        result=one_pridect(a)
        if result==0:
            print('正常语句')
        else:
            print('内含诈骗信息')
        time_end = time.time()  # 记录结束时间
        time_sum = time_end - time_start  # 计算的时间差为程序的执行时间,单位为秒/s
        print('识别用时%f' %time_sum)
        result_list.append(result)
        time_all+=time_sum
    error=np.sum(result_list)
    correct=num-error
    accuracy=accuracy_score(y_test, predictions)
    print('正常语句数量:%d' %correct)
    print('内含诈骗信息语句数量:%d' % error)
    print('总用时:%f' %time_all)
elif mode==2 :
    TESTFILE="test.txt"
    data, target = get_data(TESTFILE)  # 读取数据
    data = DataFrame(data)  # 将文本转换化成表格形式
    target = DataFrame(target)  # 将标签转化成表格形式
    df = concat([data, target], axis=1)  # 拼接为一个表格
    df.columns = ['text', 'label']
    df['words'] = df["text"].apply(word_cut)  # 分词处理
    df['去除停用词后的数据'] = df["words"].apply(lambda x: remove_stopwords(x))
    x = df["去除停用词后的数据"]  # 处理对象是去除停用词后的数据
    x_vec = np.concatenate([average_vec(z) for z in x])  # 把训练数据处理成词向量
    y = df['label'].values
    time_start = time.time()  # 记录开始时间
    predictions = clf.predict(x_vec)
    time_end = time.time()  # 记录结束时间
    time_sum = time_end - time_start  # 计算的时间差为程序的执行时间,单位为秒/s
    print('识别100条数据用时%f' % time_sum)
    print('Accuracy:', accuracy_score(y, predictions)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

白马少年郎

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值