基于sklearn的文本分类—逻辑回归(1)

本文是文本分类的第一篇,记录使用逻辑回归进行文本分类任务,数据集下载地址:http://thuctc.thunlp.org/

文本分类的主要内容如下:
-0 THUCNews数据集处理方法
- 1.基于逻辑回归的文本分类
- 2.基于朴素贝叶斯的文本分类
- 3.使用LDA进行文档降维以及特征选择
- 4.基于SVM的文本分类
- 5.基于多层感知机MLPC的文本分类
- 6.基于卷积神经网络词级别的文本分类以及调参
- 7.基于卷积神经网络的句子级别的文本分类以及调参
- 8.基于Facebook fastText的快速高效文本分类
- 9.基于RNN的文本分类
- 10.基于LSTM的文本分类
- 11.总结

1 数据预处理

其中使用的训练数据来自清华大学开源的文本分类数据集,原始数据集比较大,提供下载的是提取的小数据,thu_data_500 表示每个类提取500篇文章,thu_data_3000 表示每个类提取3000篇文章,一共14个类别,数据处理的代码如下:

import os
import codecs
import jieba
import refrom sklearn.utils import shuffle
category = ['星座', '股票', '房产', '时尚', '体育', '社会', '家居', '游戏', '彩票', '科技', '教育', '时政', '娱乐', '财经']
# 每篇文档保留的文档数量
#per_class_max_docs = 1000def load_data_to_mini(path, to_path, per_class_max_docs=1000):"""处理清华大学语料库,将类别和文档处理成fasttext 所需要的格式:param path: :param to_path: :return: """# 抽取后的语料库corpus = []if not os.path.isdir(path):print('path error')# 列举当前目录下的所有子列别目录with codecs.open(to_path, 'w') as f:for files in os.listdir(path):curr_path = os.path.join(path, files)print(curr_path)if os.path.isdir(curr_path):count = 0docs = []for file in os.listdir(curr_path):count += 1if count > per_class_max_docs:breakfile_path = os.path.join(curr_path, file)# 读取文件中的内容with codecs.open(file_path, 'r', encoding='utf-8') as fd:docs.append('__label__' + files + ' ' + ' '.join(jieba.cut(re.sub('[  \n\r\t]+', '', fd.read()))))f.write('__label__' + files + ' ' + ' '.join(jieba.cut(re.sub('[  \n\r\t]+', '', fd.read()))))corpus.append(docs)# 将数据写到一个新的文件中with codecs.open(to_path, 'a') as f:for docs in corpus:for doc in docs:f.write(doc + '\n')return corpus

通过调用下面的代码,执行小数据集的提取

corpus = load_data_to_mini('/root/git/data/THUCNews', 'thu_data_all', 3000)
/root/git/data/THUCNews/娱乐
/root/git/data/THUCNews/星座
/root/git/data/THUCNews/时尚
/root/git/data/THUCNews/股票
/root/git/data/THUCNews/彩票
/root/git/data/THUCNews/体育
/root/git/data/THUCNews/房产
/root/git/data/THUCNews/社会
/root/git/data/THUCNews/财经
/root/git/data/THUCNews/家居
/root/git/data/THUCNews/游戏
/root/git/data/THUCNews/科技
/root/git/data/THUCNews/教育
/root/git/data/THUCNews/时政

我们看下提取的结果

print('corpus size(%d,%d)' %(len(corpus), len(corpus[0])))
corpus size(14,1000)

可以看到,结果一共是14个类,每个类500篇文档,下面看下corpus里面的具体内容

corpus[0][1]
'__label__股票 世基 投资 : 紧缩 压力 骤然 增加 沪 指 再失 2800 \u3000 \u3000 余炜 \u3000 \u3000 周二 大盘 在 半年线 处 止跌 后 , 连续 3 日 展开 反弹 , 昨日 一度 站上 过 2830 点 , 但 最终 还是 未能 收复 , 显示 出 20 日线 和 年线 从技术上 对 市场 的 压力 比 想象 中 更加 大 。 弱势 格局 下 , 利空 传言 纷至沓来 , 周末 效应 再次 显现 , 周五 大盘 给 我们 呈现出 的 是 一幕 疲软 下滑 走势 , 使得 前三天 的 反弹 基本 化为乌有 , 2800 点 再 一次 失守 , 股指 重新 来到 半年线 附近 求 支撑 。 \u3000 \u3000 盘面 热点 比较 稀少 , 其中 资产重组 、 业绩 增长 和 预增 题材 的 几只 品种 涨势 不错 , 昨日 提到 过 的 广电 信息 、 银鸽投资 连续 涨停 , 计划 高送 转 的 精诚 铜业 也 受大单 推动 涨停 。 此外 , 高铁 概念 逆势 重新 活跃 , 晋亿 实业 最高 逼近 涨停 , 带动 晋西 车轴 、 中国 北车 、 天马 股份 等 快速 上攻 , 其中 北车 和 晋 亿 实业 已经 率先 创出 阶段 新高 。 部分 具备 病菌 概念 的 医药 股 也 表现 较 好 , 自早 盘起 就 展现 强势 , 莱茵 生物 涨停 , 紫鑫 药业 、 海王 生物 、 联环 药业 大涨 7% 左右 。 \u3000 \u3000 从 目前 公开 消息 来看 , 相信 是 货币政策 面 的 利空 预期 在 对 市场 形成 压力 , 随着 韩国 央行 的 昨日 加息 , 新兴 经济体 紧缩 预期 骤然 升温 , 之前 秘鲁 和 泰国 已经 有过 连续 加息 的 动作 , 与此同时 , 虽然 西方 主要 国家 仍 在 维持 宽松 , 但 随着 发达 经济体 复苏 步伐 的 加快 , 通胀 也 有 抬头 迹象 。 国内 方面 , 下周 可能 将 公布 2010 年 全年 和 12 月份 的 经济运行 数据 , 形势 摆在 这里 , 投资者 有所 担忧 也 是 情理之中 。 欢迎 发表 评论 \xa0 \xa0 我要 评论'

可以看到,开头时_label_的本文标签,后面接着的是新闻正文,正文已经使用jieba进行了分词,词之间使用空格键分开。
下面进行数据的切分,将数据划分为样本和标签,因为读取的数据是按照类别来分块的,在后面采用训练数据和测试数据的时候,会出现问题,所以这里也需要进行数据的随机打乱,数据打乱最好不要使用numpy.random.shuffle(),这个效率很低,而且非常容易出现内存溢出问题,推荐使用的是pandas或者是sklearn中的shuffle,我使用的是后者。切分的代码如下:

def split_data_with_label(corpus):"""将数据划分为训练数据和样本标签:param corpus: :return: """input_x = []input_y = []tag = []if os.path.isfile(corpus):with codecs.open(corpus, 'r') as f:for line in f:tag.append(line)else:for docs in corpus:for doc in docs:tag.append(doc)tag = shuffle(tag)for doc in tag:index = doc.find(' ')input_y.append(doc[:index])input_x.append(doc[index + 1 :])# 打乱数据,避免在采样的时候出现类别不均衡现象# datasets = np.column_stack([input_x, input_y])# np.random.shuffle(datasets)# input_x = []# input_y = []# for i in datasets:#     input_x.append(i[:-1])#     input_y.append(i[-1:])return [input_x, input_y]

这个函数返回两个值,其中第一个返回值input_x是样本数据,一共14*500行,第二个参数input_y和input_x有着相同的行数,每行对应着input_x中新闻样本的类别标签.

2.特征选择

下面将进行特征提取,特征选择的方法有基本的bag-of-words, tf-idf,n-gran等,我们主要使用TF-IDF进行这些方法进行实验,下面是代码:

from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.cross_validation import train_test_split
from sklearn.metrics.scorer import make_scorer
from sklearn import linear_model
from sklearn import metricsfrom time import time
/usr/local/lib/python3.5/dist-packages/sklearn/cross_validation.py:41: DeprecationWarning: This module was deprecated in version 0.18 in favor of the model_selection module into which all the refactored classes and functions are moved. Also note that the interface of the new CV iterators are different from that of this module. This module will be removed in 0.20."This module will be removed in 0.20.", DeprecationWarning)
def feature_extractor(input_x, case='tfidf', max_df=1.0, min_df=0.0):"""特征抽取:param corpus: :param case: 不同的特征抽取方法:return: """return TfidfVectorizer(token_pattern='\w', ngram_range=(1,2), max_df=max_df, min_df=min_df).fit_transform(input_x)

接下来将进行训练数据和测试数据的切分,现在不进行更好的交叉验证等技术,仅仅简单的以一定的比例划分训练数据和测试数据。使用sklearn中提供的工具,具体代码如下:

def split_data_to_train_and_test(corpus, indices=0.2, random_state=10, shuffle=True):"""将数据划分为训练数据和测试数据:param corpus: [input_x]:param indices: 划分比例:random_state: 随机种子:param shuffle: 是否打乱数据:return: """input_x, y = corpus# 切分数据集x_train, x_dev, y_train, y_dev = train_test_split(input_x, y, test_size=indices, random_state=10)print("Vocabulary Size: {:d}".format(input_x.shape[1]))print("Train/Dev split: {:d}/{:d}".format(len(y_train), len(y_dev)))return x_train, x_dev, y_train, y_dev

函数返回四个值,分别是训练数据的样本,训练数据的标签,测试数据样本,测试数据真实标签,下面调用朴素贝叶斯进行分类。

逻辑回归是一种判别式模型,在线性回归的基础上,套用了一个sigmod函数,这个函数讲线性结果映射到一个概率区间,并且概率在0.5周围是光滑的,这就使得数据的分类结果都趋向于在0,1这两端。

LogisticRegression()主要有的参数:
- penalty: 表示正则项为L1或者L2,默认是L2
- C 正则项的参数C,也就是惩罚系数
- fit_intercept 表示线性模型中的bias,也就是模型中的参数b 是一个布尔值,表示带或者不带bias,一般都是带的!
- solver 表示的是参数学习的方法,有{‘newton-cg’, ‘lbfgs’, ‘liblinear’, ‘sag’, ‘saga’}这几种情况,在小数据集下liblinear是相对好的选择,在数据集大的时候,选择saga,sag会是一个更好的选择,但是liblinear在多分类情况下受限制与ovr,所以其他的选择在多分类下更明智

这里主要是进行相关的实验,不在理论上展开太多,下面采用逻辑回归进行文档分类,具体代码如下:

def fit_and_predicted(train_x, train_y, test_x, test_y, penalty='l2', C=1.0, solver='lbfgs'):"""训练与预测:param train_x: :param train_y: :param test_x: :param test_y: :return: """clf = linear_model.LogisticRegression(penalty=penalty, C=C, solver=solver, n_jobs=-1).fit(train_x, train_y)predicted = clf.predict(test_x)print(metrics.classification_report(test_y, predicted))print('accuracy_score: %0.5fs' %(metrics.accuracy_score(test_y, predicted)))

上面函数调用LogisticRegression(),基于线性分类器的变种模型有很多,我们将会在后面的试验中使用添加了L1范式的lasso回归,添加了L2范式的岭回归回归

下面将进行实际的代码运行阶段了。

# 1. 加载语料
corpus = split_data_with_label('thu_data_1000')

2.1 TF-IDF (max_df, min_df)=dafault (1.0,0.0)

input_x, y = corpus
# 2. 特征选择
input_x = feature_extractor(input_x, 'tfidf')
# 3.切分训练数据和测试数据
train_x, test_x, train_y, test_y = split_data_to_train_and_test([input_x, y])
Vocabulary Size: 942969
Train/Dev split: 11200/2800
# 4. 训练以及测试
t0 = time()
print('\t\t使用 max_df,min_df=(1.0,0.0) 进行特征选择的逻辑回归文本分类\t\t')
fit_and_predicted(train_x, train_y, test_x, test_y)
print('time uesed: %0.4fs' %(time() - t0))
     使用 max_df,min_df=(1.0,0.0) 进行特征选择的逻辑回归文本分类     precision    recall  f1-score   support__label__体育       0.93      0.97      0.95       186
__label__娱乐       0.87      0.88      0.88       233
__label__家居       0.88      0.90      0.89       203
__label__彩票       0.98      0.96      0.97       207
__label__房产       0.90      0.90      0.90       178
__label__教育       0.92      0.91      0.92       208
__label__时尚       0.92      0.92      0.92       197
__label__时政       0.83      0.87      0.85       211
__label__星座       0.94      0.97      0.95       202
__label__游戏       0.96      0.91      0.94       202
__label__社会       0.85      0.92      0.88       210
__label__科技       0.88      0.80      0.84       173
__label__股票       0.87      0.82      0.84       196
__label__财经       0.93      0.90      0.91       194avg / total       0.90      0.90      0.90      2800accuracy_score: 0.90321s
time uesed: 44.1572s

可以看出逻辑回归的文本分类方法在该数据集上表现良好,综合得分都有91%以上,下面我们将对tf-idf做文章,看看不同的tf-idf参数对特征产生影响

2.2 TF-IDF 不同的max_df对结果参数的影响

# 2. 特征选择
max_df = [0.2, 0.4, 0.5, 0.8, 1.0, 1.5, 5]
for i in max_df:input_x, y = corpusinput_x = feature_extractor(input_x, 'tfidf', max_df=i)# 3.切分训练数据和测试数据train_x, test_x, train_y, test_y = split_data_to_train_and_test([input_x, y])# 4. 训练以及测试t0 = time()print('\t 使用 max_df,min_df=(%.1f,0.0) 进行特征选择的逻辑回归文本分类\t\t\n' %(i))fit_and_predicted(train_x, train_y, test_x, test_y)print('time uesed: %0.4fs' %(time() - t0))
Vocabulary Size: 670795
Train/Dev split: 5600/1400使用 max_df,min_df=(0.2,0.0) 进行特征选择的逻辑回归文本分类       precision    recall  f1-score   support_体育_       0.95      0.95      0.95       109_娱乐_       0.73      0.88      0.80        92_家居_       0.98      0.88      0.93       109_彩票_       0.99      0.96      0.97        97_房产_       0.94      0.94      0.94        97_教育_       0.94      0.89      0.92       104_时尚_       0.87      0.87      0.87       110_时政_       0.86      0.89      0.87        93_星座_       0.96      0.93      0.95       105_游戏_       0.97      0.91      0.94       103_社会_       0.84      0.88      0.86        99_科技_       0.85      0.86      0.86        93_股票_       0.82      0.88      0.85        78_财经_       0.97      0.91      0.94       111avg / total       0.91      0.90      0.91      1400accuracy_score: 0.90429s
time uesed: 63.8214s
Vocabulary Size: 671113
Train/Dev split: 5600/1400使用 max_df,min_df=(0.4,0.0) 进行特征选择的逻辑回归文本分类       precision    recall  f1-score   support_体育_       0.97      0.94      0.96       109_娱乐_       0.78      0.89      0.83        92_家居_       0.94      0.87      0.90       109_彩票_       0.98      0.97      0.97        97_房产_       0.93      0.92      0.92        97_教育_       0.95      0.88      0.92       104_时尚_       0.90      0.86      0.88       110_时政_       0.83      0.90      0.87        93_星座_       0.94      0.95      0.95       105_游戏_       0.95      0.90      0.93       103_社会_       0.86      0.90      0.88        99_科技_       0.88      0.87      0.88        93_股票_       0.80      0.91      0.85        78_财经_       0.95      0.89      0.92       111avg / total       0.91      0.91      0.91      1400accuracy_score: 0.90500s
time uesed: 62.6203s
Vocabulary Size: 671183
Train/Dev split: 5600/1400使用 max_df,min_df=(0.5,0.0) 进行特征选择的逻辑回归文本分类       precision    recall  f1-score   support_体育_       0.97      0.94      0.96       109_娱乐_       0.79      0.89      0.84        92_家居_       0.93      0.87      0.90       109_彩票_       0.98      0.97      0.97        97_房产_       0.93      0.91      0.92        97_教育_       0.94      0.88      0.91       104_时尚_       0.91      0.87      0.89       110_时政_       0.83      0.89      0.86        93_星座_       0.94      0.96      0.95       105_游戏_       0.95      0.89      0.92       103_社会_       0.85      0.90      0.87        99_科技_       0.88      0.87      0.88        93_股票_       0.80      0.91      0.85        78_财经_       0.94      0.88      0.91       111avg / total       0.91      0.90      0.90      1400accuracy_score: 0.90357s
time uesed: 63.2442s
Vocabulary Size: 671261
Train/Dev split: 5600/1400使用 max_df,min_df=(0.8,0.0) 进行特征选择的逻辑回归文本分类       precision    recall  f1-score   support_体育_       0.96      0.94      0.95       109_娱乐_       0.79      0.88      0.83        92_家居_       0.92      0.89      0.91       109_彩票_       0.98      0.97      0.97        97_房产_       0.93      0.91      0.92        97_教育_       0.95      0.88      0.92       104_时尚_       0.91      0.87      0.89       110_时政_       0.83      0.88      0.85        93_星座_       0.94      0.97      0.96       105_游戏_       0.95      0.89      0.92       103_社会_       0.85      0.89      0.87        99_科技_       0.88      0.85      0.86        93_股票_       0.77      0.91      0.84        78_财经_       0.95      0.88      0.92       111avg / total       0.91      0.90      0.90      1400accuracy_score: 0.90143s
time uesed: 64.9945s
Vocabulary Size: 671267
Train/Dev split: 5600/1400使用 max_df,min_df=(1.0,0.0) 进行特征选择的逻辑回归文本分类       precision    recall  f1-score   support_体育_       0.95      0.94      0.94       109_娱乐_       0.80      0.88      0.84        92_家居_       0.95      0.89      0.92       109_彩票_       0.98      0.95      0.96        97_房产_       0.93      0.92      0.92        97_教育_       0.95      0.88      0.92       104_时尚_       0.91      0.87      0.89       110_时政_       0.81      0.90      0.85        93_星座_       0.94      0.98      0.96       105_游戏_       0.95      0.90      0.93       103_社会_       0.84      0.89      0.86        99_科技_       0.89      0.84      0.86        93_股票_       0.76      0.91      0.83        78_财经_       0.96      0.87      0.92       111avg / total       0.91      0.90      0.90      1400accuracy_score: 0.90214s
time uesed: 67.9015s
Vocabulary Size: 671267
Train/Dev split: 5600/1400使用 max_df,min_df=(1.5,0.0) 进行特征选择的逻辑回归文本分类       precision    recall  f1-score   support_体育_       0.95      0.94      0.94       109_娱乐_       0.80      0.88      0.84        92_家居_       0.95      0.89      0.92       109_彩票_       0.98      0.95      0.96        97_房产_       0.93      0.92      0.92        97_教育_       0.95      0.88      0.92       104_时尚_       0.91      0.87      0.89       110_时政_       0.81      0.90      0.85        93_星座_       0.94      0.98      0.96       105_游戏_       0.95      0.90      0.93       103_社会_       0.84      0.89      0.86        99_科技_       0.89      0.84      0.86        93_股票_       0.76      0.91      0.83        78_财经_       0.96      0.87      0.92       111avg / total       0.91      0.90      0.90      1400accuracy_score: 0.90214s
time uesed: 66.4803s
Vocabulary Size: 562057
Train/Dev split: 5600/1400使用 max_df,min_df=(5.0,0.0) 进行特征选择的逻辑回归文本分类       precision    recall  f1-score   support_体育_       0.94      0.83      0.88       109_娱乐_       0.61      0.75      0.67        92_家居_       0.91      0.55      0.69       109_彩票_       0.95      0.84      0.89        97_房产_       0.94      0.81      0.87        97_教育_       0.92      0.80      0.86       104_时尚_       0.82      0.72      0.77       110_时政_       0.77      0.78      0.78        93_星座_       0.86      0.75      0.80       105_游戏_       0.96      0.72      0.82       103_社会_       0.77      0.78      0.77        99_科技_       0.64      0.81      0.71        93_股票_       0.33      0.88      0.48        78_财经_       0.97      0.67      0.79       111avg / total       0.83      0.76      0.78      1400accuracy_score: 0.75929s
time uesed: 22.6883s

从实验结果可以看出,最好的max_df是在0.4-0.5之间,这也就是为什么很多demo中设置TF-IDF阈值进行特征的筛选,下面设置在max_df为1.0的目标下测试min_df;

2.2 TF-IDF 不同的min_df对结果参数的影响

# 2. 特征选择
min_df = [0., 0.1, 0.2, 0.3, 0.4]
for i in min_df:input_x, y = corpusinput_x = feature_extractor(input_x, 'tfidf', max_df=1.0, min_df=i)# 3.切分训练数据和测试数据train_x, test_x, train_y, test_y = split_data_to_train_and_test([input_x, y])# 4. 训练以及测试t0 = time()print('\t 使用 max_df,min_df=(1.0,%.1f) 进行特征选择的逻辑回归文本分类\t\t\n' %(i))fit_and_predicted(train_x, train_y, test_x, test_y)print('time uesed: %0.4fs' %(time() - t0))
Vocabulary Size: 671267
Train/Dev split: 5600/1400使用 max_df,min_df=(1.0,0.0) 进行特征选择的逻辑回归文本分类       precision    recall  f1-score   support_体育_       0.95      0.94      0.94       109_娱乐_       0.80      0.88      0.84        92_家居_       0.95      0.89      0.92       109_彩票_       0.98      0.95      0.96        97_房产_       0.93      0.92      0.92        97_教育_       0.95      0.88      0.92       104_时尚_       0.91      0.87      0.89       110_时政_       0.81      0.90      0.85        93_星座_       0.94      0.98      0.96       105_游戏_       0.95      0.90      0.93       103_社会_       0.84      0.89      0.86        99_科技_       0.89      0.84      0.86        93_股票_       0.76      0.91      0.83        78_财经_       0.96      0.87      0.92       111avg / total       0.91      0.90      0.90      1400accuracy_score: 0.90214s
time uesed: 67.8985s
Vocabulary Size: 1052
Train/Dev split: 5600/1400使用 max_df,min_df=(1.0,0.1) 进行特征选择的逻辑回归文本分类       precision    recall  f1-score   support_体育_       0.93      0.94      0.94       109_娱乐_       0.75      0.75      0.75        92_家居_       0.87      0.85      0.86       109_彩票_       0.97      0.97      0.97        97_房产_       0.91      0.88      0.89        97_教育_       0.95      0.88      0.92       104_时尚_       0.88      0.84      0.86       110_时政_       0.82      0.89      0.86        93_星座_       0.93      0.96      0.94       105_游戏_       0.95      0.88      0.91       103_社会_       0.84      0.88      0.86        99_科技_       0.79      0.78      0.79        93_股票_       0.73      0.90      0.80        78_财经_       0.94      0.86      0.90       111avg / total       0.88      0.88      0.88      1400accuracy_score: 0.87786s
time uesed: 1.8236s
Vocabulary Size: 472
Train/Dev split: 5600/1400使用 max_df,min_df=(1.0,0.2) 进行特征选择的逻辑回归文本分类       precision    recall  f1-score   support_体育_       0.89      0.92      0.90       109_娱乐_       0.71      0.79      0.75        92_家居_       0.80      0.79      0.79       109_彩票_       0.97      0.86      0.91        97_房产_       0.92      0.80      0.86        97_教育_       0.96      0.84      0.89       104_时尚_       0.86      0.82      0.84       110_时政_       0.77      0.84      0.80        93_星座_       0.85      0.90      0.88       105_游戏_       0.78      0.66      0.72       103_社会_       0.77      0.87      0.82        99_科技_       0.71      0.73      0.72        93_股票_       0.65      0.83      0.73        78_财经_       0.92      0.85      0.88       111avg / total       0.83      0.82      0.82      1400accuracy_score: 0.82214s
time uesed: 1.4046s
Vocabulary Size: 244
Train/Dev split: 5600/1400使用 max_df,min_df=(1.0,0.3) 进行特征选择的逻辑回归文本分类       precision    recall  f1-score   support_体育_       0.87      0.89      0.88       109_娱乐_       0.73      0.66      0.70        92_家居_       0.81      0.74      0.78       109_彩票_       0.90      0.84      0.87        97_房产_       0.90      0.80      0.85        97_教育_       0.84      0.78      0.81       104_时尚_       0.78      0.83      0.81       110_时政_       0.68      0.78      0.73        93_星座_       0.83      0.86      0.84       105_游戏_       0.75      0.61      0.67       103_社会_       0.70      0.84      0.76        99_科技_       0.69      0.72      0.71        93_股票_       0.60      0.78      0.68        78_财经_       0.87      0.78      0.82       111avg / total       0.79      0.78      0.78      1400accuracy_score: 0.78143s
time uesed: 1.1189s
Vocabulary Size: 154
Train/Dev split: 5600/1400使用 max_df,min_df=(1.0,0.4) 进行特征选择的逻辑回归文本分类       precision    recall  f1-score   support_体育_       0.82      0.83      0.82       109_娱乐_       0.66      0.63      0.64        92_家居_       0.75      0.60      0.66       109_彩票_       0.91      0.85      0.88        97_房产_       0.82      0.75      0.78        97_教育_       0.77      0.72      0.74       104_时尚_       0.70      0.75      0.73       110_时政_       0.65      0.78      0.71        93_星座_       0.85      0.86      0.85       105_游戏_       0.63      0.57      0.60       103_社会_       0.70      0.76      0.73        99_科技_       0.61      0.67      0.64        93_股票_       0.54      0.67      0.60        78_财经_       0.78      0.72      0.75       111avg / total       0.73      0.73      0.73      1400accuracy_score: 0.72643s
time uesed: 1.0229s

从上面的实验可以看出,min_df或许取0.0是一个不错的选择,那就默认吧。

不得不说,总感觉上面的控制变量进行参数的寻找是有毛病的,暂且就这么做吧。在后面的试验中,我们将选取max_df=0.5,min_df=0.0进行相关实验。

3 逻辑回归的调参

3.1 交叉验证

在进行最优参数的调整之前,我们先看一下sklearn提供的另外一个函数LogisticRegressionCV(),它提供了标准的k-fold-cross-validator

def fit_and_predicted_use_CV(train_x, train_y, test_x, test_y, penalty='l2', C=1.0, solver='lbfgs', cv=10):"""训练与预测:param train_x: :param train_y: :param test_x: :param test_y: :return: """clf = linear_model.LogisticRegressionCV(penalty=penalty, C=C, solver=solver, n_jobs=-1, cv=cv).fit(train_x, train_y)predicted = clf.predict(test_x)print(metrics.classification_report(test_y, predicted))print('accuracy_score: %0.5fs' %(metrics.accuracy_score(test_y, predicted)))
input_x, y = corpus
input_x = feature_extractor(input_x, 'tfidf', max_df=i)
# 3.切分训练数据和测试数据
train_x, test_x, train_y, test_y = split_data_to_train_and_test([input_x, y])
# 4. 训练以及测试
t0 = time()
print('\t 使用 max_df,min_df=(%.1f,0.0) 进行特征选择的逻辑回归文本分类\t\t\n' %(i))
fit_and_predicted_use_CV(train_x, train_y, test_x, test_y)
print('time uesed: %0.4fs' %(time() - t0))

可以看到使用交叉验证的结果往往比我们直接划分数据集的效果要好一些。

3.2 逻辑回归的最佳参数寻找

现在将采用sklearn中提供的网格查找方法进行最优参数的寻找,网格查找其实是一种暴力查找方法。

import numpy as np
from sklearn.grid_search import GridSearchCV
def train_and_predicted_with_graid(corpus, param_grid, cv=5):input_x, y = corpusscoring = ['precision_macro', 'recall_macro', 'f1_macro']clf = linear_model.LogisticRegression(n_jobs=-1)grid = GridSearchCV(clf, param_grid, cv=cv, scoring='accuracy')scores = grid.fit(input_x, y)print('parameters:')best_parameters = grid.best_estimator_.get_params()for param_name in sorted(best_parameters):print('\t%s: %r' %(param_name, best_parameters[param_name]))return scores
C= [0.1, 0.2, 0.5, 0.8, 1.5, 3, 5]
fit_intercept=[True, False]
penalty=['l1', 'l2']
solver=['newton-cg', 'lbfgs', 'liblinear', 'sag', 'saga']
solver = ['saga']
param_grid=dict(C=C, fit_intercept=fit_intercept, penalty=penalty, solver=solver)
input_x, y = corpus
input_x = feature_extractor(input_x, 'tfidf', max_df=0.5, min_df=0.0)
scores = train_and_predicted_with_graid([input_x, y], cv=5, param_grid=param_grid)
parameters:C: 5class_weight: Nonedual: Falsefit_intercept: Trueintercept_scaling: 1max_iter: 100multi_class: 'ovr'n_jobs: -1penalty: 'l2'random_state: Nonesolver: 'saga'tol: 0.0001verbose: 0warm_start: False

4. 其他线性分类器

4.1 简单的线性回归

def fit_and_predicted_with_linerCV(train_x, train_y, test_x, test_y, alpha=1.0, cv=10):"""训练与预测:param train_x: :param train_y: :param test_x: :param test_y: :return: """clf = linear_model.LogisticRegressionCV(penalty=penalty, C=C, solver=solver, n_jobs=-1, cv=cv).fit(train_x, train_y)predicted = clf.predict(test_x)print(metrics.classification_report(test_y, predicted))print('accuracy_score: %0.5fs' %(metrics.accuracy_score(test_y, predicted)))
input_x, y = corpus
input_x = feature_extractor(input_x, 'tfidf', max_df=i)
# 3.切分训练数据和测试数据
train_x, test_x, train_y, test_y = split_data_to_train_and_test([input_x, y])
# 4. 训练以及测试
t0 = time()
print('\t 使用线性回归的文本分类\t\t\n' %(i))
fit_and_predicted_with_linerCV(train_x, train_y, test_x, test_y)
print('time uesed: %0.4fs' %(time() - t0))
{'fit_time': array([ 0.69856882,  0.6891861 ,  0.68457079,  0.68122745,  0.68401599]),'score_time': array([ 0.24055672,  0.25055385,  0.24642444,  0.24583435,  0.25062966]),'test_f1_macro': array([ 0.93190598,  0.93358814,  0.92900074,  0.93620104,  0.93139325]),'test_precision_macro': array([ 0.93411186,  0.93509947,  0.93082131,  0.93790787,  0.93312355]),'test_recall_macro': array([ 0.93178571,  0.93357143,  0.92892857,  0.93607143,  0.93142857]),'train_f1_macro': array([ 0.95534592,  0.95516529,  0.95665886,  0.95573948,  0.95629695]),'train_precision_macro': array([ 0.95629235,  0.95618146,  0.95767379,  0.9566414 ,  0.95725075]),'train_recall_macro': array([ 0.95526786,  0.95508929,  0.95660714,  0.95571429,  0.95625   ])}

4.2 使用L1范式的Lasso

def fit_and_predicted_with_LassoCV(train_x, train_y, test_x, test_y):"""训练与预测:param train_x: :param train_y: :param test_x: :param test_y: :return: """clf = linear_model.LassoCV().fit(train_x, train_y)predicted = clf.predict(test_x)print(metrics.classification_report(test_y, predicted))print('accuracy_score: %0.5fs' %(metrics.accuracy_score(test_y, predicted)))
input_x, y = corpus
input_x = feature_extractor(input_x, 'tfidf', max_df=i)
# 3.切分训练数据和测试数据
train_x, test_x, train_y, test_y = split_data_to_train_and_test([input_x, y])
# 4. 训练以及测试
t0 = time()
print('\t 使用线性回归的文本分类\t\t\n' %(i))
fit_and_predicted_with_LassoCV(train_x, train_y, test_x, test_y)
print('time uesed: %0.4fs' %(time() - t0))
{'fit_time': array([ 0.69856882,  0.6891861 ,  0.68457079,  0.68122745,  0.68401599]),'score_time': array([ 0.24055672,  0.25055385,  0.24642444,  0.24583435,  0.25062966]),'test_f1_macro': array([ 0.93190598,  0.93358814,  0.92900074,  0.93620104,  0.93139325]),'test_precision_macro': array([ 0.93411186,  0.93509947,  0.93082131,  0.93790787,  0.93312355]),'test_recall_macro': array([ 0.93178571,  0.93357143,  0.92892857,  0.93607143,  0.93142857]),'train_f1_macro': array([ 0.95534592,  0.95516529,  0.95665886,  0.95573948,  0.95629695]),'train_precision_macro': array([ 0.95629235,  0.95618146,  0.95767379,  0.9566414 ,  0.95725075]),'train_recall_macro': array([ 0.95526786,  0.95508929,  0.95660714,  0.95571429,  0.95625   ])}

4.3 使用L2范式的岭回归

def fit_and_predicted_with_RidgeCV(train_x, train_y, test_x, test_y):"""训练与预测:param train_x: :param train_y: :param test_x: :param test_y: :return: """clf = linear_model.RidgeClassifierCV().fit(train_x, train_y)predicted = clf.predict(test_x)print(metrics.classification_report(test_y, predicted))print('accuracy_score: %0.5fs' %(metrics.accuracy_score(test_y, predicted)))
input_x, y = corpus
input_x = feature_extractor(input_x, 'tfidf', max_df=i)
# 3.切分训练数据和测试数据
train_x, test_x, train_y, test_y = split_data_to_train_and_test([input_x, y])
# 4. 训练以及测试
t0 = time()
print('\t 使用线性回归的文本分类\t\t\n' %(i))
fit_and_predicted_with_RidgeCV(train_x, train_y, test_x, test_y)
print('time uesed: %0.4fs' %(time() - t0))
{'fit_time': array([ 0.69856882,  0.6891861 ,  0.68457079,  0.68122745,  0.68401599]),'score_time': array([ 0.24055672,  0.25055385,  0.24642444,  0.24583435,  0.25062966]),'test_f1_macro': array([ 0.93190598,  0.93358814,  0.92900074,  0.93620104,  0.93139325]),'test_precision_macro': array([ 0.93411186,  0.93509947,  0.93082131,  0.93790787,  0.93312355]),'test_recall_macro': array([ 0.93178571,  0.93357143,  0.92892857,  0.93607143,  0.93142857]),'train_f1_macro': array([ 0.95534592,  0.95516529,  0.95665886,  0.95573948,  0.95629695]),'train_precision_macro': array([ 0.95629235,  0.95618146,  0.95767379,  0.9566414 ,  0.95725075]),'train_recall_macro': array([ 0.95526786,  0.95508929,  0.95660714,  0.95571429,  0.95625   ])}

4.4 使用elastic net正则项的的线性回归

def fit_and_predicted_with_ElasticNetCV(train_x, train_y, test_x, test_y):"""训练与预测:param train_x: :param train_y: :param test_x: :param test_y: :return: """clf = linear_model.MultiTaskElasticNetCV().fit(train_x, train_y)predicted = clf.predict(test_x)print(metrics.classification_report(test_y, predicted))print('accuracy_score: %0.5fs' %(metrics.accuracy_score(test_y, predicted)))
input_x, y = corpus
input_x = feature_extractor(input_x, 'tfidf', max_df=i)
# 3.切分训练数据和测试数据
train_x, test_x, train_y, test_y = split_data_to_train_and_test([input_x, y])
# 4. 训练以及测试
t0 = time()
print('\t 使用线性回归的文本分类\t\t\n' %(i))
fit_and_predicted_with_ElasticNetCV(train_x, train_y, test_x, test_y)
print('time uesed: %0.4fs' %(time() - t0))
{'fit_time': array([ 0.69856882,  0.6891861 ,  0.68457079,  0.68122745,  0.68401599]),'score_time': array([ 0.24055672,  0.25055385,  0.24642444,  0.24583435,  0.25062966]),'test_f1_macro': array([ 0.93190598,  0.93358814,  0.92900074,  0.93620104,  0.93139325]),'test_precision_macro': array([ 0.93411186,  0.93509947,  0.93082131,  0.93790787,  0.93312355]),'test_recall_macro': array([ 0.93178571,  0.93357143,  0.92892857,  0.93607143,  0.93142857]),'train_f1_macro': array([ 0.95534592,  0.95516529,  0.95665886,  0.95573948,  0.95629695]),'train_precision_macro': array([ 0.95629235,  0.95618146,  0.95767379,  0.9566414 ,  0.95725075]),'train_recall_macro': array([ 0.95526786,  0.95508929,  0.95660714,  0.95571429,  0.95625   ])}

线性模型有很多的变种,其的简单高效并且可解释性强等特点在机器学习领域有很广泛的应用,这里不作进一步展开,大家自己科普吧~~

5. 总结

本文记录了使用sklearn,采用线性回归进行文本分类任务,在特征选择哪里,进行TF-IDF的参数验证部分,找到相对较好的max_df=0.5左右;

在选取好了特征后,我们对数据集进行交叉验证,发现交叉验证的方式能提高模型的效果,推荐在后面划分数据集的时候使用交叉验证。

我以逻辑回归为例,进行了线性回归分类器的参数搜索部分,然后利用最佳的参数,训练了最佳的逻辑回归文本分类模型,模型性能的acc值能达到:91%以上

最后,我们利用其它具有代表性的线性分类器进行相关实验,但是没有进行调参工作,其中L1产生比较离散的数值,elasticNet结合了L1,L2的优缺点,其在集合上的图像介于两者之间,效果在论文中比L1,L2都要好。

文本分类---逻辑回归(1)相关推荐

  1. 机器学习中二分类逻辑回归的学习笔记

    1 致谢 感谢 Andrew Ng的教导! 2 前言 逻辑回归是机器学习中很重要而且很基础的算法,它也代表了分类算法最基本的思想. 3 二分类逻辑回归逻辑回归算法 3.1 假设函数 假设函数的形式为: ...

  2. python机器学习案例系列教程——逻辑分类/逻辑回归LR/一般线性回归(softmax回归)

    全栈工程师开发手册 (作者:栾鹏) python数据挖掘系列教程 线性函数.线性回归 参考:http://blog.csdn.net/luanpeng825485697/article/details ...

  3. 吴恩达ex3_吴恩达机器学习 EX3 作业 第一部分多分类逻辑回归 手写数字

    1 多分类逻辑回归 逻辑回归主要用于分类,也可用于one-vs-all分类.如本练习中的数字分类,输入一个训练样本,输出结果可能为0-9共10个数字中的一个数字.一对多分类训练过程使用"一对 ...

  4. 多分类逻辑回归 MNLogit python

    多分类逻辑回归MNLogit 引言 实例及python实现 数据集 查看数据情况 Logistics回归 输出结果 模型评价 Precision.Recall.f1_score ROC曲线及AUC 混 ...

  5. 逻辑回归二分类算法python_多分类逻辑回归 (Multinomial Logistic Regression)

    前言 分类从结果的数量上可以简单的划分为: 二分类(Binary Classification) 多分类(Multinomial Classification). 其中二分类是最常见且使用最多的分类场 ...

  6. 【吴恩达】机器学习作业 ex3data1 -- 多分类逻辑回归(Python)

    一.前言 本次是多分类逻辑回归的代码,主题是让你预测5000个手写数字对应的真正数字,每张图片有400个特征值,可以用20*20的方阵表示出来,一共5000行数据,此次的数据集是.mat类型,和以往的 ...

  7. 浅谈对机器学习方法(决策树,SVM,knn最近邻,随机森林,朴素贝叶斯、逻辑回归)的理解以及用sklearn工具实现文本分类和回归方法...

    一.决策树 定下一个最初的质点,从该点出发.分叉.(由于最初质点有可能落在边界值上,此时有可能会出现过拟合的问题. 二.SVM  svm是除深度学习在深度学习出现之前最好的分类算法了.它的特征如下: ...

  8. 分类---逻辑回归(二分类)

    逻辑回归的基本原理:逻辑回归预测的是概率,需要求解的是如何选取参数c和b可以使得所有样本预测正确的可能性最大.逻辑回归算法需要找到分类概率P(y=1)与输入向量X的直接关系,然后通过比较概率值来判断类 ...

  9. 2.2案例:鸢尾花分类——逻辑回归

    文章目录 一.引言 鸢尾花数据集 二.鸢尾花分类 一.引言 鸢尾花数据集为机器学习常用的数据集,今天,我们基于该数据集进行算法学习 鸢尾花数据集 鸢尾花数据集有3个类别,每个类别有50个样本,其中一个 ...

  10. 分类——逻辑回归Python实现

    目录 一.确认训练数据 二.逻辑回归实现 三.验证 四.线性不可分分类的实现 五.随机梯度下降算法的实现 一.确认训练数据 import numpy as np import matplotlib.p ...

最新文章

  1. 如何处理大数据:微博信息流数据库设计
  2. C++知识点10——函数指针
  3. linux perl 报错 Can‘t locate CPAN.pm in @INC (@INC contains: inc /usr/local/lib64/perl5 /usr.... 解决方法
  4. application.properties中自定义属性的使用
  5. 神经信息学整理(1)-神经细胞,MP模型
  6. Deformable ConvNets自己的理解
  7. python转义例题_笨办法学Python记录--习题37 异常,lambda,yield,转义序列
  8. 【matlab】线性空间滤波器的实现
  9. oracle怎么使用包,oracle包(package)入门——应用实例
  10. 活动目录概念和灾难恢复
  11. 2016-06-07【普元EOS Studio】
  12. Android开机动画总结
  13. Win10 快捷键大全(史上最全)
  14. B站崩了、Facebook崩了,我们到底该怎么保证高可用
  15. 微信公众号关注自动回复得到小程序链接
  16. java 定义16进制_java数据类型(大小等),变量定义,各进制书写方法
  17. (完全理解)二重积分中的换元积分中的雅可比矩阵
  18. debian安装rar
  19. 小时候看过一部漫画,忘记名字了。。。
  20. JVM全局导图(第一版)

热门文章

  1. 新版标准日本语初级_第三十九课
  2. elasticsearch实现搜索拼音然后高亮内容
  3. 正版NOD32升级ID在线申请
  4. allegro怎么修改文本_allegro user preferences常见设置及说明
  5. ajax多个分页,通过Ajax与kaminari进行多重分页
  6. Oracle环境变量配置
  7. python数字转对应中文_python英文数字到中文数字的转换
  8. Access数据库修复 压缩
  9. ad网络标号怎么用_altium designer网络标号的作用范围
  10. 用牛顿迭代法求方程2x^3-4x^2+3x-6=0在1.5附近的解,要求误差小于1e-5