NLP逻辑回归模型(LR)实现分类问题实例详解

之前写了一个贝叶斯分类的问题,这次使用LR实现一个分类问题(调库实现),首先就是收集数据,这次使用的是一个某简书大佬的一个小项目的数据集(也可以自己收集一个数据集,进行分类),格式如下:

1	今天早盘带学员以15元左右买入《300223北京君正》明天有望大涨,请关注 勿追买!金股热线:400-6289775现代投资【国富咨询】
0	您尾号7544卡13日14:26网上银行支出(消费)158元。【工商银行】

步骤如下:数据预处理(此过程可以代码实现,也可以自己提前手动处理好,本次使用的数据集格式都和无效数据、乱码数据都清理掉了)->将数据拆分为训练集、测试集、预测集->将数据生成词频字典->提取特征,将文本特征进行数值化->训练LR模型->模型评估->进行预测

这里简单说一下独热码:假设词库是 我\爱\你\中国,则独热码位数为4位,其实我爱你为1110,我爱中国1101。(1代表存在,0代表不存在)(1110其实就代表 有我、爱、你的意思)

文件结构如下:数据文件为train.txt、predict.txt,代码文件为model.py文件

NLP逻辑回归模型(LR)实现分类问题实例详解

1.首先,加载需要库文件

import collections
import itertools
import operator
import array
import jieba
import sklearn
import sklearn.linear_model as linear_model

2.写一个分离数据标签和内容的数据处理函数(该函数test_size参数同时也是一个标志,为0则不划分,否则划分)

# 对文本进行标签和文本的分离,并划分训练集和测试集
def data_xy(data_path, test_size):
    assert test_size >= 0 and test_size < 1.0, '0 <= test_size < 1'
    # 列表:y是标签,x是文本
    y = list()
    x = list()
    for line in open(data_path, "r").readlines():
        # line[:-1]除去最后一个元素(换行符),split('\t', 1)按\t进行分割,为什么这样哪,具体请看数据集
        label, text = line[:-1].split('\t', 1)
        # 使用jieba分词工具进行分词
        x.append(list(jieba.cut(text)))
        y.append(int(label))
    # 参数test_size为0代表不进行划分
    if test_size == 0:
        return x, y
    # 参数test_size为0-1时,利用sklearn包划分数据集
    # train_test_split()具体参考:https://blog.csdn.net/zhuqiang9607/article/details/83686308
    return sklearn.model_selection.train_test_split(
        x, y, test_size=test_size, random_state=1028)

3.建立词频字典,并过滤低频词的函数

# 创建词频字典,并过滤低频词
def build_dict(text_list, min_freq):
    # 根据传入的文本列表,创建一个最小频次为min_freq的字典,并返回字典word -> wordid
    assert min_freq >= 0 and min_freq < 100, '请输入合理的最小词频'
    # collections.Counter快速的统计一个字典里面每个元素出现的次数,参数必须是一维的list
    freq_dict = collections.Counter(itertools.chain(*text_list))
    # 按词频排序
    freq_list = sorted(freq_dict.items(), key=operator.itemgetter(1), reverse=True)
    # 过滤低频词
    words, _ = zip(*filter(lambda wc: wc[1] >= min_freq, freq_list))
    return dict(zip(words, range(len(words))))

4.将文本转成独热码的函数

# 将传入的文本转化为向量/独热码
def text2vect(text_list, word2id):
    # 返回结果大小为[n_samples, dict_size]
    X = list()
    for text in text_list:
        # 创建数组长度,长度[0] * len(word2id)
        vect = array.array('l', [0] * len(word2id))
        for word in text:
            if word not in word2id:
                continue
            vect[word2id[word]] = 1
        X.append(vect)
    return X

5.关于模型的各种评估结果的函数

def evaluate(model, X, y):
    # 评估数据集,并返回评估结果,包括:正确率、AUC值
    accuracy = model.score(X, y)
    fpr, tpr, thresholds = sklearn.metrics.roc_curve(y, model.predict_proba(X)[:, 1], pos_label=1)
    return accuracy, sklearn.metrics.auc(fpr, tpr)

主函数

# 主函数
if __name__ == "__main__":
    # 有监督模型,标签0-->正常短信,标签1-->垃圾短信
    data = "train.txt"
    predict = "predict.txt"
    # step 1:分词并拆分成训练集train和测试集test,预测集predict
    X_train, X_test, Y_train, Y_test = data_xy(data, 0.2)
    X_predict, Y_predict = data_xy(predict, 0)
    # step 2:创建字典
    word2id = build_dict(X_train, min_freq=5)
    # step 3:抽取特征,文本特征的数值化,这里使用了Bag-of-words模型,常用的方式是还有TF-IDF、word2vec等
    X_train = text2vect(X_train, word2id)
    X_test = text2vect(X_test, word2id)
    X_predict = text2vect(X_predict, word2id)
    # step 4:训练模型,我们使用逻辑回归模型来解决这个二分类的问题,直接调用sklearn中封装好LR的模型,
    # 详细参数说明请查询skilearn的官网API
    lr = linear_model.LogisticRegression(C=1)
    lr.fit(X_train, Y_train)
    # step 5:训练集模型评估
    accuracy, auc = evaluate(lr, X_train, Y_train)
    print("训练集正确率:", accuracy * 100)
    print("训练集AUC值:", auc)
    # step 6:测试集模型评估
    accuracy, auc = evaluate(lr, X_test, Y_test)
    print("测试集正确率:", accuracy * 100)
    print("测试AUC值:", auc)
    # step 7:进行预测,并输出预测结果和实际结果
    label_predict = lr.predict(X_predict)
    # 输出的label_predict和Y_predict格式不统一,很难受,输出一下数据类型看一下,然后进行统一
    # print(type(label_predict),type(Y_predict))
    # <class 'numpy.ndarray'> <class 'list'>
    print("模型预测标签:", label_predict.tolist())
    print("数据实际标签:", Y_predict)

完整代码如下:

import collections
import itertools
import operator
import array
import jieba
import sklearn
import sklearn.linear_model as linear_model
# 对文本进行标签和文本的分离,并划分训练集和测试集
def data_xy(data_path, test_size):
    assert test_size >= 0 and test_size < 1.0, '0 <= test_size < 1'
    # 列表:y是标签,x是文本
    y = list()
    x = list()
    for line in open(data_path, "r").readlines():
        # line[:-1]除去最后一个元素(换行符),split('\t', 1)按\t进行分割,为什么这样哪,具体请看数据集
        label, text = line[:-1].split('\t', 1)
        # 使用jieba分词工具进行分词
        x.append(list(jieba.cut(text)))
        y.append(int(label))
    # 参数test_size为0代表不进行划分
    if test_size == 0:
        return x, y
    # 参数test_size为0-1时,利用sklearn包划分数据集
    # train_test_split()具体参考:https://blog.csdn.net/zhuqiang9607/article/details/83686308
    return sklearn.model_selection.train_test_split(
        x, y, test_size=test_size, random_state=1028)
# 创建词频字典,并过滤低频词
def build_dict(text_list, min_freq):
    # 根据传入的文本列表,创建一个最小频次为min_freq的字典,并返回字典word -> wordid
    assert min_freq >= 0 and min_freq < 100, '请输入合理的最小词频'
    # collections.Counter快速的统计一个字典里面每个元素出现的次数,参数必须是一维的list
    freq_dict = collections.Counter(itertools.chain(*text_list))
    # 按词频排序
    freq_list = sorted(freq_dict.items(), key=operator.itemgetter(1), reverse=True)
    # 过滤低频词
    words, _ = zip(*filter(lambda wc: wc[1] >= min_freq, freq_list))
    return dict(zip(words, range(len(words))))
# 将传入的文本转化为向量/独热码
def text2vect(text_list, word2id):
    # 返回结果大小为[n_samples, dict_size]
    X = list()
    for text in text_list:
        # 创建数组长度,长度[0] * len(word2id)
        vect = array.array('l', [0] * len(word2id))
        for word in text:
            if word not in word2id:
                continue
            vect[word2id[word]] = 1
        X.append(vect)
    return X
def evaluate(model, X, y):
    # 评估数据集,并返回评估结果,包括:正确率、AUC值
    accuracy = model.score(X, y)
    fpr, tpr, thresholds = sklearn.metrics.roc_curve(y, model.predict_proba(X)[:, 1], pos_label=1)
    return accuracy, sklearn.metrics.auc(fpr, tpr)


# 主函数
if __name__ == "__main__":
    # 有监督模型,标签0-->正常短信,标签1-->垃圾短信
    data = "train.txt"
    predict = "predict.txt"
    # step 1:分词并拆分成训练集train和测试集test,预测集predict
    X_train, X_test, Y_train, Y_test = data_xy(data, 0.2)
    X_predict, Y_predict = data_xy(predict, 0)
    # step 2:创建字典
    word2id = build_dict(X_train, min_freq=5)
    # step 3:抽取特征,文本特征的数值化,这里使用了Bag-of-words模型,常用的方式是还有TF-IDF、word2vec等
    X_train = text2vect(X_train, word2id)
    X_test = text2vect(X_test, word2id)
    X_predict = text2vect(X_predict, word2id)
    # step 4:训练模型,我们使用逻辑回归模型来解决这个二分类的问题,直接调用sklearn中封装好LR的模型,
    # 详细参数说明请查询skilearn的官网API
    lr = linear_model.LogisticRegression(C=1)
    lr.fit(X_train, Y_train)
    # step 5:训练集模型评估
    accuracy, auc = evaluate(lr, X_train, Y_train)
    print("训练集正确率:", accuracy * 100)
    print("训练集AUC值:", auc)
    # step 6:测试集模型评估
    accuracy, auc = evaluate(lr, X_test, Y_test)
    print("测试集正确率:", accuracy * 100)
    print("测试AUC值:", auc)
    # step 7:进行预测,并输出预测结果和实际结果
    label_predict = lr.predict(X_predict)
    # 输出的label_predict和Y_predict格式不统一,很难受,输出一下数据类型看一下,然后进行统一
    # print(type(label_predict),type(Y_predict))
    # <class 'numpy.ndarray'> <class 'list'>
    print("模型预测标签:", label_predict.tolist())
    print("数据实际标签:", Y_predict)

运行结果:

训练集正确率: 99.40760993392573
训练集AUC值: 0.9995892953795253
测试集正确率: 96.81093394077449
测试AUC值: 0.9925394550652651
模型预测标签: [0, 1, 0, 0, 1, 0, 1, 0, 0]
数据实际标签: [0, 1, 0, 0, 1, 0, 1, 1, 0]

(以上代码可以直接运行,对应数据,可以自己爬取,格式按照样例即可)

NLP逻辑回归模型(LR)实现分类问题实例详解NLP逻辑回归模型(LR)实现分类问题实例详解 任泓洁的小生活 发布了94 篇原创文章 · 获赞 20 · 访问量 3万+ 私信 关注
上一篇:python实现灰色预测模型(GM11)——以预测股票收盘价为例


下一篇:第十三节 岭回归(L2正则化)解决过拟合问题