我做的是中文新闻分类,新闻分类现有的较流行的语料库包括搜狗新闻语料库、T大的数据、复旦的数据等等。论文看得不算多,找数据的话随便看几篇就知道啦。链接不放了,随便一搜就找得到。
对了,吐槽一下搜狗新闻的语料。如果你搜教程的话,会发现很多博主都用的是搜狗语料,然而你也会发现,人家用的数据集跟你现在在搜狗实验室下下来的数据集不一样——前几年比较好用的数据集没了,现在的数据集处理起来非常之麻烦。。我吐了
这里说一下较理想的标准数据集地样子吧:
如果你拿到的是这样的数据集,那么恭喜你,你的工作量至少减少了一半多
跑数据一分钟,数据处理两小时可不是说说而已。
这份数据是我结合搜狗新闻和T大新闻数据整理自用的,8个类别,每类5000条文本,其中1000测试,4000训练。数据量比较适合做毕业论文这种小课题。已上传至CSDN资源,希望能帮后来者入门快一些。
停用词较常用的是哈工大停用词表,这里放一个github连接,作者总结了四份中文停用词表,挺全的。
愉快的心情。
如果你不幸要用搜狗新闻语料库,还要多一步,这里放一个转送门,有博主做了详细解释,不想看就直接看代码学习。
code
'''数据中为上述doc标签的集合,并不是标准的xml文件,首先将数据开头和结尾分别加上''和根标签。'''
# 修复xml格式
filePath = 'news_sohusite_xml.dat' #语料路径
#fileSeqWordDonePath = 'data/sougou.xml.parse.txt'# 分词后生成路径
#
fw=open(fileSeqWordDonePath, 'w', encoding='utf-8')
fw.write('')
with open(filePath, 'r', encoding='gb18030' ) as fileTrainRaw: #python3
for line in fileTrainRaw:
fw.write(line.replace('&','&')) #去除非法字符
fw.write('')
fw.close()
如果你的语料格式还保留了爬虫爬取是网页风格,那么就需先从url里提取出类别,content中取出文本内容。不难理解。
code
# -*- coding: utf-8 -*-
'''
该脚本用于将语料库新闻语料
转化为按照URL作为类别名、
content作为内容的txt文件存储
'''
'''生成原始语料文件夹下文件列表'''
def listdir(path, list_name):
for file in os.listdir(path):
file_path = os.path.join(path, file)
if os.path.isdir(file_path):
listdir(file_path, list_name)
else:
list_name.append(file_path)
'''字符数小于这个数目的content将不被保存'''
threh = 50
'''获取所有语料'''
list_name = []
listdir('data2/',list_name)
'''对每个语料'''
for path in list_name:
print(path)
file = open(path, 'rb').read().decode("utf8")
'''
正则匹配出url和content
'''
patternURL = re.compile(r'(.*?).sohu.com ', re.S)
patternCtt = re.compile(r'(.*?) ', re.S)
classes = patternURL.findall(file)
contents = patternCtt.findall(file)
'''
# 把所有内容小于30字符的文本全部过滤掉
'''
for i in range(contents.__len__())[::-1]:
if len(contents[i]) < threh:
contents.pop(i)
classes.pop(i)
'''
把URL进一步提取出来,只提取出一级url作为类别
'''
for i in range(classes.__len__()):
patternClass = re.compile(r'http://(.*?)/',re.S)
classi = patternClass.findall(classes[i])
classes[i] = classi[0]
#print(classes[i])
'''
按照RUL作为类别保存到samples文件夹中
'''
for i in range(classes.__len__()):
file = 'data/' + classes[i] + '.txt'
f = open(file,'a+',encoding='utf-8')
f.write(contents[i]+'\n') #加\n换行显示
这时你的数据应该是每一类在一个txt中了。
这么做有利有弊,
利在于一步到胃,你可以直接分词然后就上特征选择、分类器了
弊在于,如果你此时你还处于没有分训练集合测试集的境地。。那你就尴尬了,因为一般的方法(train_test_splite)无法在一个分完词的txt里操作
我当时真的醉了,辛辛苦苦大半天,一棍子砸在裆中间。蛋疼。
所以我这里其实是断了一环的,即如何在一个txt中分出训练测试集。
不过我查不到方法时,就换了思路。因为当时找数据集时就有两种情况,一种是这种每个类别一个大txt的,另一种是每个类别一个文档,每个文档中数千个小txt的,即我最终选择的版本,也是T大数据集的样子。
一般来讲为追求类别平衡,每个类别中的文本数量是相同的。
如果是低数量级的数据,训练集测试集比取37、28均可;如果是百万级别乃至更多时,其实取19乃至1:99效果会更好。
咱就做个毕设,4万条数据,取28就蛮好。
至于怎么分的?我能想到的一个是直接在循环里把一定数量的txt移到新文件夹里,一个是用上文提到的splite应该也行(我不太了解也没试过,有晓得的读者可以说说)
因为我得东拼西凑把5000条数据搞齐,所以我是用最笨的方法,即手工剪切粘贴。。你们别学我。
为方便后续分词和统计特征,把训练集中每个类别下的小txt合成一个大txt
这个咱会。
code
import os
import os.path
import time
time1 = time.time() # tik_tok_计时器
def MergeTxt(filepath, outfile): # 合并同一个文件夹下多个txt
'''
os.walk()可以得到一个三元tupple(parent, dirnames, filenames)
parent:起始路径
dirnames:起始路径下的文件夹
filenames:第三个是起始路径下的文件
函数从给定的rootdir进行遍历,此时parent = rootdir
将rootdir中的所有文件夹名,放入dirnames中,所有的文件名放入filenames中
从dirnames中选择第一个文件夹进行遍历,此时parent = rootdir / 1,接下来便是不断地进行迭代
'''
for parent, dirnames, filenames in os.walk(filepath):
k = open(parent + outfile, 'a+', encoding='utf-8') # 此时应该到了第2级目录,parent已变为二级
for filepath in filenames: # 遍历二级中的文件集
txtPath = os.path.join(parent, filepath) # txtpath就是所有文件夹的路径
f = open(txtPath, encoding='utf-8')
k.write(f.read() + "\n") # 换行写入
k.close()
print("finished")
if __name__ == '__main__':
filepath = "data_merge/train/"
outfile = ".txt"
MergeTxt(filepath, outfile)
time2 = time.time()
print(u'总共耗时:' + str(time2 - time1) + 's')
终于到了这一步,很关键但复杂的一步,但有了结巴,一切便索然无味了起来hhhh
果然科技的发展是为了让人变懒呢。懒是人类之光。
code
import jieba as jb
from os import path
import os
import time
tik=time.time()
d = path.dirname(__file__)
stopwords='data_standard/stopwords_all.txt' # 停用词表
filepath="data_merge/train/" # 待处理文本路径
outfile = 'data_merge/train_splited/' # 输出文件路径
# 如果是多级目录,请千万千万 记得 在最后加上 /
def jiebaClearText(text):
mywordlist= []
seg_list=jb.cut(text, cut_all=False) #jieba分词,默认模式
liststr = "/".join(seg_list) #先进行分词操作了,以 / 隔开
f_stop = open(stopwords, encoding='utf-8') #在这里加编码 utf-8
try:
f_stop_text = f_stop.read()
#f_stop_text = f_stop_text.decode('utf-8')#unicode(f_stop_text, 'utf-8')
finally:
f_stop.close()
f_stop_seg_list = f_stop_text.split('\n') #以\n为分隔的txt停用词表,将每个词保存为list中的元素
for myword in liststr.split('/'):
if not (myword.strip() in f_stop_seg_list) and len(myword.strip()) > 1:
mywordlist.append(myword)
return ' '.join(mywordlist)
for parent, dirnames, filenames in os.walk(filepath):
for filepath in filenames: # 遍历二级中的文件集
k = open(outfile + filepath, 'a+', encoding='utf-8') # 此时应该到了第2级目录,parent已变为二级
txtPath = os.path.join(parent, filepath) # txtpath就是所有文件夹的路径
f=open(txtPath,'r', encoding='utf-8').read()
k.write(jiebaClearText(f))
tok=time.time()
print(u'总共耗时:' + str(tok - tik) + 's')
如果用的是本文的数据集,只做最后一步就可了。
分完词之后就没了。你的数据就已经可以拿去给算法糟蹋了。
我的课题是特征选择算法研究,但没想到难点居然在数据预处理hhhh
当然,后面的我虽然已有思路,但还没做,只是觉得比预处理简单,也许却是望山跑死马呢。
但愿顺利,明天再更。