法院项目实践随笔(3)——数据预处理

数据预处理

        项目一开始的原始数据,是一个个法院文书,全是中文字符,对于机器来说,是无法对中文字符进行计算处理的,自然就不能将原始数据直接塞到神经网络中训练,所以我们要对原始数据进行预处理,使它不仅能够被机器接受,还要保留原有的特征信息。在深度学习领域,Tensorflow的确有它的独到之处,在极客学院找了篇tensorflow的简单教程(MNIST机器学习入门),刚好也是用的卷积神经网络结构,简单实现了这个教程,算是对tensorflow和卷积神经网络都有了个实现经验。

        由于MNIST数据是图像,跟文本类型还是有区别的。对于图像,我们可以将每个像素映射成一个值,这样二维的图像就可以转换成一个二维矩阵,刚好适合将其放进神经网络中。对于文本,该怎么处理呢?简单了解了下NLP相关的知识,发现对于文本,现在的方法都是先将文本内容分词,然后给每一个词匹配一个向量,称之为词向量,这样每个词向量为一行,也可以构建一个文本的词向量矩阵。如何构建这样的一个词向量矩阵,或者是说,如何给每个词赋予一个词向量,这是我们接下来考虑的问题。

分词

        中文文本是一句一句的句子,为了给每个词赋予词向量,首先得将句子以词为单位进行划分,即分词。分词网上的工具有很多,比较常用的是中文结巴分词,它支持3中模式,精确模式,全模式和搜索引擎模式,我用的是精确模式。它支持多语言平台,我用的是它的python包,安装方式和下载路径在上面给的网址中有。主要用到它的分词,关键词抽取和词性标注的功能,由于jieba分词并没有句法分析功能,所以在项目往后推进的过程中,也会用到其他的分词工具和句法分析器,包括Stanford parser

NiuParserLTP

word2vec

        对于词的向量表示,现在分为2大类,一种是one-hot representation,具体说就是,如果一个文本中出现了200个不同的词,那么每个词的向量维度就是200,他们的表示就是在相应位置上为1,其他全为0,例如(1,0,0,0,0,0……)(0,1,0,0,0,0……)。这样的表示方法在词数少的时候可以,但是我们很容易想到,不同的词的个数多了之后,每一个向量的维度就会很长很长,这样对于机器来说,处理起来十分困难,为了解决这种问题,Hinton与1986年提出了一个新的构想——Distributed representation,它的原理是通过训练,将每一个词映射到一个固定维度的向量空间中,每个词表征为这个向量空间中的一个点,并通过引入距离的概念表现词与词之间的相似度。word2vec就是运用这种词向量表征方式,具体的原理和算法分析,可以参考这里

        了解了word2vec的基本原理,接下来就是要运用它,训练我们的语料库,构建词向量空间。这里我们用的是gensim中的word2vec方法,这是它的官方文档,我还参考了一篇国外的博客Word2vec Tutorial和国内响应的一篇知乎专栏基于 Gensim 的 Word2Vec 实践

# 引入 word2vec
from gensim.models import word2vec

# 引入日志配置
import logging

logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)

# 引入训练数据
raw_sentences = ["the quick brown fox jumps over the lazy dogs","yoyoyo you go home now to sleep"]
sentences = [s.encode('utf-8').split() for s in sentences]
# 如果是文件的话,必须是分好词的
sentences = word2vec.Text8Corpus('train')
# 多个文件下的操作
class MySentences(object):
    def __init__(self, dirname):
        self.dirname = dirname

    def __iter__(self):
        for fname in os.listdir(self.dirname):
            for line in open(os.path.join(self.dirname, fname)):
                yield line.split()

sentences = MySentences('/some/directory') # a memory-friendly iterator
# min_count表示出现频率小于此值的不计入词库,默认是5
model = word2vec.Word2Vec(sentences, min_count=10)

# size表示词向量维度,默认是100
model = word2vec.Word2Vec(sentences, size=200)

# workers表示并行训练的线程数,默认是1
model = word2vec.Word2Vec(sentences, workers=1)

# 模型保存和读取
model.save('train.model')
model1 = Word2Vec.load('train.model')
model.save_word2vec_format('text.model.bin', binary=True)
model1 = word2vec.Word2Vec.load_word2vec_format('text.model.bin', binary=True)

# 获取对应词向量
model['computer']  # raw NumPy vector of a wordarray([-0.00449447, -0.00310097,  0.02421786, ...], dtype=float32)

class gensim.models.word2vec.Word2Vec (sentences=None,size=100,alpha=0.025,window=5,min_count=5, max_vocab_size=None, sample=0.001,seed=1,workers=3,min_alpha=0.0001, sg=0, hs=0, negative=5,cbow_mean=1, hashfxn=<built-in function hash>,iter=5,null_word=0,trim_rule=None, sorted_vocab=1, batch_words=10000)

·  sentences:可以是一个·ist,对于大语料集,建议使用BrownCorpus,Text8Corpus或·ineSentence构建。
·  sg: 用于设置训练算法,默认为0,对应CBOW算法;sg=1则采用skip-gram算法。
·  size:是指特征向量的维度,默认为100。大的size需要更多的训练数据,但是效果会更好. 推荐值为几十到几百。
·  window:表示当前词与预测词在一个句子中的最大距离是多少
·  alpha: 是学习速率
·  seed:用于随机数发生器。与初始化词向量有关。
·  min_count: 可以对字典做截断. 词频少于min_count次数的单词会被丢弃掉, 默认值为5
·  max_vocab_size: 设置词向量构建期间的RAM限制。如果所有独立单词个数超过这个,则就消除掉其中最不频繁的一个。每一千万个单词需要大约1GB的RAM。设置成None则没有限制。
·  sample: 高频词汇的随机降采样的配置阈值,默认为1e-3,范围是(0,1e-5)
·  workers参数控制训练的并行数。
·  hs: 如果为1则会采用hierarchica·softmax技巧。如果设置为0(defau·t),则negative sampling会被使用。
·  negative: 如果>0,则会采用negativesamp·ing,用于设置多少个noise words
·  cbow_mean: 如果为0,则采用上下文词向量的和,如果为1(defau·t)则采用均值。只有使用CBOW的时候才起作用。
·  hashfxn: hash函数来初始化权重。默认使用python的hash函数
·  iter: 迭代次数,默认为5
·  trim_rule: 用于设置词汇表的整理规则,指定那些单词要留下,哪些要被删除。可以设置为None(min_count会被使用)或者一个接受()并返回RU·E_DISCARD,uti·s.RU·E_KEEP或者uti·s.RU·E_DEFAU·T的函数。
·  sorted_vocab: 如果为1(defau·t),则在分配word index 的时候会先对单词基于频率降序排序。
·  batch_words:每一批的传递给线程的单词的数量,默认为10000

构建词向量矩阵

        训练好词向量空间后,接下来做的就是对将文本处理成词向量矩阵。对于机器训练,我们希望每次传递给机器的训练数据都是规范化格式化的,这样机器可以批量处理,从而加快训练速度。这就要求我们,对于每一个文本,都处理成相同大小的矩阵。通过统计分析,我们发现每个文本分词后的词数在200词左右,当然也有比较少的和比较多的。为了构建合适的训练集,我们只选取了200词左右的文本作为训练对象,这样我们就可以将每一个训练文本处理成200*200的词向量矩阵:对于多于200词的,我们采取从中间截断的方法;对于少于200词的,我们采取补0的方法。

        在这个时候,我们发现,原始数据中包含有很多字符和少数乱码,这给我们匹配词向量带来很多麻烦,于是在分词的时候,我们通过识别编码和正则表达式,将字符和乱码剔除。

import re
quchu = "[^\u4E00-\u9FA5]"
result = re.sub(quchu, "", line)

然后将对每一个词匹配词向量,最后将处理好的矩阵保存到txt中。

def trans2txt(logger, sourcefile, targetfile, wordLen=200, wordCount=200):
    model = gensim.models.Word2Vec.load('result.model')
    f1 = open(sourcefile, "r")
    f2 = file(targetfile, "w")
    while 1:
        line = f1.readline()
        if line:
            a_old = np.zeros(wordLen, float)
            for i in range(0, wordCount):
                str_new, sep, str_rest = line.partition(',')
                str_utf8 = str_new.decode('utf-8')
                line = str_rest
                try:
                    a_new = model[str_utf8]
                except Exception, e:
                    a_new = np.zeros(wordLen, float)
                    logger.error(e.message)
                if i != 0:
                    a_old = np.vstack((a_old, a_new))
                else:
                    a_old = a_new
            m = np.asmatrix(a_old)
            m = m.reshape((1, wordLen * wordCount))
            np.savetxt(f2, m)
        else:
            break
    f1.close()
    f2.close()
这里用到的是python2,原因是存储模型的那台服务器比较渣,装不了包,懒得去捣鼓,直接用的2,后面自己做实验都用的3.



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值