天池学习赛新闻文本分类(1)

文章对一个新闻分类赛题的数据进行了分析,包括新闻句子的平均长度约为872个字符,存在长文本;类别分布不均,科技和星座类新闻数量差异显著;每篇新闻平均含有77个句子。此外,还探讨了字符分布和可能的标点符号。
摘要由CSDN通过智能技术生成

一、赛题介绍

赛题以新闻数据为赛题数据,数据集报名后可见并可下载。赛题数据为新闻文本,并按照字符级别进行匿名处理。整合划分出14个候选分类类别:财经、彩票、房产、股票、家居、教育、科技、社会、时尚、时政、体育、星座、游戏、娱乐的文本数据。
赛题数据由以下几个部分构成:训练集20w条样本,测试集A包括5w条样本,测试集B包括5w条样本。为了预防选手人工标注测试集的情况,我们将比赛数据的文本按照字符级别进行了匿名处理。处理后的赛题训练数据如下:
在这里插入图片描述
在数据集中标签的对应的关系如下:

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

评价标准为类别f1_score的均值,选手提交结果与实际测试集的类别进行对比,结果越大越好。
计算公式:F1 = 2 * \frac{(precision * recall) }{(precision + recall)}
通过sklearn完成f1_score计算:

二、数据读取与数据分析

1.取小部分数据进行读取

import pandas as pd
train_df = pd.read_csv('train_set.csv', sep='\t', nrows=100)

2.句子长度分析

在赛题数据中每行句子的字符使用空格进行隔开,所以可以直接统计单词的个数来得到每个句子的长度。统计并如下:

%pylab inline
train_df['text_len'] = train_df['text'].apply(lambda x: len(x.split(' ')))
print(train_df['text_len'].describe())

结果如下:
在这里插入图片描述
这段代码输出了一个数据集的文本长度(text_len)统计信息,其中包括样本个数、均值、标准差、最小值、25%分位数、中位数、75%分位数和最大值。具体解释如下:

样本个数:该数据集包含的文本样本数量为 100。
均值:该数据集中所有文本的平均长度为 872.32。
标准差:该数据集中所有文本长度的标准差为 923.14,反映了数据分布的离散度。
最小值:该数据集中最短的文本长度为 64。
25%分位数:将所有文本长度从小到大排序后,在第 25% 的位置上的文本长度为 359.5,表示 25% 的文本长度小于等于 359.5。
中位数:将所有文本长度从小到大排序后,中间位置的文本长度为 598,即 50% 的文本长度小于等于 598。
75%分位数:将所有文本长度从小到大排序后,在第 75% 的位置上的文本长度为 1058,表示 75% 的文本长度小于等于 1058。
最大值:该数据集中最长的文本长度为 7125。

这些统计信息可以帮助我们了解数据集中文本长度的整体情况,进而进行相应的数据处理或建模工作,例如对长度较长的文本进行截断、对长度不均匀的数据进行分层抽样等,以提高建模的准确性和效率。

将句子长度绘制了直方图,可见大部分句子的长度都几种在2000以内:

_ = plt.hist(train_df['text_len'], bins=200)
plt.xlabel('Text char count')
plt.title("Histogram of char count")
#bins=200 表示将数据分割成200个箱子,也就是在 x 轴上画出了200个柱子

在这里插入图片描述

3.新闻类别分布

接下来可以对数据集的类别进行分布统计,具体统计每类新闻的样本个数。从统计结果可以看出,赛题的数据集类别分布存在较为不均匀的情况。在训练集中体育类新闻最多,其次是股票类新闻,最少的新闻是星座新闻。

# 统计各类新闻数量
class_counts = train_df['label'].value_counts()

# 定义颜色列表
colors = ['b', 'g', 'r', 'c', 'm', 'y', 'k', 'orange', 'brown', 'pink', 'purple', 'gray', 'olive', 'navy']

# 绘制柱状图,并指定颜色
class_counts.plot(kind='bar', color=colors)

# 添加图表标题和横轴标签
plt.title('News class count')
plt.xlabel("category")

# 显示图表
plt.show()

在这里插入图片描述

4.字符分布统计

接下来可以统计每个字符出现的次数,首先可以将训练集中所有的句子进行拼接进而划分为字符,并统计每个字符的个数。

从统计结果中可以看出,在训练集中总共包括2405个字,其中编号3750的字出现的次数最多,编号5034的字出现的次数最少。

from collections import Counter
all_lines = ' '.join(list(train_df['text']))
word_count = Counter(all_lines.split(" "))
word_count = sorted(word_count.items(), key=lambda d:d[1], reverse = True)

print(len(word_count))

print(word_count[0])

print(word_count[-1])
------------------------------------------
2405
('3750', 3702)
('5034', 1)

可以根据字在每个句子的出现情况,反推出标点符号。下面代码统计了不同字符在句子中出现的次数,其中字符3750,字符900和字符648在新闻的覆盖率接近99%,很有可能是标点符号。

from collections import Counter
train_df['text_unique'] = train_df['text'].apply(lambda x: ' '.join(list(set(x.split(' ')))))
all_lines = ' '.join(list(train_df['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])
-----------------------------------------------------
('3750', 99)
('900', 99)
('648', 96)

假设字符3750,字符900和字符648是句子的标点符号,接下来我们分析每篇新闻由多少个句子构成

#对 "text" 列中的每个单词列表使用了三次 count() 方法,以分别计算单词 "3750"、"900" 和 "648" 在其中出现的次数,并将这些次数相加得到总的出现次数。因此,最终生成的 DataFrame 包含两列数据,第一列是单词列表,第二列是标点的出现次数及句子个数。
df=pd.DataFrame({"text":train_df["text"]})
df["text"]=df["text"].apply(lambda x: x.split(" "))
df["count"]=df["text"].apply(lambda x: x.count("3750")+x.count("900")+x.count("648"))
df["count"].mean()
------------------------------
77.27

对于每类新闻中出现次数对多的字符进行统计

df2=pd.DataFrame({"label":train_df["label"],"text":train_df["text"]})
#利用三次replace替换掉标点符号
df2["text"]=df2["text"].apply(lambda x : x.replace("3750","").replace("900","").replace("648",""))
#去除空字符串
df2["text"]=df2["text"].apply(lambda x: [k for k in x.split(" ") if k.strip()])


groups = df2.groupby(by="label")

for name, group in groups:
    sum_list=[]
    for i in group["text"].tolist():
        sum_list+=i
    # 使用 Counter 函数统计每个数字出现的次数
    counter = Counter(sum_list)

    # 获取出现次数最多的数字和它出现的次数
    most_common_num, count = counter.most_common(1)[0]

    # 输出结果
    print(f"主题{name}出现次数最多的字符是 {most_common_num},出现了 {count} 次。")
----------------------------------------------------------------------
主题0出现次数最多的字符是 6122,出现了 179 次。
主题1出现次数最多的字符是 3370,出现了 211 次。
主题2出现次数最多的字符是 4704,出现了 225 次。
主题3出现次数最多的字符是 2465,出现了 65 次。
主题4出现次数最多的字符是 4464,出现了 40 次。
主题5出现次数最多的字符是 4939,出现了 66 次。
主题6出现次数最多的字符是 2555,出现了 297 次。
主题7出现次数最多的字符是 3370,出现了 134 次。
主题8出现次数最多的字符是 913,出现了 33 次。
主题9出现次数最多的字符是 3370,出现了 35 次。
主题10出现次数最多的字符是 2999,出现了 64 次。
主题11出现次数最多的字符是 5310,出现了 27 次。
主题12出现次数最多的字符是 4464,出现了 59 次。
主题13出现次数最多的字符是 1903,出现了 3 次。

三、数据分析结果

通过上述分析我们可以得出以下结论:

1.赛题中每个新闻包含的字符个数平均为872个,还有一些新闻字符较长;
2.赛题中新闻类别分布不均匀,科技类新闻样本量接近2w,星座类新闻样本量不到1k;
3.赛题中每篇新闻平均由77条句子构成;

通过分析可以发现数据的一些缺陷,每个新闻平均字符个数较多,可能需要截断,由于类别不均衡,可能会严重影响模型的精度。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值