2020-03-14 08:42:43 weixin_32759777 阅读数 3747
  • 易语言入门精品课程

    中文编程.易语言入门精品课程.讲师结合十几年的易语言学习经验.站在纯新手角度详细带你进入中文编程易语言的世界.本教程采用循序渐进原则构造.结合大量实战例子.相比于传统教程.学习本教程.更能增加编程逻辑.

    154 人正在学习 去看看 马龙

声音是一种人类的表达方式,也是一种语言,可以使用语言的方式表达出来
任何信息 因为表达的方式的不同,会表现出 理解程度上的难易
所以如果声音转文字,一定是带感情描述的转而不是,直白的转文字
文字转语音也是一样的,要带着全部的信息转换

首先要学一下中文的情感和环境描述 为什么要说中文,因为中文对这方面是由表达丰富性的
每种语言的表达优势决定了使用人群的某些东西或者是理论发展的很好,
中国文字更加的擅长表达情感和环境语气描述,更具有文学性

英文和数字更具有数理表达能力

这一切都可以从世界历史可证

首先学习一下
说话语气描写的词语
温和 热情 亲切 严厉 生硬 肯定 否定 冷淡 安慰 取笑 挖苦 狡辩 分辨 讪笑 嗤笑
训斥 追问 询问 忠告 命令 幽默 夸耀 感激 盘问 大发雷霆 破口大骂 语无伦次
据理力争 反唇相讥 恶语伤人 自吹自擂 出言不逊 豪言壮语 疾言厉色 一一话别
言辞恳切 凯凯而谈 夸夸其谈 谆谆告诫 绝妙句子

基本就是开心,悲伤,严肃,和气

所以最基本的语言识别应该识别出这个人说话的语气
还有这个人说话中所有的代词所指向的真正的事物或人物,事件,那么这些被指向的对象,来自之前的聊天记录,和以往的共同经历,经历一样但不一定是同时同地,

所以要想做好聊天机器人 首先语气要识别出来,其次是将指向对象弄清楚,自根据自己的性格处事方法,回答此事件,性格和处事方法完全可以通过一个人物的描写,加上真实的例子,加以模仿,即根据自己过往的回答或者是书中参考过来的或是生活中看或听到他人回答的 综合的给出说话的语气 和 说话的节奏(音色)这样才能非语无伦次 非上句不接下句的 有感情的 聊天

语音智能 并不是机械的翻译,和无厘头的聊天,而是有逻辑有感情的聊天
为什么现在语音聊天这么二 这是因为所有的解决方案都是来自英文,并没有一个针对中文的方案来处理,外国人说话基本是波澜不惊,可中国人的情感丰富
依赖一个不同语言的解决方案自然是不能 表达其逻辑性和情感的

所以本人猜想一下解决方案
最后时将语音智能变成真正的智能

要达到有感情有逻辑的聊天需要实现两种功能
其中一种功能 是中文逻辑解释器,和python一样一个面向对象的语言自然要解释器
还需要一个可以完成自然的语气判定和识别的生成网络

2019-10-30 20:18:50 sd4567855 阅读数 262
  • 易语言入门精品课程

    中文编程.易语言入门精品课程.讲师结合十几年的易语言学习经验.站在纯新手角度详细带你进入中文编程易语言的世界.本教程采用循序渐进原则构造.结合大量实战例子.相比于传统教程.学习本教程.更能增加编程逻辑.

    154 人正在学习 去看看 马龙

自然语言与编程语言

  1. 自然语言中词汇比编程语言中词汇丰富。
  2. 自然语言是非结构化,编程语言是结构化的。结构化:信息具有明确的结构关系。
  3. 自然语言含有大量歧义。
  4. 容错性。
  5. 易变性。
  6. 简略性。

自然语言处理层次

  1. 语音、图像、文本,其中文本是重中之重。
  2. 词法分析:将文本分割为有意义的词语(中文分词),确定每个词语的类别和浅层的歧义消除(词性标注),识别出专有名词(命名实体识别)。
  3. 信息抽取。
  4. 文本分类、文本聚类。
  5. 句法分析。
  6. 语义分析:确定一个词在语境中的含义,而不是词性(词义消除),标注句子中的谓语和其他成分的关系(语义角色标注),分析句子中词语之间的语义关系(语义依存分析)。

自然语言处理的流派

  1. 基于规则的专家系统
  2. 基于统计的学习方法
  3. 传统方法与深度学习

机器学习

  1. 模型:被学习的算法。
  2. 特征。
  3. 数据集/语料库。
  4. 监督学习。
  5. 无监督学习。
  6. 半监督学习。

语料库

  1. 中文分词语料库
  2. 词性标注语料库
  3. 命名实体识别语料库
  4. 词法分析语料库
  5. 文本分类语料库
2017-07-25 15:45:38 Irving_zhang 阅读数 9150
  • 易语言入门精品课程

    中文编程.易语言入门精品课程.讲师结合十几年的易语言学习经验.站在纯新手角度详细带你进入中文编程易语言的世界.本教程采用循序渐进原则构造.结合大量实战例子.相比于传统教程.学习本教程.更能增加编程逻辑.

    154 人正在学习 去看看 马龙

前面几章介绍了卷积神经网络在自然语言处理中的应用,这是因为卷积神经网络便于理解并且易上手编程,大多教程(比如tensorflow的官方文档就先CNN再RNN)。但RNN的原理决定了它先天就适合做自然语言处理方向的问题(如语言模型,语音识别,文本翻译等等)。因此接下来一段时间应该会着重研究RNN,LSTM,Attention等在NLP的应用及其tensorflow实现。

在介绍本篇文章之前,先推荐几篇学习内容:
语言模型部分:
1、CS224d 第四篇notes,首先讲语言模型的问题,然后推导了RNN、biRNN和LSTM。比99%的中文博客要靠谱。
2、language model and word2vec,前半部分是语言模型,后半部分介绍了Skip-gram等模型,并引入word2vec。
RNN和LSTM部分:
1、The Unreasonable Effectiveness of Recurrent Neural Networks 该文主要介绍了RNN在NLP中的应用,很直观。
2、Understanding LSTM Networks LSTM过程中很完美的公式,相信看一遍就能记住。
3、2的中文版 对自己英文不自信的同学可以看这个译文。

本篇文章实现基于字符的RNN语言模型,源自于Understanding LSTM Networks,在该篇文章中也附有github的网址,不过是基于Torch实现的,在github上有人对其使用tensorflow重写,实现了基于字符的语言模型,我们今天就来介绍这个代码

数据处理

数据处理两个最重要的工作
1. 将文本格式的文件转化为np格式的数组。首先构建字符或者单词的字典embedding_dic,字典的key为字符或者单词,value为该字符或单词对应的索引。其次要构造字符或者单词表embedding_w,每一行是一个字符或者单词的词向量(比如one-hot编码或者word2vec),对应的行标即为该单词的索引。
2. 生成next_batch,这里要对训练的过程进行feed的格式进行考虑,确保与占位符声明的tensorshape一致。在将所有的训练集遍历过一次以后,需要将训练集进行重排permutation。

源代码中将seq_length和batches都设置为50,这样不方便观察tensor的变化,因此在下面的代码中,我会将seq_length设置为100(只需要在train文件中更改配置参数即可)。因此一些主要参数为:

tensor_size = 1115000 #实际为11153941115000为取整之后的结果
batch_size = 50
seq_length = 100
num_batches = 223

在源码中,po主将所有的字符存为vocab.pkl,将input.txt中的所有字符存为data.npy。这样如果之前已经有这两个文件,那么直接读取preprocessed的文件就行了,就可以不用再处理文本了。该源码中采用的数据集为莎士比亚作品集,是一个很小的数据集,但当数据集很大时,就可以节省很多时间了。这是可以借鉴的一个点。

po主通过collections.Counter、zip、map等几个函数,就将文本处理的第一步工作做完,这是该段代码可以借鉴的第二个点。第二步要创建next_batch,和我们之前使用start和end两个指针不同,该段代码直接对batches进行了分割,然后使用一个pointer指针指向下一个块儿就行了。详细信息代码中已经添加了中文注释。

# coding=utf-8
import codecs
import os
import collections
from six.moves import cPickle
import numpy as np


class TextLoader():
    def __init__(self, data_dir, batch_size, seq_length, encoding='utf-8'):
        self.data_dir = data_dir
        self.batch_size = batch_size
        self.seq_length = seq_length
        self.encoding = encoding

        input_file = os.path.join(data_dir, "input.txt")
        vocab_file = os.path.join(data_dir, "vocab.pkl")
        tensor_file = os.path.join(data_dir, "data.npy")

        if not (os.path.exists(vocab_file) and os.path.exists(tensor_file)):
            print("reading text file")
            self.preprocess(input_file, vocab_file, tensor_file)
        else:
            print("loading preprocessed files")
            self.load_preprocessed(vocab_file, tensor_file)
        self.create_batches()
        self.reset_batch_pointer()

    # 当第一次训练时执行此函数,生成data.npy和vocab.pkl
    def preprocess(self, input_file, vocab_file, tensor_file):
        with codecs.open(input_file, "r", encoding=self.encoding) as f:
            data = f.read()
        # 统计出每个字符出现多少次,统计结果总共有65个字符,所以vocab_size = 65
        counter = collections.Counter(data)
        # 按键值进行排序
        count_pairs = sorted(counter.items(), key=lambda x: -x[1])
        # 得到所有的字符
        self.chars, _ = zip(*count_pairs)
        self.vocab_size = len(self.chars)
        # 得到字符的索引,这点在文本处理的时候是值得借鉴的
        self.vocab = dict(zip(self.chars, range(len(self.chars))))
        # 将字符写入文件
        with open(vocab_file, 'wb') as f:
            cPickle.dump(self.chars, f)
        # 使用map得到input文件中1115394个字符对应的索引
        self.tensor = np.array(list(map(self.vocab.get, data)))
        np.save(tensor_file, self.tensor)

    # 如果不是第一次执行训练,那么载入之前的字符和input信息
    def load_preprocessed(self, vocab_file, tensor_file):
        with open(vocab_file, 'rb') as f:
            self.chars = cPickle.load(f)
        self.vocab_size = len(self.chars)
        self.vocab = dict(zip(self.chars, range(len(self.chars))))
        self.tensor = np.load(tensor_file)
        self.num_batches = int(self.tensor.size / (self.batch_size *
                                                   self.seq_length))

    def create_batches(self):
        # tensor_size = 1115000 batch_size = 50, seq_length = 100
        # num_batches = 223
        self.num_batches = int(self.tensor.size / (self.batch_size *
                                                   self.seq_length))

        # When the data (tensor) is too small,
        # let's give them a better error message
        if self.num_batches == 0:
            assert False, "Not enough data. Make seq_length and batch_size small."

        self.tensor = self.tensor[:self.num_batches * self.batch_size * self.seq_length]
        xdata = self.tensor
        ydata = np.copy(self.tensor)
        # ydata为xdata的左循环移位,例如x为[1,2,3,4,5],y就为[2,3,4,5,1]
        # 因为y是x的下一个字符
        ydata[:-1] = xdata[1:]
        ydata[-1] = xdata[0]
        # x_batches 的 shape 就是 223 × 50 × 100
        self.x_batches = np.split(xdata.reshape(self.batch_size, -1),
                                  self.num_batches, 1)
        self.y_batches = np.split(ydata.reshape(self.batch_size, -1),
                                  self.num_batches, 1)

    def next_batch(self):
        x, y = self.x_batches[self.pointer], self.y_batches[self.pointer]
        self.pointer += 1
        return x, y

    def reset_batch_pointer(self):
        self.pointer = 0

模型构建

RNN不太好理解的就是模型构建部分,几个重要的函数在下面的博客都有说明。
1、使用TensorFlow实现RNN模型入门篇2–char-rnn语言建模模型
2、解读tensorflow之rnn
理解了这几个函数,我们开始看代码。占位符placeholder有两个,分别命名为self.input_data和self.targets,值得一提的是,由于我们现在要训练的模型是language model,也就是给一个字符,预测最有可能的下一个字符,因此input和output是同型的,并且output是input的左移位,这在数据处理的时候已经提到过。placeholder只存储一个batch的data,input接收的是该字符在self.vocab中对应的index(后续会将index转成word_ embedding),每次接收一个seq_length的字符,那么,input shape=[batch_size, num_steps]。
注意:此时的num_steps,即为RNN可以回溯的步长,在该例子中,num_steps=seq_length=100。

为了解释方便,我将模型的主要部分用下图表示。
1. 首先看图1,input_shape为[batch_size, seq_length],通过lookup_embedding函数以后shape为[batch_size, seq_length, rnn_size]。需要注意的是,图4中的一个圈代表RNNcell,里边有很多神经元组成。
2. 图2中的rnn_size就是图4中一个RNNcell中神经元的个数。
3. 图2到图3的split函数,以1轴进行分割(即以seq进行分割,0轴为batch),分成图3所示一片一片的形式,再通过squeeze函数,每一片的大小变为[batch_size, rnn_size]。共有seq_length=100片。
4. 然后将每一片送入图4中的一个num_step中,上文已经说明num_steps=seq_length=100。接下来就可以开始进行训练了。此源码中的num_layers=2,因此是一个二层的RNN网络,在图4中已经画出。
这里写图片描述

有了上述图片的解释,代码应该不难看懂:

# coding=utf-8
import tensorflow as tf
from tensorflow.contrib import rnn
from tensorflow.contrib import legacy_seq2seq


class Model():
    def __init__(self, args, training=True):
        self.args = args
        if not training:
            args.batch_size = 1
            args.seq_length = 1

        if args.model == 'rnn':
            cell_fn = rnn.BasicRNNCell
        elif args.model == 'gru':
            cell_fn = rnn.GRUCell
        elif args.model == 'lstm':
            cell_fn = rnn.BasicLSTMCell
        elif args.model == 'nas':
            cell_fn = rnn.NASCell
        else:
            raise Exception("model type not supported: {}".format(args.model))

        # 二层RNN,需要将rnn_size作为参数传入到rnn_cell中
        cells = []
        for _ in range(args.num_layers):
            cell = cell_fn(args.rnn_size)
            if training and (args.output_keep_prob < 1.0 or args.input_keep_prob < 1.0):
                cell = rnn.DropoutWrapper(cell,
                                          input_keep_prob=args.input_keep_prob,
                                          output_keep_prob=args.output_keep_prob)
            cells.append(cell)

        # 通过cells列表,构建多层RNN,函数具体的解释可以看官网或者上文推荐的博客
        self.cell = cell = rnn.MultiRNNCell(cells, state_is_tuple=True)

        # 占位符的shape,图中已经解释清楚
        self.input_data = tf.placeholder(
            tf.int32, [args.batch_size, args.seq_length])
        self.targets = tf.placeholder(
            tf.int32, [args.batch_size, args.seq_length])
        self.initial_state = cell.zero_state(args.batch_size, tf.float32)

        # 定义需要训练的权重和偏置,因为需要和[batch,rnn_size]大小的split片相乘,
        # 所以需要定义shape为[args.rnn_size, args.vocab_size]
        with tf.variable_scope('rnnlm'):
            softmax_w = tf.get_variable("softmax_w",
                                        [args.rnn_size, args.vocab_size])
            softmax_b = tf.get_variable("softmax_b", [args.vocab_size])

        # 嵌入层,随机进行初始化
        embedding = tf.get_variable("embedding", [args.vocab_size, args.rnn_size])
        inputs = tf.nn.embedding_lookup(embedding, self.input_data)

        # dropout beta testing: double check which one should affect next line
        if training and args.output_keep_prob:
            inputs = tf.nn.dropout(inputs, args.output_keep_prob)

        # split函数,将图2变至图3的很多片,方便传入RNNcell
        # 即[batch_size, seq_length, rnn_size]-->[batch_size, 1, rnn_size]
        inputs = tf.split(inputs, args.seq_length, 1)
        # squeeze函数,将大小为1的维度去掉,因此每一片的维度从[batch_size,1,rnn_size]
        # 变为[batch_size,rnn_size]
        inputs = [tf.squeeze(input_, [1]) for input_ in inputs]

        # loop函数连接num_steps步的rnn_cell,将h(t-1)的输出prev做变换然后传入h(t)作为输入
        def loop(prev, _):
            prev = tf.matmul(prev, softmax_w) + softmax_b
            prev_symbol = tf.stop_gradient(tf.argmax(prev, 1))
            return tf.nn.embedding_lookup(embedding, prev_symbol)

        """
        该函数实现了一个简单的多层rnn模型。上面的MultiRNNCell函数构造了一个时间步的多层rnn,
        本函数则实现将其循环num_steps个时间步。
        :param decoder_inputs:输入列表,是一个长度为num_steps的列表,
                            每个元素是[batch_size, input_size]的2-D维的tensor
        :param initial_state:初始化状态,2-D的tensor,shape为 [batch_size x cell.state_size].
        :param cell:RNNCell
        :param loop_function:如果不为空,则将该函数应用于第i个输出以得到第i+1个输入,
                此时decoder_inputs变量除了第一个元素之外其他元素会被忽略。其形式定义为:loop(prev, i)=next。
                prev是[batch_size x output_size],i是表明第i步,next是[batch_size x input_size]。
        """
        outputs, last_state = legacy_seq2seq.rnn_decoder(inputs, self.initial_state, cell, loop_function=loop if not training else None, scope='rnnlm')
        out_concat = tf.concat(outputs, 1)
        output = tf.reshape(out_concat, [-1, args.rnn_size])


        self.logits = tf.matmul(output, softmax_w) + softmax_b
        self.probs = tf.nn.softmax(self.logits)
        loss = legacy_seq2seq.sequence_loss_by_example(
                [self.logits],
                [tf.reshape(self.targets, [-1])],
                [tf.ones([args.batch_size * args.seq_length])])
        self.cost = tf.reduce_sum(loss) / args.batch_size / args.seq_length
        with tf.name_scope('cost'):
            self.cost = tf.reduce_sum(loss) / args.batch_size / args.seq_length
        self.final_state = last_state
        self.lr = tf.Variable(0.0, trainable=False)
        tvars = tf.trainable_variables()
        # 梯度截断
        grads, _ = tf.clip_by_global_norm(tf.gradients(self.cost, tvars),
                args.grad_clip)
        with tf.name_scope('optimizer'):
            optimizer = tf.train.AdamOptimizer(self.lr)
        self.train_op = optimizer.apply_gradients(zip(grads, tvars))

        # instrument tensorboard
        tf.summary.histogram('logits', self.logits)
        tf.summary.histogram('loss', loss)
        tf.summary.scalar('train_loss', self.cost)

训练过程

训练部分的代码也没有新的难懂的部分,也有很多冗余的部分,所以重点关注加了注释的部分吧:

# coding=utf-8
from __future__ import print_function
import tensorflow as tf

import argparse
import time
import os
from six.moves import cPickle

from utils import TextLoader
from model import Model


def main():
    parser = argparse.ArgumentParser(
                        formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument('--data_dir', type=str, default='data/tinyshakespeare',
                        help='data directory containing input.txt')
    parser.add_argument('--save_dir', type=str, default='save',
                        help='directory to store checkpointed models')
    parser.add_argument('--log_dir', type=str, default='logs',
                        help='directory to store tensorboard logs')
    parser.add_argument('--rnn_size', type=int, default=128,
                        help='size of RNN hidden state')
    parser.add_argument('--num_layers', type=int, default=2,
                        help='number of layers in the RNN')
    parser.add_argument('--model', type=str, default='lstm',
                        help='rnn, gru, lstm, or nas')
    parser.add_argument('--batch_size', type=int, default=50,
                        help='minibatch size')
    parser.add_argument('--seq_length', type=int, default=100,
                        help='RNN sequence length')
    parser.add_argument('--num_epochs', type=int, default=50,
                        help='number of epochs')
    parser.add_argument('--save_every', type=int, default=1000,
                        help='save frequency')
    parser.add_argument('--grad_clip', type=float, default=5.,
                        help='clip gradients at this value')
    parser.add_argument('--learning_rate', type=float, default=0.002,
                        help='learning rate')
    parser.add_argument('--decay_rate', type=float, default=0.97,
                        help='decay rate for rmsprop')
    parser.add_argument('--output_keep_prob', type=float, default=1.0,
                        help='probability of keeping weights in the hidden layer')
    parser.add_argument('--input_keep_prob', type=float, default=1.0,
                        help='probability of keeping weights in the input layer')
    parser.add_argument('--init_from', type=str, default=None,
                        help="""continue training from saved model at this path. Path must contain files saved by previous training process:
                            'config.pkl'        : configuration;
                            'chars_vocab.pkl'   : vocabulary definitions;
                            'checkpoint'        : paths to model file(s) (created by tf).
                                                  Note: this file contains absolute paths, be careful when moving files around;
                            'model.ckpt-*'      : file(s) with model definition (created by tf)
                        """)
    args = parser.parse_args()
    train(args)


def train(args):
    # 读入数据
    data_loader = TextLoader(args.data_dir, args.batch_size, args.seq_length)
    args.vocab_size = data_loader.vocab_size

    # check compatibility if training is continued from previously saved model
    if args.init_from is not None:
        # check if all necessary files exist
        assert os.path.isdir(args.init_from)," %s must be a a path" % args.init_from
        assert os.path.isfile(os.path.join(args.init_from,"config.pkl")),"config.pkl file does not exist in path %s"%args.init_from
        assert os.path.isfile(os.path.join(args.init_from,"chars_vocab.pkl")),"chars_vocab.pkl.pkl file does not exist in path %s" % args.init_from
        ckpt = tf.train.get_checkpoint_state(args.init_from)
        assert ckpt, "No checkpoint found"
        assert ckpt.model_checkpoint_path, "No model path found in checkpoint"

        # open old config and check if models are compatible
        with open(os.path.join(args.init_from, 'config.pkl'), 'rb') as f:
            saved_model_args = cPickle.load(f)
        need_be_same = ["model", "rnn_size", "num_layers", "seq_length"]
        for checkme in need_be_same:
            assert vars(saved_model_args)[checkme]==vars(args)[checkme],"Command line argument and saved model disagree on '%s' "%checkme

        # open saved vocab/dict and check if vocabs/dicts are compatible
        with open(os.path.join(args.init_from, 'chars_vocab.pkl'), 'rb') as f:
            saved_chars, saved_vocab = cPickle.load(f)
        assert saved_chars==data_loader.chars, "Data and loaded model disagree on character set!"
        assert saved_vocab==data_loader.vocab, "Data and loaded model disagree on dictionary mappings!"

    if not os.path.isdir(args.save_dir):
        os.makedirs(args.save_dir)
    with open(os.path.join(args.save_dir, 'config.pkl'), 'wb') as f:
        cPickle.dump(args, f)
    with open(os.path.join(args.save_dir, 'chars_vocab.pkl'), 'wb') as f:
        cPickle.dump((data_loader.chars, data_loader.vocab), f)

    # 构建模型
    model = Model(args)

    with tf.Session() as sess:
        # instrument for tensorboard
        summaries = tf.summary.merge_all()
        writer = tf.summary.FileWriter(
                os.path.join(args.log_dir, time.strftime("%Y-%m-%d-%H-%M-%S")))
        writer.add_graph(sess.graph)

        sess.run(tf.global_variables_initializer())
        saver = tf.train.Saver(tf.global_variables())
        # restore model
        if args.init_from is not None:
            saver.restore(sess, ckpt.model_checkpoint_path)
        # 开始训练
        for e in range(args.num_epochs):
            sess.run(tf.assign(model.lr,
                               args.learning_rate * (args.decay_rate ** e)))
            data_loader.reset_batch_pointer()
            state = sess.run(model.initial_state)
            for b in range(data_loader.num_batches):
                start = time.time()
                x, y = data_loader.next_batch()
                feed = {model.input_data: x, model.targets: y}
                for i, (c, h) in enumerate(model.initial_state):
                    feed[c] = state[i].c
                    feed[h] = state[i].h
                train_loss, state, _ = sess.run([model.cost, model.final_state, model.train_op], feed)

                # instrument for tensorboard
                summ, train_loss, state, _ = sess.run([summaries, model.cost, model.final_state, model.train_op], feed)
                writer.add_summary(summ, e * data_loader.num_batches + b)

                end = time.time()
                print("{}/{} (epoch {}), train_loss = {:.3f}, time/batch = {:.3f}"
                      .format(e * data_loader.num_batches + b,
                              args.num_epochs * data_loader.num_batches,
                              e, train_loss, end - start))
                if (e * data_loader.num_batches + b) % args.save_every == 0\
                        or (e == args.num_epochs-1 and
                            b == data_loader.num_batches-1):
                    # save for the last result
                    checkpoint_path = os.path.join(args.save_dir, 'model.ckpt')
                    saver.save(sess, checkpoint_path,
                               global_step=e * data_loader.num_batches + b)
                    print("model saved to {}".format(checkpoint_path))


if __name__ == '__main__':
    main()

训练结果

在cpu的电脑上训练还是很快的,经过五千多步的迭代,loss能降到1.4左右。github上的代码只展示了loss,因此在这里我们也只展示loss和graph。
这里写图片描述
这里写图片描述

2020-02-08 17:31:06 ZNWhahaha 阅读数 34
  • 易语言入门精品课程

    中文编程.易语言入门精品课程.讲师结合十几年的易语言学习经验.站在纯新手角度详细带你进入中文编程易语言的世界.本教程采用循序渐进原则构造.结合大量实战例子.相比于传统教程.学习本教程.更能增加编程逻辑.

    154 人正在学习 去看看 马龙

博客参考何晗所著的《自然语言处理入门》

自然语言处理

自然语言处理(Natural Language Processing, NLP) 是一门融合了计算机科学、人工智能及语言学的交叉学科。研究内容是通过机器学习等技术,让计算机学会处理人类语言,乃至实现理解人类语言或人工智能。

自然语言与编程语言的区别

词汇量

自然语言中的词汇量远远比编程语言中的关键字多。编程语言中的关键字数量是有限且确定的。而在自然语言中,以汉语为例,《现代汉语常用词表》中一共收录了56008个词条,且新词在不停创造。

结构化

自然语言是非结构化的,而编程语言是结构化的。

歧义性

自然语言中含有大量的歧义,且歧义根据语境不同而表现出特定的含义。

容错性

在编程语言中,必须要保证编程语句的绝对正确,否则会出现无法编译或者存在潜在BUG。而自然语言即使语句中存在错别字、病句等,人类还是可以猜出所要表达的意思。

易变性

编程语言与自然语言都是不断发展变化的。区别是编程语言变化发展较自然语言而言相对缓慢。

简略性

自然语言中常常出现对一个背景、常识等进行简略,如“老地方见”、“网吧对面”。这种现象对自然语言处理带来障碍。

自然语言处理结构

自然语言处理的结构如下图所示,主要有输入源(语音、图像和文本);中文分词、词性标注和命名实体识别;信息抽取;文本分类与文本聚类;句法分析等。
自然语言处理层次结构

语音、图像和文本

自然语言处理一般将文本作为处理输入源。对于语音、图像显示的输入源,通过语音识别(Speech Recognition)光学符号识别(Optical Chatacter Recognition) 转化为文本进行处理。

中文分词、词性标注、命名实体识别

三者统称为词法分析,主要任务是将文本分解为有意义的词语(中文分词),确定词语的类别及进行简单的歧义消除(词性标注),识别较长的专有名词(命名实体识别)。

信息抽取

在经过词法分析阶段后,文本已部分结构化,既为有意义的单词列表。通过单词列表从简单的高频词汇到高级算法提取关键词。

文本分类和聚类

文本分类和文本聚类是对于文本输入源在文章级别进行的分析操作。
文本分类:将许多文档进行分类整理、判断一段话的褒贬义、判断邮件是否为垃圾邮件。
文本聚类:将相似的文档归档到一起,或者排除重复的文档。在这其中不关心文档的具体类别。

句法分析

对于句子的主谓宾结构进行分析,用于问答系统、搜索引擎和基于短语的机器翻译。

语义分析与篇章分析

语言分析侧重语义而非语法。包括的内容有确定一个词在语境中的含义(词义消歧),标注句子中的谓语与其他成分的关系(语义角色标注),分析句子中词语之间的语义关系(语义依存分析)。

其他高级任务

  1. 自动问答:小米的小爱同学,苹果的Siri
  2. 自动摘要:为一篇长文档生成摘要
  3. 机器翻译: 将一句话从一种语言翻译为另外一种语言

自然语言处理的流派

自然语言处理中的流派有:基于规则的专家系统;基于统计的学习方法

  1. 基于规则的专家系统:既为规则系统,根据特点领域专家手工定制的确定性流程来运行的系统称为基于规则的专家系统。其特点是要求设计者对所处理的问题具备输入的理解,并在可能的情况下全面考虑所有的发生情况。系统难以扩展,维护成本高。
  2. 基于统计的学习方法:使用统计学的方法让计算机自动学习语言(统计学习方法是机器学习的别称)。

现如今基本将规则与统计这两种方法结合起来,以统计学为主,以规则为辅进行自然语言处理。

机器学习

学习自然语言处理,不可避免的学习机器学习领域有关的知识。

什么是机器学习

机器学习的定义是:不直接编程却能赋予计算机提高其能力的方法
既机器学习是让机器学会算法的算法。通常称机器学习算法为 “元算法”,被学习的算法为 “模型”

模型

模型是对现实问题的数学抽象,由一个假设函数以及一系列的参数构成。过程类似于数学建模。

特征

特征是指事物的特点转换的数值。
例如:在性别识别问题中,中国人的姓名的特征为:
对于中国人的人名,姓与其性别无关。则姓为无用特征,名为有用特征。对于“名”,在机器学习中赋予中国字对应的优先级(即为特征权重或参数模型)。机器学习算法根据数据自动觉得这些字的权重。这个过程称为 特征提取。在工程上不需要逐个字的去写特征,而是定义一套模板来提取特征。这种自动提取特征的模板为 特征模板
例如:名字为name的话,定义特征模板为name[1]+name[2],通过遍历一些姓名实例,即可取得其相应的特征。

数据集

让机器自动学习以得到模型参数的大量实例为习题集。其中“例子”称为 样本
习题集在机器学习领域称为 数据集 ,在自然语言处理领域称作 语料库

训练、训练集

在机器学习中对有标注的数据集上进行迭代学习的过程称为 训练 。训练所用到的数据集叫做 训练集。其中的每一遍学习都称为 一次迭代

监督学习、无监督学习与半监督学习

  1. 监督学习
    在进行机器学习时,采用的数据集是已标注过的,监督学习算法让机器先进行一遍学习,将学习所得的结果与答案对比,根据误差纠正模型的错误。监督学习的流程如下所示:
    在这里插入图片描述
  2. 无监督学习
    机器学习所采用的数据集没有经过标注,既数据集无答案。这种学习称作无监督学习。一般用于聚类和降维,因为两者都不需要数据标注。
  3. 半监督学习
    半监督方法则是将监督学习方法与无监督学习方法友好的结合起来。既训练多个模型,对同一实例进行预测,会得到多个结果。如果这些结果大多一致,则可以将该实例和结果放到一起作为新的训练样本,扩充训练集。
2011-04-18 16:10:00 wintone666 阅读数 538
  • 易语言入门精品课程

    中文编程.易语言入门精品课程.讲师结合十几年的易语言学习经验.站在纯新手角度详细带你进入中文编程易语言的世界.本教程采用循序渐进原则构造.结合大量实战例子.相比于传统教程.学习本教程.更能增加编程逻辑.

    154 人正在学习 去看看 马龙

 在工业信息化水平不断提高的时代,各单位需要处理的纸质表格数据量非常大,通过手工将这些数据录入到系统中,费时费力。效率就是企业生命,文通表格识别系统将纸质表格数据电子化,能够帮助您及时、准确得到第一手数据,提高工作效率。
刘伟一三四二六二一一三零四
  文通表格识别系统  性能特点
    一、识别字符类型丰富。系统能识别的字符包括印刷中文(简体)、印刷中文(繁体)、手写中文(简体)、手写中文(繁体)、印刷英文、印刷数字、手写英文、手写数字、条码、CheckBox等;
    二、识别速度快,一般说来,系统识别一张表格的速度在1.5秒钟左右;
    三、识别率高,对版面整洁的印刷字符的识别,正确率达99.96%,对于规范手写数字的识别,正确率在98.5%以上,对于规范手写汉字的识别,正确率在95%左右;
    四、提供功能灵活的模板制作工具(模板编辑器),通过模板编辑器,用户在很短的时间内就能够定制完成自己的识别模板;
    五、提供先进的校对工具(纵向校对器),纵向校对的引入,极大地提高了校对的速度和准确性;
    六、多种表格自动分类(基于分类码的分类、基于表格特征的分类)及定位机制(基于四框线的定位、基于十字线的定位);
    七、具有自动倾斜校正、自动判断表格是否颠倒并进行正转等功能。
    八、丰富的编程接口,用户可以根据自己的实际情况,将核心灵活地嵌入到自己的应用程序中。

  文通表格识别系统  应用范围
     政府部门:各种申请表、申报表的录入及其处理
     银行、证券部门:大量的存单、储单、支票、内部流转票据、证券买卖单据的录入及其处理
     工商、税务部门:各种纳税申报表、财务报表以及汇算清缴表的录入及其处理
     统计部门:各类社会调查表(如人口普查表、农业普查表、商业调查表)的录入及其处理
     人事部门:人事登记表、人事测评考核表的录入及其处理
     保险行业:保险单的录入及其处理
     教育、医疗部门:成绩单录入、病情统计表的录入及其处理
     制造业:进出库票据、定货单的录入及其处理
     企、事业单位:财务报表、单位内部报表、产品发布时订单的录入及其处理
     其它行业或部门表格数据录入

没有更多推荐了,返回首页