赞
踩
实操主要包括以下几个任务:
在机器学习算法的训练过程中,假设给定 N N N个样本,每个样本有 M M M个特征,这样组成了 N × M N×M N×M的样本矩阵,然后完成算法的训练和预测。文本表示成计算机能够运算的数字或向量的方法一般称为词嵌入(Word Embedding)方法。词嵌入将不定长的文本转换到定长的空间内,是文本分类的第一步。
将每一个单词使用一个离散的向量表示。具体将每个字/词编码一个索引,然后根据索引进行赋值。
One-hot表示方法的例子如下:
句子1:我 爱 北 京 天 安 门
句子2:我 喜 欢 上 海
首先对所有句子的字进行索引,即将每个字确定一个编号:
{
'我': 1, '爱': 2, '北': 3, '京': 4, '天': 5,
'安': 6, '门': 7, '喜': 8, '欢': 9, '上': 10, '海': 11
}
在这里共包括11个字,因此每个字可以转换为一个11维度稀疏向量:
我:[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
爱:[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
...
海:[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
Bag of Words(词袋表示),也称为Count Vectors,每个文档的字/词可以使用其出现次数(词频)来进行表示。
句子1:我 爱 北 京 天 安 门
句子2:我 喜 欢 上 海
直接统计每个字出现的次数,并进行赋值:
句子1:我 爱 北 京 天 安 门
转换为 [1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0]
句子2:我 喜 欢 上 海
转换为 [1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1]
在sklearn中可以直接CountVectorizer
来实现这一步骤:
from sklearn.feature_extraction.text import CountVectorizer
corpus = [
'This is the first document.',
'This document is the second document.',
'And this is the third one.',
'Is this the first document?',
]
vectorizer = CountVectorizer()
vectorizer.fit_transform(corpus).toarray()
N-gram与Count Vectors类似,不过加入了相邻单词组合成为新的单词,并进行计数。
如果N取值为2,则句子1和句子2就变为:
句子1:我爱 爱北 北京 京天 天安 安门
句子2:我喜 喜欢 欢上 上海
TF-IDF 分数由两部分组成:第一部分是词语频率(Term Frequency),第二部分是逆文档频率(Inverse Document Frequency)。其中计算语料库中文档总数除以含有该词语的文档数量,然后再取对数就是逆文档频率。
TF(t)= 该词语在当前文档出现的次数 / 当前文档中词语的总数
IDF(t)= log_e(文档总数 / 出现该词语的文档总数)
机器学习是对能通过经验自动改进的计算机算法的研究。机器学习通过历史数据训练出模型对应于人类对经验进行归纳的过程,机器学习利用模型对新数据进行预测对应于人类利用总结的规律对新问题进行预测的过程。
本文主要为利用python进行实操,使用到的模型理论部分可以跳转相应的链接学习。
值得注意的是,XGBoost、LightGBM并不是指某个算法,而是机器学习算法GBDT的算法实现,高效地实现了GBDT算法并进行了算法和工程上的许多改进,具体区别和联系可参考:GBDT、XGBoost、LightGBM的区别和联系
根据数据分析结果,我们这里可以去掉可能是标点符号的字符(字符3750,字符900和字符648)。
import pandas as pdimport joblibdata_file = 'train_set.csv'rawdata = pd.read_csv(data_file, sep='\t', encoding='UTF-8')#用正则表达式按标点替换文本import rerawdata['words']=rawdata['text'].apply(lambda x: re.sub('3750|900|648',"",x))del rawdata['text']
一般策略是:
在选择模型、确定模型参数时:
先把当前竞赛给的训练集划分为三个部分:训练集、验证集、测试集。其中,训练集用于训练,验证集用于调参,测试集用于评估线下和线上的模型效果。
特别的,为了进行交叉验证,划分后的训练集留10%用于测试;剩下90%输入交叉验证。
注意:测试集最好固定下来,可以先打乱然后记录下索引值,之后直接取用。
有一些模型的参数需要选择,这些参数会在一定程度上影响模型的精度,那么如何选择这些参数呢?
在确定最佳模型参数(best parameters)后:可以把原始的完整训练集全部扔给设置为best parameters的模型进行训练,得到最终的模型(final model),然后利用final model对真正的测试集进行预测。
注意:由于训练集中,不同类别的样本个数不同,在进行数据集划分时可以考虑使用分层抽样,根据不同类别的样本占比进行抽样,以保证标签的分布与整个数据集的分布一致。
from sklearn.model_selection import train_test_splitimport joblibrawdata.reset_index(inplace=True,drop=True)test_data=joblib.load('test_index.pkl')train_data=joblib.load('train_index.pkl')X=list(rawdata.index)y=rawdata['label']X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.1,stratify=y) #stratify=y表示分层抽样,根据不同类别的样本占比进行抽样test_data={'X_test':X_test,'y_test':y_test}joblib.dump(test_data,'test_index.pkl')train_data={'X_train':X_train,'y_train':y_train}joblib.dump(train_data,'train_index.pkl')train_x=rawdata.loc[train_data['X_train']]['words']train_y=rawdata.loc[train_data['X_train']]['label'].valuestest_x=rawdata.loc[test_data['X_test']]['words']test_y=rawdata.loc[test_data['X_test']]['label'].values
利用StratifiedKFold对划分后的train_data分层抽样:
sfolder=sklearn.model_selection.StratifiedKFold(n_splits=10,shuffle=True,random_state=1)for train, test in sfolder.split(X,y): print('Train: %s | test: %s' % (train, test))
# test 读取测试集数据test_data_file = 'test_a.csv'f = pd.read_csv(test_data_file, sep='\t', encoding='UTF-8')test_data = f['text'].apply(lambda x: re.sub('3750|900|648',"",x))
使用sklearn库进行词频特征和TFIDF特征提取,注意,这里使用划分后的训练集提取各个词的特征(fit),而由训练集划分出的测试集的特征是由该特征映射的,而不是用全部训练集提取的特征映射来的;而最终测试集的特征由全部训练集提取的特征映射得到。
max_features表示特征维度,该值也算是超参数,这里只设置了300维。
from sklearn.feature_extraction.text import CountVectorizervectorizer = CountVectorizer(max_features=300)vectorizer = vectorizer.fit(train_x)train_text = vectorizer.transform(train_x)#训练集划分出的测试集的特征由train_x映射test_text = vectorizer.transform(test_x)#最终测试集vectorizer = CountVectorizer(max_features=300)vectorizer = vectorizer.fit(rawdata['words'])final_test_text=vectorizer.transform(test_data)
from sklearn.feature_extraction.text import TfidfVectorizertfidf = TfidfVectorizer(ngram_range=(1,3), max_features=300)tfidf = tfidf.fit(train_x)train_text_tfidf = tfidf.transform(train_x)test_text_tfidf = tfidf.transform(test_x)final_test_text_tfidf=tfidf.transform(test_data)#最终测试集tfidf = TfidfVectorizer(ngram_range=(1,3), max_features=300)tfidf = tfidf.fit(rawdata['words'])final_test_text=tfidf.transform(test_data)
通过本地构建验证集计算F1得分。
# Count Vectors + RidgeClassifierfrom sklearn.linear_model import RidgeClassifierfrom sklearn.metrics import f1_scoreclf = RidgeClassifier()clf.fit(train_text[:10000], train_y[:10000])val_pred = clf.predict(train_text[10000:])print(f1_score(train_y[10000:], val_pred, average='macro'))
测试集精度:0.5948335699700965
# TF-IDF + RidgeClassifierimport pandas as pdfrom sklearn.linear_model import RidgeClassifierfrom sklearn.metrics import f1_scoreclf = RidgeClassifier()clf.fit(train_text_tfidf[:10000], train_y.values[:10000])val_pred = clf.predict(train_text_tfidf[10000:])print(f1_score(train_y.values[10000:], val_pred, average='macro'))# 0.87
0.6928858913248898
利用sklearn内置的Adaboost模块可以直接进行模型训练,Adaboost是集成学习模型,可以选择不同的个体学习器,这里选择决策树分类器作为基学习器。
import numpy as npfrom sklearn.ensemble import AdaBoostClassifierfrom sklearn.tree import DecisionTreeClassifierfrom sklearn.datasets import make_gaussian_quantilesbdt = AdaBoostClassifier(DecisionTreeClassifier(max_depth=2, min_samples_split=20, min_samples_leaf=5), algorithm="SAMME", n_estimators=200, learning_rate=0.8)bdt.fit(train_text_tfidf, train_y)Z = bdt.predict(test_text_tfidf)print "Score:", bdt.score(train_text_tfidf,train_y)
额外安装依赖库xgboost:
pip install xgboost#pip install xgboost==1.4.2
由两种方式可以利用XGBoost库进行模型训练和预测,第一种基于XGBoost的sklearn API(推荐),第二种是基于XGBoost自带接口。
import pandas as pdfrom sklearn import metricsfrom sklearn.model_selection import train_test_splitimport xgboost as xgbimport matplotlib.pyplot as plt#基于XGB的sklearn API-推荐from xgboost.sklearn import XGBClassifierclf = XGBClassifier( n_estimators=20, # 迭代次数 learning_rate=0.1, # 步长 max_depth=5, # 树的最大深度 min_child_weight=1, # 决定最小叶子节点样本权重和 silent=1, # 输出运行信息 subsample=0.8, # 每个决策树所用的子样本占总样本的比例(作用于样本) colsample_bytree=0.8, # 建立树时对特征随机采样的比例(作用于特征)典型值:0.5-1 objective='multi:softmax', # 多分类!!!!!! num_class=3, nthread=4, seed=27)print "training..."clf.fit(train_text_tfidf, train_y, verbose=True)fit_pred = clf.predict(test_text_tfidf)# 基于XGBoost自带接口# xgboost模型初始化设置dtrain=xgb.DMatrix(train_text_tfidf,label=train_y)dtest=xgb.DMatrix(test_text_tfidf)watchlist = [(dtrain,'train')]# booster:params={'booster':'gbtree', 'objective': 'multi:softmax',#多分类:'multi:softmax',二分类:'binary:logistic', 'num_class':14,#类别个数 'eval_metric': 'auc', 'max_depth':5, 'lambda':10, 'subsample':0.75, 'colsample_bytree':0.75, 'min_child_weight':2, 'eta': 0.025, 'seed':0, 'nthread':8, 'gamma':0.15, 'learning_rate' : 0.01}# 建模与预测:50棵树bst=xgb.train(params,dtrain,num_boost_round=50,evals=watchlist)ypred=bst.predict(dtest) # 设置阈值、评价指标y_pred = (ypred >= 0.5)*1print ('Precesion: %.4f' %metrics.precision_score(test_y,ypred,average='macro'))print ('Recall: %.4f' % metrics.recall_score(test_y,ypred,average='macro'))print ('F1-score: %.4f' %metrics.f1_score(test_y,ypred,average='macro'))print ('Accuracy: %.4f' % metrics.accuracy_score(test_y,ypred,average='macro'))print ('AUC: %.4f' % metrics.roc_auc_score(test_y,ypred,average='macro'))
import pandas as pdimport numpy as npfrom sklearn.ensemble import RandomForestClassifierfrom sklearn.model_selection import GridSearchCVfrom sklearn import cross_validation, metricsrf0 = RandomForestClassifier(oob_score=True, random_state=10)rf0.fit(train_text_tfidf,train_y)print rf0.oob_score_y_predprob = rf0.predict_proba(train_text_tfidf)[:,1]
需要安装依赖库lightgbm。
pip install lightgbm #pip install lightgbm==3.3.0#LightGBM官方文档:http://lightgbm.readthedocs.io/en/latest/Python-Intro.html
lightgbm库和XGBoost库的使用方式类似,相比XGBoost的优点可参考LightGBM核心解析与调参 - 掘金 (juejin.cn)。
这里给出推荐的使用方法:
from lightgbm import LGBMClassifierfrom sklearn.datasets import load_irisfrom lightgbm import plot_importanceimport matplotlib.pyplot as pltfrom sklearn.model_selection import train_test_splitfrom sklearn.metrics import accuracy_scoremodel = LGBMClassifier( max_depth=3, learning_rate=0.1, n_estimators=200, # 使用多少个弱分类器 objective='multiclass', num_class=3, booster='gbtree', min_child_weight=2, subsample=0.8, colsample_bytree=0.8, reg_alpha=0, reg_lambda=1, seed=0 # 随机数种子)model.fit(train_text_tfidf,train_y, eval_set=[(train_text_tfidf, train_y), (test_text_tfidf, test_y)], verbose=100, early_stopping_rounds=50)# 对测试集进行预测y_pred = model.predict(test_text_tfidf)#计算准确率accuracy = accuracy_score(test_y,y_pred)print('accuracy:%3.f%%'%(accuracy*100))# 显示重要特征plot_importance(model)plt.show()#accuracy: 90%
score = cross_val_score(clf,X,y,cv=skf,scoring='f1')print('f1 score:'+str(score)+'\n')
结合分层抽样和网格搜索超参数来确定最优模型:
from sklearn.model_selection import GridSearchCVfrom sklearn.model_selection import StratifiedKFold decision_tree_classifier = DecisionTreeClassifier() parameter_grid = {'max_depth': [1, 2, 3, 4, 5], 'max_features': [1, 2, 3, 4]} skf = StratifiedKFold(n_splits=10,shuffle=True,random_state=1)skf = skf.get_n_splits(train_text_tfidf, train_y)grid_search = GridSearchCV(decision_tree_classifier, param_grid=parameter_grid,cv=skf)#注意这里将cv设置为分层抽样交叉验证grid_search.fit(all_inputs, all_classes)
这里以随机森林和LightGBM的交叉验证+网格搜索为例进行实验。
param_test1 = {'n_estimators':range(10,71,10)}gsearch1 = GridSearchCV(estimator = RandomForestClassifier(min_samples_split=100,min_samples_leaf=20,max_depth=8,max_features='sqrt' ,random_state=10), param_grid = param_test1,cv=skf)gsearch1.fit(train_text_tfidf,train_y)gsearch2.cv_results_,gsearch1.best_params_, gsearch1.best_score_param_test2 = {'max_depth':range(3,14,2), 'min_samples_split':range(50,201,20)}gsearch2 = GridSearchCV(estimator = RandomForestClassifier(n_estimators= 70, min_samples_leaf=20,max_features='sqrt' ,oob_score=True, random_state=10), param_grid = param_test2, cv=skf)#注意这里将cv设置为分层抽样交叉验证gsearch2.fit(train_text_tfidf,train_y)gsearch2.cv_results_,gsearch2.best_params_, gsearch2.best_score_
from sklearn.datasets import load_irisimport lightgbm as lgbfrom sklearn.model_selection import GridSearchCV # Perforing grid searchfrom sklearn.model_selection import train_test_splitparameters = { 'max_depth': [15, 20, 25, 30, 35], 'learning_rate': [0.01, 0.02, 0.05, 0.1, 0.15], 'feature_fraction': [0.6, 0.7, 0.8, 0.9, 0.95], 'bagging_fraction': [0.6, 0.7, 0.8, 0.9, 0.95], 'bagging_freq': [2, 4, 5, 6, 8], 'lambda_l1': [0, 0.1, 0.4, 0.5, 0.6], 'lambda_l2': [0, 10, 15, 35, 40], 'cat_smooth': [1, 10, 15, 20, 35]}gbm = LGBMClassifier(max_depth=3, learning_rate=0.1, n_estimators=200, # 使用多少个弱分类器 objective='multiclass', num_class=3, booster='gbtree', min_child_weight=2, subsample=0.8, colsample_bytree=0.8, reg_alpha=0, reg_lambda=1, seed=0 # 随机数种子 )# 有了gridsearch我们便不需要fit函数gsearch = GridSearchCV(gbm, param_grid=parameters, scoring='accuracy', cv=skf)gsearch.fit(train_text_tfidf,train_y)
Datawhale零基础入门NLP赛事 - Task3 基于机器学习的文本分类
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。