数据读取
用pandas读取数据
train_df = pd.read_csv('data/train_set.csv', sep='\t')
print(train_df.head())
这里的read_csv
由两部分组成:
- 第一个参数是你数据文件的路径,根据自己的实际情况修改成绝对路径或者相对路径;
- 分隔符
sep
: 每列分割的字符,此处设置为\t
- 还有一个参数,这里面没用。
nrows
是此次读取文件的函数,限制读取的记录数量。如果nrows=100
代表读取文件的前100行。
读取数据的时候我遇到了一个问题,label和text之间总是有\t,以至于不能得到一个正常的DataFrame。我用其他的方法处理之后才得到如下数据:
label text
0 2 2967 6758 339 2021 1854 3731 4109 3792 4149 15...
1 11 4464 486 6352 5619 2465 4802 1452 3137 5778 54...
2 3 7346 4068 5074 3747 5681 6093 1777 2226 7354 6...
3 2 7159 948 4866 2109 5520 2490 211 3956 5520 549...
4 3 3646 3055 3055 2490 4659 6065 3370 5814 2465 5...
但是看过教程以后,只需一个sep='\t'
便解决了数据读取的问题。
数据分析
在读取完数据集以后,首先应该进行数据分析,这是比赛中拿到数据的一般步骤。文本数据是一种非结构化的数据,也许不需要做出很多的分析,但是通过数据分析可以找到一些规律。
至于找哪些规律,这个一般参加比赛多了更能准确找到思路。在此作为一个NLP的小小白,参考了教程的内容:
- 赛题数据中,新闻文本的长度是多少? 如果文本很长的话不利于训练,所以需要对文本进行分割;
- 数据集中类别是如何分布的,哪种类别最多,哪种类别最少;
- 数据集中字符是怎样分布的? (这个的出发点应该是找到标点符号,如果出现的频率覆盖了全部的新闻,估计就有可能是标点符号)
文本长度分析
数据集中每个text都是用字符之间都是空格分开的,所以可以统计字符的个数来得到每个句子的长度。首先分析了Text的类型:print(type(train_df['text'][0]))
得到是<class 'str'>
,因此可以直接使用split()
函数。统计代码及结果如下:
train_df['text_len'] = train_df['text'].apply(lambda x: len(x.split(' ')))
print(train_df['text_len'].describe())
统计结果:
count 200000.000000
mean 907.207110
std 996.029036
min 2.000000
25% 374.000000
50% 676.000000
75% 1131.000000
max 57921.000000
Name: text_len, dtype: float64
对新闻文本分析可以看出,平均每个新闻文本的长度是907,新闻最长是57921,最短是2.整体来看文本还是比较长的。统计文本长度的直方图如下:
_ = plt.hist(train_df['text_len'], bins=100)
plt.xlabel('Text char count')
plt.title("Histogram of char count")
plt.show()
大部分句子长度都在2000以内。
新闻类别分布
对新闻的类别进行分布统计,统计每类新闻的样本个数。
# 统计每类新闻样本个数
train_df['label'].value_counts().plot(kind='bar')
plt.title('News class count')
plt.xlabel("category")
plt.show()
从统计结果可以看出,数据集类别分布存在较为不均匀的情况。在训练集中科技类新闻最多,其次是股票类新闻,最少的新闻是星座新闻。
字符分布统计
要统计每个字符出现的次数,首先将所有文本进行拼接进而划分为字符,再对字符进行统计。
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])
从统计结果来看,训练集总共包括6869个字符,字符编号3750的出现的次数最多为7482224次,字符编号3133的出现的次数最少为1次。
**重点:**可以根据字符在每个句子中出现的情况反推出标点符号。下面统计了不同字符在句子中出现的次数。
# 统计不同字符在每个句子中出现的次数
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])
根据统计结果可以看出3750,900,648的覆盖率达到了99%(一共20W条数据),推断出这三个字符可能是标点符号。但是900和648出现了多次连续的情况,因此判断这两个都不能是句子的结束符号,因此大胆推测3750为句子的结束符号。
('3750', 197997)
('900', 197653)
('648', 191975)
作业:
- 假设字符3750,字符900和字符648是句子的标点符号,请分析赛题每篇新闻平均由多少个句子构成?
- 统计每类新闻中出现次数对多的字符
我在之前将每个文本以3750作为结束符进行了处理,将每篇新闻的句子数量保存到了sentence_num.csv
中,针对作业一:
# 求平均每篇新闻有多少个句子
col_name = ['sentence_num']
sen_num = pd.read_csv('data/sentence_num.csv',names=col_name)
sen_sum = sum(sen_num['sentence_num'])
sen_ave = sen_sum / sen_num.shape[0]
print('句子个数之和:{}'.format(sen_sum))
print('一共有{}篇新闻'.format(sen_num.shape[0]))
print('平均每篇新闻中句子个数为:{}'.format(sen_ave))
结果如下:
针对作业二,首先将数据按类别拼接到一起,
# 不同新闻分割,按标签排序
new_df = df.sort_values(by='label',ascending=True)
找出每个类别第一条记录的索引,再分别求出每类新闻出现次数最多的字符。
# label:index 1:38918,2:75863,3:107288,4:129421,5:144437,6:156669,7:166654,8:175495,9:183342,10:189220\
# 11:194140,12:197271,13:199092
拿体育新闻举例:
for i,row in sorted_df[75863:107288].iterrows():
text = str(row['text'])
text =text.split()
for j,word in enumerate(text):
word = int(word)
word_list.append(word)
# 去重
sorted_list,word_uni = np.unique(word_list, return_counts=True)
print(type(word_uni))
word_uni_list = word_uni.tolist()
sorted_list = sorted_list.tolist()
#出现对多的是一个符号,去掉
id_num_list = [sorted_list.index(i) for i in [3750,900,648]]
print(id_num_list)
for i in id_num_list:
del word_uni_list[i]
del sorted_list[i]
max_num = max(word_uni_list)
id_num = word_uni_list.index(max(word_uni_list))
max_word = sorted_list[id_num]
print("体育类新闻出现字符次数最多的个数:{}".format(max_num))
print("体育类新闻出现字符次数最多的字符:{}".format(max_word))
结果如下:
科技类新闻出现字符次数最多的个数:502377
科技类新闻出现字符次数最多的字符:3370
股票类新闻出现字符次数最多的个数:557924
股票类新闻出现字符次数最多的字符:3370
体育类新闻出现字符次数最多的个数:351374
体育类新闻出现字符次数最多的字符:7399
娱乐类新闻出现字符次数最多的个数:187649
娱乐类新闻出现字符次数最多的字符:6122
时政类新闻出现字符次数最多的个数:119816
时政类新闻出现字符次数最多的字符:4411
社会类新闻出现字符次数最多的个数:158747
社会类新闻出现字符次数最多的字符:6122
教育类新闻出现字符次数最多的个数:192903
教育类新闻出现字符次数最多的字符:6248
财经类新闻出现字符次数最多的个数:158280
财经类新闻出现字符次数最多的字符:3370
家居类新闻出现字符次数最多的个数:56590
家居类新闻出现字符次数最多的字符:6122
游戏类新闻出现字符次数最多的个数:46230
游戏类新闻出现字符次数最多的字符:7328
房产类新闻出现字符次数最多的个数:67544
房产类新闻出现字符次数最多的字符:3370
时尚类新闻出现字符次数最多的个数:18591
时尚类新闻出现字符次数最多的字符:4939
彩票类新闻出现字符次数最多的个数:51343
彩票类新闻出现字符次数最多的字符:4464