一、赛题描述

赛题数据为新闻文本,并按照字符级别进行匿名处理。整合划分出14个候选分类类别:财经、彩票、房产、股票、家居、教育、科技、社会、时尚、时政、体育、星座、游戏、娱乐的文本数据。

赛题任务:赛题以自然语言处理为背景,要求选手对新闻文本进行分类,这是一个典型的字符识别问题

赛题数据由以下几个部分构成:训练集20w条样本,测试集A包括5w条样本,测试集B包括5w条样本。为了预防选手人工标注测试集的情况,我们将比赛数据的文本按照字符级别进行了匿名处理。处理后的赛题训练数据如下:

label text
6 57 44 66 56 2 3 3 37 5 41 9 57 44 47 45 33 13 63 58 31 17 47 0 1 1 69 26 60 62 15 21 12 49 18 38 20 50 23 57 44 45 33 25 28 47 22 52 35 30 14 24 69 54 7 48 19 11 51 16 43 26 34 53 27 64 8 4 42 36 46 65 69 29 39 15 37 57 44 45 33 69 54 7 25 40 35 30 66 56 47 55 69 61 10 60 42 36 46 65 37 5 41 32 67 6 59 47 0 1 1 68

在数据集中标签的对应的关系如下:

{'科技': 0, '股票': 1, '体育': 2, '娱乐': 3, '时政': 4, '社会': 5, '教育': 6, '财经': 7, '家居': 8, '游戏': 9, '房产': 10, '时尚': 11, '彩票': 12, '星座': 13}

赛题数据来源为互联网上的新闻,通过收集并匿名处理得到。因此选手可以自行进行数据分析,可以充分发挥自己的特长来完成各种特征工程,不限制使用任何外部数据和模型。
数据列使用\t进行分割,Pandas读取数据的代码如下:

train_df = pd.read_csv('../input/train_set.csv', sep='\t')

二、评测标准

评价标准为类别f1_score的均值,选手提交结果与实际测试集的类别进行对比,结果越大越好。

可以通过sklearn完成f1_score计算:

from sklearn.metrics import f1_score
y_true = [0, 1, 2, 0, 1, 2]
y_pred = [0, 2, 1, 0, 0, 1]
f1_score(y_true, y_pred, average='macro')

三、解题思路

赛题思路分析:赛题本质是一个文本分类问题,需要根据每句的字符进行分类。但赛题给出的数据是匿名化的,不能直接使用中文分词等操作,这个是赛题的难点。

因此本次赛题的难点是需要对匿名字符进行建模,进而完成文本分类的过程。由于文本数据是一种典型的非结构化数据,因此可能涉及到特征提取分类模型两个部分。为了减低参赛难度,我们提供了一些解题思路供大家参考:

  • 思路1:TF-IDF + 机器学习分类器

直接使用TF-IDF对文本提取特征,并使用分类器进行分类。在分类器的选择上,可以使用SVM、LR、或者XGBoost。

  • 思路2:FastText

FastText是入门款的词向量,利用Facebook提供的FastText工具,可以快速构建出分类器。

  • 思路3:WordVec + 深度学习分类器

WordVec是进阶款的词向量,并通过构建深度学习分类完成分类。深度学习分类的网络结构可以选择TextCNN、TextRNN或者BiLSTM。

  • 思路4:Bert词向量

Bert是高配款的词向量,具有强大的建模学习能力。

四、相关知识 - 文本表示方法

One-hot

这里的One-hot与数据挖掘任务中的操作是一致的,即将每一个单词使用一个离散的向量表示。具体将每个字/词编码一个索引,然后根据索引进行赋值。

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

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

N-gram与Count Vectors类似,不过加入了相邻单词组合成为新的单词,并进行计数。

如果N取值为2,则句子1和句子2就变为:

句子1:我爱 爱北 北京 京天 天安 安门
句子2:我喜 喜欢 欢上 上海

TF-IDF

TF-IDF 分数由两部分组成:第一部分是词语频率(Term Frequency),第二部分是逆文档频率(Inverse Document Frequency)。其中计算语料库中文档总数除以含有该词语的文档数量,然后再取对数就是逆文档频率。

TF(t)= 该词语在当前文档出现的次数 / 当前文档中词语的总数
IDF(t)= log_e(文档总数 / 出现该词语的文档总数)

五、代码展示

jupyter notebook代码如下:

import pandas as pd
import numpy as np
import os
from collections import Counter
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import RidgeClassifier
from sklearn.metrics import f1_scoreos.getcwd()# 读取数据
path='/Users/weiyi/Applications/jupyter_work/ml/datasets/news_text_classification/'
train = pd.read_csv(path+'train_set.csv', sep='\t')
test = pd.read_csv(path+'test_a.csv', sep='\t')# 1.数据分析
此步骤我们读取了所有的训练集数据,在此我们通过数据分析希望得出以下结论:
赛题数据中,新闻文本的长度是多少?
赛题数据的类别分布是怎么样的,哪些类别比较多?
赛题数据中,字符分布是怎么样的?# 数据探索
train.head()test.head()### 1.1句子长度分析
在赛题数据中每行句子的字符使用空格进行隔开,所以可以直接统计单词的个数来得到每个句子的长度。统计并如下:%pylab inline
train['text_len'] = train['text'].apply(lambda x: len(x.split(' ')))
print(train['text_len'].describe())对新闻句子的统计可以得出,本次赛题给定的文本比较长,每个句子平均由907个字符构成,最短的句子长度为2,最长的句子长度为57921。
下图将句子长度绘制了直方图,可见大部分句子的长度都几乎在2000以内。_ = plt.hist(train['text_len'], bins=200)
plt.xlabel('Text length')
plt.title("Histogram of text length")
plt.xlim(-0.5,7000) # x轴度量范围### 1.2新闻类别分布
接下来可以对数据集的类别进行分布统计,具体统计每类新闻的样本个数。train['label'].value_counts().plot(kind='bar')
plt.title('News class count')
plt.xlabel("category")在数据集中标签的对应的关系如下:{'科技': 0, '股票': 1, '体育': 2, '娱乐': 3, '时政': 4, '社会': 5, '教育': 6, '财经': 7, '家居': 8, '游戏': 9, '房产': 10, '时尚': 11, '彩票': 12, '星座': 13}从统计结果可以看出,赛题的数据集类别分布存在较为不均匀的情况。在训练集中科技类新闻最多,其次是股票类新闻,最少的新闻是星座新闻。### 1.3字符分布统计
接下来可以统计每个字符出现的次数,首先可以将训练集中所有的句子进行拼接进而划分为字符,并统计每个字符的个数。从统计结果中可以看出,在训练集中总共包括6869个字,其中编号3750的字出现的次数最多,编号3133的字出现的次数最少。all_lines = ' '.join(list(train['text']))
word_count = Counter(all_lines.split(" "))
word_count
# dict.items() 返回可遍历的(键, 值) 元组数组
# key -- 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。
word_count = sorted(word_count.items(), key=lambda x:x[1], reverse = True)  # reverse = True降序print(len(word_count))print(word_count[0])print(word_count[-1])
word_count这里还可以根据字在每个句子的出现情况,反推出标点符号。下面代码统计了不同字符在句子中出现的次数(新闻次数),其中字符3750,字符900和字符648在20w条新闻的覆盖率接近99%,很有可能是标点符号。train['text_unique'] = train['text'].apply(lambda x: ' '.join(list(set(x.split(' ')))))
all_lines = ' '.join(list(train['text_unique']))
word_count = Counter(all_lines.split(" "))
word_count = sorted(word_count.items(), key=lambda d:int(d[1]), reverse = True)print(word_count[0])print(word_count[1])print(word_count[2])# 问题1: 假设字符900是句号,分析赛题每篇新闻平均由多少个句子构成?   len() 返回元素个数或字符长度
train['text_juzilen'] = train['text'].apply(lambda x:len(x.split(' 900 ')))
train['text_juzilen'].mean()# 问题2: 统计每类新闻中出现次数最多的字符
label_text = train.groupby('label')['text'].apply(lambda x: ' '.join(list(x)))# 聚合之后为series,不能进行split操作,先转datafram
new_label_text = label_text.reset_index()
new_label_textlabel_word_count = new_label_text['text'].apply(lambda x:Counter(x.split(' ')))  # Series# label_word_count = sorted(label_word_count.items(), key=lambda x:x[1], reverse = True)
# label_word_count### 数据分析的结论通过上述分析我们可以得出以下结论:赛题中每个新闻包含的字符个数平均为1000个,还有一些新闻字符较长;
赛题中新闻类别分布不均匀,科技类新闻样本量接近4w,星座类新闻样本量不到1k;
赛题总共包括7000-8000个字符;
通过数据分析,我们还可以得出以下结论:每个新闻平均字符个数较多,可能需要截断;由于类别不均衡,会严重影响模型的精度;# 2.模型预测# 方法1:
# ngram_range: tuple 有时候我们觉得单个的词语作为特征还不足够,能够加入一些词组更好,就可以设置这个参数,如(1,2)下面允许词表使用1个词语,或者2个词语的组合
# max_feature: int 在大规模语料上训练TFIDF会得到非常多的词语,如果再使用了上一个设置加入了词组,那么我们词表的大小就会爆炸。出于时间和空间效率的考虑,可以限制最多使用多少个词语,模型会优先选取词频高的词语留下
tfidf = TfidfVectorizer(ngram_range=(1,3), max_features=3000)
train_test = tfidf.fit_transform(train['text'])clf = RidgeClassifier()
clf.fit(train_test[:10000], train['label'].values[:10000])val_pred = clf.predict(train_test[10000:])
print(f1_score(train['label'].values[10000:], val_pred, average='macro'))# 方法2: (利用网格搜索)
tfidf = TfidfVectorizer(ngram_range=(1,3), max_features=3000)
X_train = tfidf.fit_transform(train['text'])# 训练集、验证集划分
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(X_train, train['label'], test_size=0.2)# 模型训练
clf = RidgeClassifier()
clf.fit(x_train, y_train)# 模型预测,利用验证集预测
y_pred = clf.predict(x_test)# F1评价函数
print(f1_score(y_test, y_pred, average='macro'))

【天池学习赛】零基础入门NLP - 新闻文本分类相关推荐

  1. Task01——零基础入门NLP - 新闻文本分类之赛题理解

    本篇目标 首先本篇文章会对赛题进行介绍以及个人对赛题的理解,带大家接触NLP的预处理.模型构建和模型训练等知识点. 赛题介绍 赛题名称:零基础入门NLP - 新闻文本分类 赛题任务:赛题以自然语言处理 ...

  2. 天池零基础入门NLP - 新闻文本分类Top1方案的bert4torch复现

    天池有些长期比赛可以练习玩玩(还可以继续提交),于是试了下简单的新闻文本分类任务,Top1的解决方案思路是"预训练+fgm+交叉验证模型融合",代码是基于bert4keras的,本 ...

  3. 零基础入门NLP - 新闻文本分类,正式赛第一名方案分享

    零基础入门NLP - 新闻文本分类,正式赛第一名方案分享:https://mp.weixin.qq.com/s/7WpZUqdlItBToLYuRLm44g

  4. 【初学者入门】零基础入门NLP - 新闻文本分类

    序言 从今天开始入门学习NLP,虽然有点晚,但是我觉得任何时候都值得开始,尤其是面对你去感兴趣的事情.今天的任务是 [零基础入门NLP - 新闻文本分类],这是天池大赛中的入门级算法比赛,入口链接请自 ...

  5. 零基础入门NLP - 新闻文本分类

    本文是对阿里云新人竞赛中的"零基础入门NLP - 新闻文本分类"解体过程进行的记录,目前仅使用了textCNN模型进行预测,后续还会考虑使用LSTM进行对比. 赛题数据 赛题以新闻 ...

  6. java统计文本中英文单词个数split_零基础入门NLP - 新闻文本分类Task2(天池入门赛)...

    本章主要内容是主要是通过pandas模块来进行数据分析.(注:文章只是对天池入门赛课件的学习) 一.学习目标 1.学习使用pandas读取赛题规律 2.分布赛题数据的分布规律 二.数据读取 使用pan ...

  7. 【学习笔记】零基础入门NLP - 新闻文本分类实战

    赛题理解   首先要理解赛题的背景及描述--赛题以新闻数据为赛题数据,数据集报名后可见并可下载.赛题数据为新闻文本,并按照字符级别进行匿名处理.整合划分出14个候选分类类别:财经.彩票.房产.股票.家 ...

  8. Task02——零基础入门NLP - 新闻文本分类之数据读取与分析

    本期目标 学习使用Pandas读取赛题数据 分析赛题数据的分布规律 数据读取 import pandas as pd train_df=pd.read_csv('./train_set.csv/tra ...

  9. 阿里云天池 零基础入门NLP - 新闻文本分类 2种做法,F1=0.87

    problem 1.赛题理解 数据集: 在NLP_data_list_0715.csv中,有三个链接. 分别可以下载训练集,测试集A,测试样例. f1_score介绍: F1分数(F1-score)是 ...

最新文章

  1. 无线局域网安装与调试(Wireless LAN installation and commissioning)
  2. 【Python基础】14_Python中的TODO注释
  3. uboot更改gpio电平_ECBM系列教程4:单片机的手和脚——GPIO
  4. 淮安中专学计算机哪个学校好,2021淮安初中十强排名 哪些初中比较好
  5. [vue] SPA单页面的实现方式有哪些?
  6. 简述网络调研的作用_利用龙伯球透镜天线提升高铁4G网络覆盖
  7. 最长重复子串_3. 无重复字符的最长子串
  8. 小D课堂 - 新版本微服务springcloud+Docker教程_4-06 Feign核心源码解读和服务调用方式ribbon和Feign选择...
  9. 惠普、华三、华为、戴尔、联想服务器维保查询地址汇总
  10. 关于excel文件损坏的处理方法
  11. 原生开发什么意思_原生App是什么意思
  12. 在利用DXP2004软件进行PCB设计时——自制元器件封装如何添加网络(布线问题)
  13. 使用NVM安装升级PNPM报错的问题
  14. 编程题:首尾相连的字符串
  15. 网络安全入门学习资源汇总
  16. 番茄ToDo帮助文档
  17. 没有了耳机接口,怎么让手机同时支持充电、听歌?USB-C音频方案了解一下
  18. UBUNTU 12.04 3D 特效设置(三)
  19. 清明时节,思念友人张锦文
  20. 怎样将「插件化」接入到项目之中?

热门文章

  1. 纸质问卷和网络问卷的优劣势
  2. 助航灯光监控系统服务器,机场助航灯光计算机监控系统的设计与实现
  3. 7-14 电话聊天狂人 C语言
  4. Android——体重计算器
  5. android 弹球碰撞
  6. WEBSTORM 2018版本破解的教程
  7. Photoshop的评价
  8. 公司企业怎么设置域名邮箱?
  9. 绵阳市塔子坝污水处理厂的污水处理工艺调研报告
  10. Android区分高低端机型