前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >项目实战01:“达观杯”文本竞赛

项目实战01:“达观杯”文本竞赛

作者头像
用户5473628
发布2019-08-08 14:56:51
6750
发布2019-08-08 14:56:51
举报
文章被收录于专栏:MiningAlgorithmsMiningAlgorithms

参考达观杯十强分享PPT来复盘比赛(文末附网盘链接):

目录:

一、观察数据;

二、特征工程:TF-IDF

三,world2vec模型

四,建立模型:LR、SVM

五,lightGBM模型

六,模型调优及最优参数

一,观察数据:

1,下载数据,读取数据,观察数据:

压缩的数据近1个G,解压后的数据也是2.6个G,分为两个csv文件。

数据包含2个csv文件:

》train_set.csv:此数据集用于训练模型,每一行对应一篇文章。文章分别在“字”和“词”的级别上做了脱敏处理。共有四列:

第一列是文章的索引(id),第二列是文章正文在“字”级别上的表示,即字符相隔正文(article);第三列是在“词”级别上的表示,即词语相隔正文(word_seg);第四列是这篇文章的标注(class)。

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

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

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

2,将训练集拆分为训练集和验证集:

利用Python语言的pandas包可以分别读取训练集和测试集:

代码如下:

df_train =pd.read_csv(‘Data/001daguan/train_set.csv’)

注释:若内存不足可添加参数:nrows=1000

df_test =pd.read_csv(‘Data/001daguan/test_set.csv’)

3,对数据以及赛题的理解:

读取训练集的前十行数据,可见数据的columns分别为:id,article,word_seg,class,其中class即为label属性,需要正确分类的属性。

二、特征工程:TF-IDF

1,TF-IDF:

TF-IDF(termfrequency–inverse document frequency)是一种用于资讯检索与资讯探勘的常用加权技术。TF-IDF是一种统计方法,用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。TF-IDF加权的各种形式常被搜寻引擎应用,作为文件与用户查询之间相关程度的度量或评级。除了TF-IDF以外,因特网上的搜寻引擎还会使用基于连结分析的评级方法,以确定文件在搜寻结果中出现的顺序。

某一特定文件内的高词语频率,以及该词语在整个文件集合中的低文件频率,可以产生出高权重的TF-IDF。因此,TF-IDF倾向于过滤掉常见的词语,保留重要的词语。

TF-IDF = TF * IDF

其中:

词频 (term frequency, TF) 指的是某一个给定的词语在该文件中出现的次数。这个数字通常会被归一化(分子一般小于分母 区别于IDF),以防止它偏向长的文件。(同一个词语在长文件里可能会比短文件有更高的词频,而不管该词语重要与否。)

对于在某一特定文件里的词语t_i 来说,它的重要性可表示为:

逆向文件频率 (inverse document frequency, IDF)是一个词语普遍重要性的度量。某一特定词语的IDF,可以由总文件数目除以包含该词语之文件的数目,再将得到的商取对数得到。

IDF计算公式为:

其中:

|D|:语料库中的文件总数;

上式分母为:包含词语t_i的文件数目,如果该词语不在语料库中,就会导致被除数为零,因此一般情况下使用:“该分母项”+1。

TF-IDF的主要思想是:如果某个词或短语在一篇文章中出现的频率TF高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。

2,代码实现:

可使用sklearn包来实现tf-idf。

例如:

使用达观杯数据,处理成为tf-idf特征,并保存到本地,

由于数据量比较大,处理时间大概为九分钟。

三,world2vec:

1,word2vec词向量原理:

word2vec是google在2013年推出的一个NLP工具,它的特点是将所有的词向量化,这样词与词之间就可以定量的去度量他们之间的关系,挖掘词之间的联系。虽然源码是开源的,但是谷歌的代码库国内无法访问,因此本文的讲解word2vec原理以Github上的word2vec代码为准。本文关注于word2vec的基础知识。

用词向量来表示词并不是word2vec的首创,在很久之前就出现了。最早的词向量是很冗长的,它使用是词向量维度大小为整个词汇表的大小,对于每个具体的词汇表中的词,将对应的位置置为1。比如我们有下面的5个词组成的词汇表,词"Queen"的序号为2, 那么它的词向量就是(0,1,0,0,0)(0,1,0,0,0)。同样的道理,词"Woman"的词向量就是(0,0,0,1,0)(0,0,0,1,0)。这种词向量的编码方式我们一般叫做1-of-N representation或者one hot representation.

Distributed representation可以解决One hot representation的问题,它的思路是通过训练,将每个词都映射到一个较短的词向量上来。所有的这些词向量就构成了向量空间,进而可以用普通的统计学的方法来研究词与词之间的关系。这个较短的词向量维度是多大呢?这个一般需要我们在训练时自己来指定。

用Distributed Representation表示的较短的词向量,我们就可以较容易的分析词之间的关系了,比如我们将词的维度降维到2维,有一个有趣的研究表明,用下图的词向量表示我们的词时,我们可以发现:

KingMan + Woman = Queen

图片:分布式词向量

可见我们只要得到了词汇表里所有词对应的词向量,那么我们就可以做很多有趣的事情了。

2,简单实践:

四,建立模型:LR、SVM:

算法原理:

1,逻辑回归:

逻辑回归就是在用回归的办法做分类任务,那有什么办法可以做到呢,此时我们就先考虑最简单的二分类,结果是正例或者负例的任务.

按照多元线性回归的思路,我们可以先对这个任务进行线性回归,学习出这个事情结果的规律,比如根据人的饮食,作息,工作和生存环境等条件预测一个人"有"或者"没有"患恶性肿瘤,可以先通过回归任务来预测人体内肿瘤的大小,取一个平均值作为阈值,假如平均值为y,肿瘤大小超过y为恶心肿瘤,无肿瘤或大小小于y的,为非恶性.这样通过线性回归加设定阈值的办法,就可以完成一个简单的二分类任务.如下图:

2,SVM:

下面是花了一天时间,在图书馆,结合西瓜书和统计学习方法对SVM进行分步骤推导:

3,代码实践:

五,lightGBM模型;

lightGBM算法相关原理可参考公众号文章:机器学习8:集成学习--LightGBM。

代码语言:javascript
复制
# 第五部分:lightGBM模型
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.metrics import f1_score
import time
import pickle
import lightgbm as LGB
from sklearn.externals import joblib

t_start = time.time()
data_path = 'Datasets/DaGuan/'
feature_path = 'Datasets/DaGuan/feature_file/'
proba_path = 'Datasets/DaGuan/proba_file/'
model_path = 'Datasets/DaGuan/model_file/'
result_path ="Datasets/DaGuan/result/"


# 0 自定义验证集的评价函数
print("0 自定义验证集的评价函数")
def f1_score_vali(preds, data_vali):
    labels = data_vali.get_label()
    preds = np.argmax(preds.reshape(19, -1), axis=0)
    score_vali = f1_score(y_true=labels, y_pred=preds, average='macro')
    return 'f1_score', score_vali, True


#1 读取数据,并转换到LGB的标准数据格式
print("1 读取数据,并转换到LGB的标准数据格式")
data_fp = open(feature_path + 'data_w_tfidf.pkl' , 'rb')
x_train, y_train, x_test = pickle.load(data_fp)
data_fp.close()

#2 划分训练集和验证集,验证集比例为test_size

print("划分训练集和验证集,验证集比例为test_size")
x_train, x_vali, y_train, y_vali = train_test_split(x_train, y_train, test_size=0.1, random_state=0)
d_train = LGB.Dataset(data=x_train, label=y_train)
d_vali = LGB.Dataset(data=x_vali, label=y_vali)


#3 训练LGB分类器
print("3 训练LGB分类器")
params = {
    'boosting': 'gbdt',
    'application': 'multiclassova',
    'num_class': 19,
    'learning_rate': 0.1,
    'num_leaves': 31,
    'max_depth': -1,
    'lambda_l1': 0,
    'lambda_l2': 0.5,
    'bagging_fraction': 1.0,

}

bst = LGB.train(params, d_train, num_boost_round=800, valid_sets=d_vali, feval=f1_score_vali,
                early_stopping_rounds=None,
                verbose_eval=True)

joblib.dump(bst, model_path + "LGB_data_w_tfidf.m")


#4 对测试集进行预测;将预测结果转换为官方标准格式;并将结果保存至本地
print("4 对测试集进行预测;将预测结果转换为官方标准格式;并将结果保存至本地")
y_proba = bst.predict(x_test)
y_test = np.argmax(y_proba, axis=1) + 1

df_result = pd.DataFrame(data={'id': range(5000), 'class': y_test.tolist()})
df_proba = pd.DataFrame(data={'id': range(5000), 'proba': y_proba.tolist()})

df_result.to_csv(result_path  + 'LGB_data_w_tfidf_result.csv', index=False)
df_proba.to_csv(result_path + 'LGB_data_w_tfidf_proba.csv', index=False)
t_end = time.time()
print("训练结束,耗时:{}min".format((t_end - t_start) / 60))

六,模型调优及最优参数

共分成2步:1,超参数调参;2,模型融合。

代码语言:javascript
复制
import pandas as pd
import pickle
import lightgbm as lgb
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model.logistic import LogisticRegression
from sklearn.svm import LinearSVC
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score

# 1,超参数调参:
fp = open('DataSets/features/data_tfidf_train.pkl', 'rb')
x_train,y_train = pickle.load(fp)
x_train, x_test, y_train, y_test = train_test_split(x_train[:5000], y_train[:5000], test_size=0.3, random_state=2019)

print('Start Training:Logistic Regression...')
lr_grid={'C':list((100,120,140))}
lr = GridSearchCV(LogisticRegression(),param_grid = lr_grid, cv = 5)
lr.fit(x_train, y_train)
print('Best param is ', lr.best_params_)
print('The best score is ', lr.best_score_)

print('Start Training:SVM...')
svm_grid={'C':list((1, 5, 10))}
svm = GridSearchCV(LinearSVC(),param_grid = svm_grid, cv = 5)
svm.fit(x_train, y_train)
print('Best param is ', svm.best_params_)
print('The best score is ', svm.best_score_)

print('Start Training:LightGBM...')
lgbm_grid={'num_leaves':list((25, 30, 35)), 'learning_rate':list((0.2, 0.1, 0.005)), 'n_estimators':list((10, 20, 50))}
lgbm = GridSearchCV(lgb.sklearn.LGBMClassifier(),param_grid = lgbm_grid, cv = 5)
lgbm.fit(x_train, y_train)
print('Best param is ', lgbm.best_params_)
print('The best score is ', lgbm.best_score_)

# 2,模型融合:
from mlxtend.classifier import StackingClassifier

lr_model = LogisticRegression()
svm_model = LinearSVC()
lgbm_model = lgb.sklearn.LGBMClassifier()
dt_model = DecisionTreeClassifier()

sclf = StackingClassifier(classifiers=[lr_model,svm_model,lgbm_model],meta_classifier=dt_model)
sclf.fit(x_train,y_train)

for clf,label in zip([lr_model,svm_model,lgbm_model,sclf],['逻辑回归','SVM','LightGBM','StackingClassifier']):
    scores = cross_val_score(clf,x_train,y_train,cv = 5,scoring='accuracy')
    print("Accuracy: %0.2f (+/- %0.2f) [%s]"% (scores.mean(), scores.std(), label))

Reference:

网盘链接:https://pan.baidu.com/s/1CFoIezO46h2XrcCAKOglEw

提取码:4916;

代码参考:https://github.com/Heitao5200/DGB/tree/master/model/model_code

1,“达观杯”文本智能处理挑战赛官网

http://www.dcjingsai.com/common/cmpt/“达观杯”文本智能处理挑战赛_竞赛信息.html;

https://blog.csdn.net/weixin_42662262/article/details/89044804;

2,TF-IDF及其算法:

http://www.cnblogs.com/biyeymyhjob/archive/2012/07/17/2595249.html;

https://blog.csdn.net/u011630575/article/details/80179494;

3,world2vec:

https://www.cnblogs.com/pinard/p/7243513.html

https://blog.csdn.net/qq_39446239/article/details/89069343

https://www.jianshu.com/p/972d0db609f2

4,建立模型:LR、SVM:

https://www.cnblogs.com/pinard/p/6029432.html

六,模型调优及最优参数:

https://blog.csdn.net/u012736685/article/details/89319007

https://www.jianshu.com/p/5905f19c4df6

https://blog.csdn.net/u012914436/article/details/89132931#datawhale_day06_2214

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-04-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 MiningAlgorithms 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档