机器学习二:文本分类(比赛实例)

1 文本分类

是自然语言处理(NLP)领域里一项基本任务。而文本呢的长度过长对文本智能解析带来了巨大的挑战。

用传统的监督学习模型对一段文文本进行分类的基本过程:

一段原始文本(数据预处理)处理后的文本(特征工程)Features(输入)y=f(x_1,x_2,x_3,...)(输出)类别

注:特征工程过程是整个机器学习过程中最要的部分。特征决定了机器学习的上限,而机器学习算法只是逼近这个上限。

2 常用的机器学习算法 

a.传统的监督学习算法:对数几率回归、支持向量机SVM、朴素贝叶斯、决策树、集成学习等

b.深度学习:cnn、rnn、attention模型等

3 “达观杯”文本智能处理挑战赛

3.1 引言

自然语言处理一直是人工智能领域的重要话题,而人类语言的复杂性也给 NLP 布下了重重困难等待解决。长文本的智能解析就是颇具挑战性的任务,如何从纷繁多变、信息量庞杂的冗长文本中获取关键信息,一直是文本领域难题。随着深度学习的热潮来临,有许多新方法来到了 NLP 领域,给相关任务带来了更多优秀成果,也给大家带来了更多应用和想象的空间。

3.2 比赛任务

此次比赛,达观数据提供了一批长文本数据和分类信息,结合当下最先进的NLP和人工智能技术,深入分析文本内在结构和语义信息,构建文本分类模型,实现精准分类。

数据包含2个csv文件:

train_set.csv:此数据集用于训练模型,每一行对应一篇文章。文章分别在“字”和“词”的级别上做了脱敏处理。共有四列: 第一列是文章的索引(id),第二列是文章正文在“字”级别上的表示,即字符相隔正文(article);第三列是在“词”级别上的表示,即词语相隔正文(word_seg);第四列是这篇文章的标注(class)。

注:每一个数字对应一个“字”,或“词”,或“标点符号”。“字”的编号与“词”的编号是独立的!

test_set.csv:此数据用于测试。数据格式同train_set.csv,但不包含class。

注:test_set与train_test中文章id的编号是独立的。

3.3 python代码如下

"""
Created on Thu Sep 20 00:08:08 2018

@author: Taylen 
"""

print("Start.................")

"""导入所需要的安装包""" 
import pandas as pd    #是python的一个数据分析包,该工具是为了解决数据分析任务而创建的。Pandas 纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的工具。
from sklearn.linear_model import LogisticRegression
from sklearn.feature_extraction.text import CountVectorizer


'''
# 功能简介:从硬盘上读取已经下好的数据,并进行简单处理
# 知识点定位:数据预处理
'''
df_train = pd.read_csv('D:/program/ml_code/v0.0/train_set.csv')
df_test = pd.read_csv('D:/program/ml_code/v0.0/test_set.csv')
df_train.drop(columns=['article', 'id'], inplace=True)  #.drop()删除指定列,inplace可选参数。如果手动设定为True(默认为False),那么原数组直接就被替换,不需要进行重新赋值。
df_test.drop(columns=['article'], inplace=True)


'''
#功能简介:将数据集中的字符文本转换为数字向量,以便计算机能够进行处理(一段文字→→→一个向量),即矢量化
#知识点定位:特征工程
'''
'''
@@@ CountVectorizer()参数说明:
① ngram_range:词组切分的长度范围;
② max_df:可以设置为范围在[0.0 1.0]的float,也可以设置为没有范围限制的int,默认为1.0。这个参数的作用是作为一个阈值,
当构造语料库的关键词集的时候,如果某个词的document frequence大于max_df,这个词不会被当作关键词。
如果这个参数是float,则表示词出现的次数与语料库文档数的百分比,如果是int,则表示词出现的次数。
如果参数中已经给定了vocabulary,则这个参数无效;
③ min_df:类似于max_df,不同之处在于如果某个词的document frequence小于min_df,则这个词不会被当作关键词;
④ max_features:默认为None,可设为int,对所有关键词的term frequency进行降序排序,只取前max_features个作为关键词集。
CountVectorizer是通过fit_transform函数将文本中的词语转换为词频矩阵,矩阵元素a[i][j] 表示j词在第i个文本下的词频。
即各个词语出现的次数,通过get_feature_names()可看到所有文本的关键字,通过toarray()可看到词频矩阵的结果。
'''
vectorizer = CountVectorizer(ngram_range=(1, 2), min_df=3, max_df=0.9, max_features=100000)
#x_train=vectorizer.fit_transform(df_train['word_seg'])等同于以下两行代码。注:fit_transform(X)拟合模型,并返回文本矩阵
vectorizer.fit(df_train['word_seg'])
x_train = vectorizer.transform(df_train['word_seg'])
x_test = vectorizer.transform(df_test['word_seg'])
y_train = df_train['class']-1


'''
#功能简介:训练一个分类器
#知识点定位:传统监督学习算法之线性逻辑回归模型
'''
'''
@@@LogisticRegression()参数说明:
① c:正则化系数λ的倒数,float类型,默认为1.0。必须是正浮点型数。像SVM一样,越小的数值表示越强的正则化;
② dual:对偶或原始方法,bool类型,默认为False。对偶方法只用在求解线性多核(liblinear)的L2惩罚项上。当样
本数量>样本特征的时候,dual通常设置为False;
③ 补充参数说明--penalty:惩罚项,str类型,可选参数为l1和l2,默认为l2。用于指定惩罚项中使用的规范。
newton-cg、sag和lbfgs求解算法只支持L2规范。L1G规范假设的是模型的参数满足拉普拉斯分布,L2假设的模型
参数满足高斯分布,所谓的范式就是加上对参数的约束,使得模型更不会过拟合(overfit),但是如果要说是不是
加了约束就会好,这个没有人能回答,只能说,加约束的情况下,理论上应该可以获得泛化能力更强的结果。
'''
lg = LogisticRegression(C=4, dual=True)
lg.fit(x_train, y_train)
"""根据训练好的分类型对测试集的样本进行预测"""
y_test = lg.predict(x_test)
"""保存预测结果至本地"""
df_test['class'] = y_test.tolist()  #tolist()将数组或者矩阵转换成列表
df_test['class'] = df_test['class'] + 1
df_result = df_test.loc[:, ['id', 'class']]
df_result.to_csv('D:/program/ml_code/v0.0/result.csv', index=False)

print("finish..................")

3.4 代码分析

3.4.1 工具包

①pandas:是python的一个数据分析包,该工具是为了解决数据分析任务而创建的。Pandas 纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的工具。

②利用逻辑斯谛回归(logistic regression)分类

虽然这个算法中有回归二字,但它做的事情却并不是回归,而是分类。下面补充以下回归与分类的基本概念:

输入变量与输出变量均为连续变量的预测问题是回归问题,而输出变量为有限个离散变量的预测问题成为分类问题。其实回归问题和分类问题的本质一样,都是针对一个输入做出一个输出预测,区别在于输出变量的类型。

logistic regression这个算法只能解决简单的线性二分类,在机器学习分类算法中并不是很出众,但其能被改进为多分类,叫做softmax, 这在深度学习中是很有名的分类算法。

 ③ CountVectorizer文本特征提取

通过fit_transform函数将文本中的词语转换为词频矩阵.

get_feature_names()可看到所有文本的关键字;

vocabulary_可看到所有文本的关键字和其位置

toarray()可看到词频矩阵的结果

CountVectorizer.fit()对于一个由字符串构成的数组,每个元素可能是一个以空格分割的句子(sentence),功能是将它们分割,为每一个单词(word)编码,在这个过程中会自动滤除停止词(stop words),例如英文句子中的”a”,”.”之类的长度为1的字符串。

fit(raw_documents[, y]):Learn a vocabulary dictionary of all tokens in the raw documents.

CountVectorizer.transform():其功能则是将输入的数组中每个元素进行分割,然后使用fit中生成的编码字典,将原单词转化成编码,数据以稀疏矩阵(csr_matrix)的形式返回。

fit_transform(raw_documents[, y]):Learn the vocabulary dictionary and return term-document matrix.

稀疏矩阵:零元素远远多余非零元素,且零元素分布没有规律。稀疏矩阵在工程应用中经常被使用,尤其是在通信编码机器学习中。若编码矩阵或特征表达矩阵是稀疏矩阵时,其计算速度会大大提升。对于机器学习而言,稀疏矩阵应用非常广,比如数据特征表示、自然语言处理等领域。

代码实列验证如下:

from sklearn.feature_extraction.text import CountVectorizer

text_fruit=["apple orange banana mango","pear orange pineapple","grape apple apple", 'banana'] # "apple orange banana mango" 为输入列表元素,即代表一个文章的字符串
cv = CountVectorizer()#创建词袋数据结构
cv_fit=cv.fit_transform(text_fruit)
#上述代码等价于下面两行
#cv.fit(text_fruit)
#cv_fit=cv.transform(text_fruit)

print(cv.get_feature_names())   
 #['apple', 'banana', 'grape', 'mango', 'orange', 'pear', 'pineapple'] 列表形式呈现文章生成的词典

print(cv.vocabulary_)             
 # {'apple': 0, 'orange': 4, 'banana': 1, 'mango': 3, 'pear': 5, 'pineapple': 6, 'grape': 2} 字典形式呈现,key:词,value:词频

print(cv_fit)
#((0, 3)	1    第0个列表元素,词典中索引为3的元素, 词频
# (0, 1)	1
# (0, 4)	1
# (0, 0)	1
# (1, 6)	1
# (1, 5)	1
# (1, 4)	1
# (2, 2)	1
# (2, 0)	2
# (3, 1)	1
print(cv_fit.toarray()) #.toarray() 是将结果转化为稀疏矩阵矩阵的表示方式;
'''
矩阵元素a[i][j] 表示j词在第i个文本下的词频。
[[1 1 0 1 1 0 0]
 [0 0 0 0 1 1 1]
 [2 0 1 0 0 0 0]
 [0 1 0 0 0 0 0]]
'''
print(cv_fit.toarray().sum(axis=0))  #每个词在所有文档中的词频
#[3 2 1 1 2 1 1]

4 如何提高模型性能

a.数据预处理:对不规范的数据进行规范化,如将文字中的图像表情去除掉

b.特征工程:技巧性较高,需要有一定的经验积累。往往选区明显的特征。如对一个人身份的确定,我们通常采取人脸特征而非身材特征

c.机器学习算法:微软两大杀器工具:适合大多数问题,并取得较好的结果的算法----LandForm、LightBGM

d.模型集成:(西瓜书第八章)将几个模型融合在一起

e.数据增强:人为增多数据

注:着重关注特征工程、模型集成与数据增强三个方面

猜你喜欢

转载自blog.csdn.net/u011591807/article/details/82861415