最近参加学校的一个数据分析比赛,因为自己前面自学了一些基本的机器学习算法,但其实还处于入门阶段,便参加了。选择了一道中文文本分类的题目。
今日头条用户画像
选题背景:
随着机器创作能力越来越强,今后社会媒体上将会产生越来越多的机器创作者自动生产的内容。有效识别出哪些是人类作者生产的内容,哪些是机器作者生产的内容(包括机器写作、机器翻译、机器自动摘要),对于媒体内容的审核、分发、推荐等,具有十分重要的意义。
题目概况
给定一个由今日头条提供的媒体内容文档构成的数据集,参赛队伍采用适当的算法,对每篇文档的作者进行身份识别,区分出该文档属于人类写作、机器写作、机器翻译和机器自动摘要中的哪一类。
需求描述
分析完成后,应提交分析报告。
提交分类模型源码。
数据集
训练集共包含97,512篇文档,文件名为t.txt,,每一行代表一篇文档,包含三个字段,依次为文档标签、文档内容和文档ID,Unicode编码,JSON格式,如下所示:
{"\u6807\u7b7e":"\u81ea\u52a8\u6458\u8981","\u5185\u5bb9":"\u5206\u6790\u4e2d\u56fd\u7ecf\u6d4e\uff0c\u8981\u770b\u8fd9\u8258\u5927\u8239\u65b9\u5411\u662f\u5426\u6b63\u786e\uff0c\u52a8\u529b\u662f\u5426\u5f3a\u52b2\uff0c\u6f5c\u529b\u662f\u5426\u5145\u6c9b\u3002\u53ea\u8981\u6295\u8d44\u8005\u5168\u9762\u4e86\u89e3\u4e2d\u56fd\u6539\u9769\u5f00\u653e\u4ee5\u6765\u7684\u7ecf\u6d4e\u53d1\u5c55\u5386\u7a0b\u3001\u8fd1\u671f\u4e2d\u56fd\u4e3a\u4fc3\u8fdb\u7ecf\u6d4e\u6301\u7eed\u7a33\u5b9a\u589e\u957f\u5236\u5b9a\u7684\u6218\u7565\u4ee5\u53ca\u4e2d\u56fd\u7ecf\u6d4e\u5404\u9879\u6570\u636e\u548c\u8d8b\u52bf\uff0c\u5c31\u4f1a\u4f5c\u51fa\u6b63\u786e\u5224\u65ad\u3002",“id”:0}
该数据打印出来为:
{‘标签’: ‘自动摘要’, ‘内容’: ‘分析中国经济,要看这艘大船方向是否正确,动力是否强劲,潜力是否充沛。只要投资者全面了解中国改革开放以来的经济发展历程、近期中国为促进经济持续稳定增长制定的战略以及中国经济各项数据和趋势,就会作出正确判断。’, ‘id’: 0}
因为数据集有点大,达到97512个样本,于是决定用深度学习框架跑结果,在Github上找到了一个开源的text-classification-cnn-rnn,按照它的官方demo实例跑是没有任何问题的,大家也可以试下它的代码。直接下载它给的训练子集,密码是:qfud。
但是怎么才能把自己的自定义数据运行上去呢,于是博主到处Google、百度,结果发现只有这一篇
cnn文本分类——运行代码text-classification-cnn-rnn-master路上遇到的坑
可以参考,问题是。。。。他连官方Demo跑出来都报错了啊。。。所以。。博主在参考了他的博客以及官方的文档后,重写一篇指引文件,方便后面的人查阅。也以免误导他人学习。ORZ(当然,,也可能是当时他的时间是2018年7月16日,所以大家在看博客的时候,也一定要注意博主发帖的时间,毕竟代码是不断更改的)
博主配置:
博主这里就不重复官方的教程跑demo了,具体的大家可以去看官方讲解。这里主要讲解下博主此次比赛如何使用自己的数据集在这个模型上的使用方法。首先数据集是一个
这个文件十分大。所以不能用常规方法点击打开,因此博主使用Python代码,一行行的打印句子。发现就像比赛题目概况一样,全是Unicode编码,最开始博主尝试改成UTF-8格式,发现不能成功。后来才知道有json库,可以直接帮助转码。。。下面是关于如何去处理这个数据集的代码:
import os, json
labels = ["自动摘要","机器作者","人类作者","机器翻译"]#创建的文件夹名,可以自定义自己的文本类别
for i in range(len(labels)):
path = "./"
path = path + labels[i]
os.mkdir(path)
#读取每一个训练集,将其放进对应文件夹内
f_obj = open('t.txt')
count = 0
while 1:
cur_example = f_obj.readline()
if cur_example == "":
break
cur_example = json.loads(cur_example)
label = cur_example['标签']
content = cur_example['内容']
exaID = cur_example['id']
fileName = label + "-" + str(exaID) + ".txt"
path = "./" + label + "/"
os.chdir(path)
with open(fileName, 'w',encoding='utf-8') as tmp_obj:
tmp_obj.write(content)
tmp_obj.close()
os.chdir("../")
count += 1
print(count)
f_obj.close()
代码的作用是将整个文件读取,并将每个不同的分类放在不同的文件夹内,这样方便后面模型的使用。(如果你们要用在自己的中文文本分类任务里,需要自己去调整创建的文件夹类别以及文件夹的命名,建议文件名是以类别+id来区分某一类文件夹里的文件)。
总之,你必须先将不同类别的文件放在不同的文件夹下面,这样方便后面的数据预处理。
分好类后,可以参考该图示
创建一个dddData文件夹,并将这四个文件夹放入dddData内,并把整个dddData文件夹放进你在Github上下载的文件夹内
进入helper文件夹内修改cnews_group.py文件。
修改部分源代码即可:(关于***.train.txt、***.test.txt、***.val.txt文件的命名,你可以自定义你想命名的,如果你改为了自己想要的文件名,请保证后面更改的代码也要跟着改进)
# f_train = open('data/cnews/cnews.train.txt', 'w', encoding='utf-8')
# f_test = open('data/cnews/cnews.test.txt', 'w', encoding='utf-8')
# f_val = open('data/cnews/cnews.val.txt', 'w', encoding='utf-8')
f_train = open('C:/Users/Syler/Desktop/text-classification-cnn-rnn/data/cnews/diyData.train.txt', 'w', encoding='utf-8')
f_test = open('C:/Users/Syler/Desktop/text-classification-cnn-rnn/data/cnews/diyData.test.txt', 'w', encoding='utf-8')
f_val = open('C:/Users/Syler/Desktop/text-classification-cnn-rnn/data/cnews/diyData.val.txt', 'w', encoding='utf-8')
关于count大于、小于的数值,建议你统计一下你的数据集的样本总数,然后第一个参数小于你总数的60%来取值,第二个参数按80%来取值。
if count < 14626:
f_train.write(category + '\t' + content + '\n')
elif count < 19502:
f_test.write(category + '\t' + content + '\n')
else:
f_val.write(category + '\t' + content + '\n')
如果你前面文件的命名格式没有更改,那么可以直接复制这个代码。可能路径不同,需要你去更改下。
if __name__ == '__main__':
# save_file('data/thucnews')
# print(len(open('data/cnews/cnews.train.txt', 'r', encoding='utf-8').readlines()))
# print(len(open('data/cnews/cnews.test.txt', 'r', encoding='utf-8').readlines()))
# print(len(open('data/cnews/cnews.val.txt', 'r', encoding='utf-8').readlines()))
save_file('C:/Users/Syler/Desktop/text-classification-cnn-rnn/dddData')
print(len(open('C:/Users/Syler/Desktop/text-classification-cnn-rnn/data/cnews/diyData.train.txt', 'r', encoding='utf-8').readlines()))
print(len(open('C:/Users/Syler/Desktop/text-classification-cnn-rnn/data/cnews/diyData.test.txt', 'r', encoding='utf-8').readlines()))
print(len(open('C:/Users/Syler/Desktop/text-classification-cnn-rnn/data/cnews/diyData.val.txt', 'r', encoding='utf-8').readlines()))
当你改完这三处代码后,你就可以运行下这段代码,如果不出问题的话,那么此时你的data文件夹里的cnews文件夹内会多出三个文件。即diyData.test.txt、diyData.trian.txt、diyData.val.txt。这时候别慌。。。不要听上个博主说的什么缺乏停用词。。根本不存在停用词的问题!!
进入data文件夹内,有一个cnews_loader.py的文件,进行修改。将你要分的类,进行补充或更改。
def read_category():
"""读取分类目录,固定"""
categories = ['机器翻译', '机器作者', '人类作者', '自动摘要']
这里需要进行CNN模型的调整参数。博主的水平暂时没有那么高,所以使用的是默认参数,如果有大佬知道怎么调超参可以更优的话,无视博主。这里因为博主只需要分4类,于是把num_classes的值修改为4即可。
class TCNNConfig(object):
"""CNN配置参数"""
embedding_dim = 64 # 词向量维度
seq_length = 600 # 序列长度
num_classes = 4 # 类别数
num_filters = 128 # 卷积核数目
kernel_size = 5 # 卷积核尺寸
vocab_size = 5000 # 词汇表达小
hidden_dim = 128 # 全连接层神经元
dropout_keep_prob = 0.5 # dropout保留比例
learning_rate = 1e-3 # 学习率
batch_size = 64 # 每批训练大小
num_epochs = 10 # 总迭代轮次
print_per_batch = 100 # 每多少轮输出一次结果
save_per_batch = 10 # 每多少轮存入tensorboard
最后修改run_cnn.py函数,将文件的命名改为前面生成的文件名。这里说下关于diyData.val.txt这个文件,这个文件是在你运行run_cnn.py的时候才会生成这个文件,所以没有的话,是不用担心的。
# train_dir = os.path.join(base_dir, 'cnews.train.txt')
# test_dir = os.path.join(base_dir, 'cnews.test.txt')
# val_dir = os.path.join(base_dir, 'cnews.val.txt')
# vocab_dir = os.path.join(base_dir, 'cnews.vocab.txt')
train_dir = os.path.join(base_dir, 'diyData.train.txt')
test_dir = os.path.join(base_dir, 'diyData.test.txt')
val_dir = os.path.join(base_dir, 'diyData.val.txt')
vocab_dir = os.path.join(base_dir, 'diyData.vocab.txt')
对了,有一个地方需要注意,关于模型的使用,有个地方可能会报错,大家需要额外注意,就是windows下的反斜杠和linux下的斜杠是不兼容的,因此可以使用这个代码进行修改。这里我修改的是predict.py文件中的一个地方。还有个文件也是需要修改的,如果是地址不对的错误,大家按照同样的方法便可以修复了。
# vocab_dir = os.path.join(base_dir, 'cnews.vocab.txt')
vocab_dir = os.path.join(base_dir, 'diyData.vocab.txt').replace('\\', '/')
最后,整个模型就可以使用了。只要前面没报错的话,就可以去命令行输入
python run_cnn.py train
进行训练。
再使用
python run_cnn.py test
进行测试训练集。
如果想使用在自定义的中文文本上运行,那么可以可以看下predict.py这个文件,稍微修改下便可以使用了。