nlp领域里,语义理解仍然是难题!

  给你一篇文章或者一个句子,人们在理解这些句子时,头脑中会进行上下文的搜索和知识联想。通常情况下,人在理解语义时头脑中会搜寻与之相关的知识。知识图谱的创始人人为,构成这个世界的是实体,而不是字符串,这从根本上改变了过去搜索的体系。语义理解其实是基于知识,概念和这些概念间的关系。人们在解答问题时,往往会讲述与这个问题相关的知识,这是语义理解的过程。这种机制完全不同于人对图像或者语音的认识。CNN在图像或者语音领域取得成果是不足为奇的,因为生物学家已经对人脑神经元在图像识别过程中的机制非常熟悉,但是对于人脑如何理解文字的神经元机制却知之甚少,所以导致了目前nlp语义理解方面进展非常缓慢。很多人尝试CNN引入nlp效果不佳,发现多层的CNN和单层的CNN几乎没有差别,原因得从人脑的神经元机制说起。生搬硬套是必然失败的!深度学习的本质并不是神经元层数多这么简单,能够从最基本的特征,逐层抽取出高阶特征,最后进行分类,这是深度学习取得成功的关键。

  有一部分人质疑word2vector不是深度学习,说层数太浅达不到深度的级别,这是一种误解。word2vector是地地道道的深度学习,能够抽取出词的高阶特征。他的成功,关键是基于他的核心思想:相同语境出现的词语义相近。从第一层one-hot到embedding层,就是高阶特征抽取的过程。前面说过,层数多了不一定带来效果的提升。词embedding已经是高阶特征了,文字比图像要复杂很多,目前CNN在nlp中的引入,方向可能是错误的。必须深入研究人脑对文字理解的神经元机制,弄清楚生物学模型,然后才能从中抽象出数学模型,就像CNN一样,否则nlp不会有长足的进展。目前来看,LSTM以及Attention Model是比较成功的,但是仍然基于形式化的,对于深层语义仍然没有解决。

  目前来看,深度学习算法LSTM,Attention Model等在nlp中的应用,仅限于上下文和词,句子向量。计算一下句子相似度,聚类之类的,要想真正让机器理解文字,还达不到。也就是说只在语义表示层做文章是远远不够的,底层的知识图谱是关键。Google提出的知识图谱是一种变革,nlp是一个完整的生态圈,从最底层的存储,GDB三元组(entry,relation,entry),到上层的语义表示(这个阶段可以借助深度学习直接在语义层进行训练),比如(head,relation,tail)三元组表示的图结构,表达了实体与实体间的关系,可以用深度学习训练出一个模型:h + r = t,获取语义表示。这样在预测时,得到了两个实体的语义表示,进行减法运算就可以知道两者的关系。这个不同于word2vector,但是还是有共性的。word2vector的CBOW就是训练x1 + x2 + …… = y这个模型。目前知网也在做这些事情。

  语义表示是深度学习在nlp应用中的重中之重。之前在词embedding上word2vector获取了巨大成功,现在主要方向是由词embedding迁移到句子或者文章embedding。获取句子的embedding,之前的博客,siamese lstm已经有论述了,在2014~2015年间,国外的学者探索了各种方法,比如tree-lstm,convnet,skip-thougt,基于ma机构的siamese lstm来计算句子或者文章的相似度。目前从数据来看,基于ma结构的siamese lstm效果最好,最适应nlp的规律。在github上已经有了siamese lstm的实验,进一步改进可是基于BiLSTM,至于增加层数是否能够带来准确率的提升,有待于进一步论证,个人持中立态度。本文主要探讨word2vector。关于他的核心思想前面已经提到了,这是道的层面,具体推导,比如CBOW ,skip-gram的优化:negative sampleing和哈夫曼树softmax,这是术的层面。现在上传用tensorflow实现的word2vector代码:

data-helper.py:

import collections
import os
import random
import zipfile
import numpy as np
import urllib.request as request
import tensorflow as tf url = 'http://mattmahoney.net/dc/' def maybe_download(filename,expected_bytes):
if not os.path.exists(filename):
filename,_ = request.urlretrieve(url+filename,filename)
statinfo = os.stat(filename)
if statinfo.st_size == expected_bytes:
print('Found and verified',filename)
else:
print(statinfo.st_size)
raise Exception('Failed to verify' + filename + '.Can you get to it with a browser?')
return filename def read_data(filename):
with zipfile.ZipFile(filename) as f:
data = tf.compat.as_str(f.read(f.namelist()[0])).split()
return data vocabulary_size = 50000
def build_dataset(words):
count = [['UNK',-1]]
count.extend(collections.Counter(words).most_common(vocabulary_size - 1))
dictionary = dict(zip(list(zip(*count))[0],range(len(list(zip(*count))[0]))))
data = list()
un_count = 0 for word in words:
if word in dictionary:
index = dictionary[word]
else:
index = 0
un_count += 1
data.append(index)
count[0][1] = un_count
reverse_dictionary = dict(zip(dictionary.values(),dictionary.keys()))
return data,reverse_dictionary,dictionary,count data_index = 0
def generate_batch(data,batch_size,num_skips,skip_window):
filename = maybe_download('text8.zip', 31344016)
words = read_data(filename)
global data_index
assert num_skips <= 2 * skip_window
assert batch_size % num_skips == 0
span = 2 * skip_window + 1
batch = np.ndarray(shape=[batch_size],dtype=np.int32)
labels = np.ndarray(shape=[batch_size,1],dtype=np.int32)
buffer = collections.deque(maxlen=span)
#初始化
for i in range(span):
buffer.append(data[data_index])
data_index = (data_index + 1) % len(data)
#移动窗口,获取批量数据
for i in range(batch_size // num_skips):
target = skip_window
avoid_target = [skip_window]
for j in range(num_skips):
while target in avoid_target:
target = np.random.randint(0,span)
avoid_target.append(target)
batch[i * num_skips + j] = buffer[skip_window]
labels[i * num_skips + j,0] = buffer[target] buffer.append(data[data_index])
data_index = (data_index + 1) % len(data)
return batch,labels

w2vModel.py

import tensorflow as tf
import w2v.data_helper as da
import numpy as np
import math
#filename = da.maybe_download('text8.zip', 31344016)
words = da.read_data("text8.zip")
assert words is not None
data,reverse_dictionary,dictionary,count = da.build_dataset(words) class config(object):
batch_size = 128
embedding_size = 128
skip_window = 1
num_skips = 2 valid_size = 16
valid_window = 100
valid_examples = np.random.choice(valid_window, valid_size, replace=False)
num_sampled = 64
vocabulary_size = 50000
num_steps = 10001 class w2vModel(object):
def __init__(self,config):
self.train_inputs = train_inputs = tf.placeholder(tf.int32, shape=[config.batch_size])
self.train_labels = train_labels = tf.placeholder(tf.int32, shape=[config.batch_size, 1])
self.valid_dataset = valid_dataset = tf.constant(config.valid_examples, dtype=tf.int32) with tf.device('/cpu:0'):
embeddings = tf.Variable(
tf.random_uniform(shape=[config.vocabulary_size, config.embedding_size], minval=-1.0, maxval=1.0))
embed = tf.nn.embedding_lookup(embeddings, train_inputs)
nce_weights = tf.Variable(
tf.truncated_normal([config.vocabulary_size, config.embedding_size], stddev=1.0 / math.sqrt(config.embedding_size)))
nce_bias = tf.Variable(tf.zeros([config.vocabulary_size])) loss = tf.reduce_mean(
tf.nn.nce_loss(weights=nce_weights, biases=nce_bias, labels=train_labels, inputs=embed,
num_sampled=config.num_sampled, num_classes=config.vocabulary_size))
optimizer = tf.train.GradientDescentOptimizer(1.0).minimize(loss)
norm = tf.sqrt(tf.reduce_sum(tf.square(embeddings), 1, keep_dims=True))
normalized_embeddings = embeddings / norm
valid_embeddings = tf.nn.embedding_lookup(normalized_embeddings, valid_dataset)
similarity = tf.matmul(valid_embeddings, normalized_embeddings, transpose_b=True)
tf.add_to_collection("embedding",embeddings)
self.saver = saver = tf.train.Saver(tf.global_variables())

train.py:

import tensorflow as tf
import w2v.w2vmodel as model
import w2v.data_helper as da config = model.config() with tf.Graph().as_default() as g:
Model = model.w2vModel(config)
with tf.Session(graph=g) as session:
tf.global_variables_initializer().run()
print("initialized") average_loss = 0.0
for step in range(config.num_steps):
batch_inputs,batch_labels = da.generate_batch(model.data,config.batch_size,config.num_skips,config.skip_window)
feed_dict = {Model.train_inputs:batch_inputs,Model.train_labels:batch_labels} _,loss_val = session.run([Model.optimizer,Model.loss],feed_dict=feed_dict)
average_loss += loss_val
if step % 2000 == 0:
if step > 0:
average_loss /= 2000
print("Average loss at step",step,":",average_loss)
average_loss = 0
if step % 10000 == 0:
sim = Model.similarity.eval()
for i in range(config.valid_size):
valid_word = model.reverse_dictionary[config.valid_examples[i]]
top_k = 8
nearest = (-sim[i,:]).argsort()[1:top_k+1]
log_str = "Nearest to %s:" % valid_word
for k in range(top_k):
close_word = model.reverse_dictionary[nearest[k]]
log_str = "%s %s," % (log_str,close_word)
print(log_str)
Model.saver.save(session, "E:/word2vector/models/model.ckpt")
#final_embeddings = model.normalized_embeddings.eval()

   代码实现比较简单,先对样本统计,然后降序排列,在得到dictionary{词:索引},接下把样本中的词转换成索引,进行训练。词向量就是神经元参数embedding,在预测时,只需要拿出embedding和dictionary,就可以得到词向量,比biLSTM和siamese lstm简单多了!但是,他在语义理解上有致命的缺点:对于词典中没出现的词的语义表示用0代替,明显是不妥当的,能力有限!所以现在国内有少数的学者研究把神经概率语义表示和符号语义表示结合起来,难度不小!

  期待nlp语义理解出现变革……

nlp语义理解的一点儿看法的更多相关文章

  1. 提速1000倍,预测延迟少于1ms,百度飞桨发布基于ERNIE的语义理解开发套件

    提速1000倍,预测延迟少于1ms,百度飞桨发布基于ERNIE的语义理解开发套件 11月5日,在『WAVE Summit+』2019 深度学习开发者秋季峰会上,百度对外发布基于 ERNIE 的语义理解 ...

  2. 【转载】BERT:用于语义理解的深度双向预训练转换器(Transformer)

    BERT:用于语义理解的深度双向预训练转换器(Transformer)   鉴于最近BERT在人工智能领域特别火,但相关中文资料却很少,因此将BERT论文理论部分(1-3节)翻译成中文以方便大家后续研 ...

  3. 【一】ERNIE:飞桨开源开发套件,入门学习,看看行业顶尖持续学习语义理解框架,如何取得世界多个实战的SOTA效果?

    ​ 参考文章: 深度剖析知识增强语义表示模型--ERNIE_财神Childe的博客-CSDN博客_ernie模型 ERNIE_ERNIE开源开发套件_飞桨 https://github.com/Pad ...

  4. C#开发微信门户及应用(31)--微信语义理解接口的实现和处理

    微信语义理解接口提供从用户自然语言输入到结构化解析的技术实现,使用先进的自然语言处理技术给开发者提供一站式的语义解析方案.该平台覆盖多个垂直领域的语义场景,部分领域还可以支持取得最终的展示结果.开发者 ...

  5. 百度Android语音识别SDK语义理解与解析方法

    百度语义理解开放平台面向互联网开发人员提供自然语言文本的解析服务,也就是能够依据文本的意图解析成对应的表示. 为了易于人阅读,同一时候也方便机器解析和生成,意图表示协议採用 json 语言进行描写叙述 ...

  6. 微信小程序——智能小秘“遥知之”源码分享(语义理解基于olami)

    微信小程序智能生活小秘书开发详解 >>>>>>>>>>>>>>>>>>>>> ...

  7. Semantic Parsing(语义分析) Knowledge base(知识图谱) 对用户的问题进行语义理解 信息检索方法

    简单说一下所谓Knowledge base(知识图谱)有两条路走,一条是对用户的问题进行语义理解,一般用Semantic Parsing(语义分析),语义分析有很多种,比如有用CCG.DCS,也有用机 ...

  8. NLP 语义相似度计算 整理总结

    更新中 最近更新时间: 2019-12-02 16:11:11 写在前面: 本人是喜欢这个方向的学生一枚,写文的目的意在记录自己所学,梳理自己的思路,同时share给在这个方向上一起努力的同学.写得不 ...

  9. TSQL Merge On子句和When not matched 语义理解

    Merge 的On子句指定Match condition,When子句指定过滤条件,如果Source Table和Targe Table匹配的上,很好理解:如果匹配不上,必须深入理解不匹配的条件,否则 ...

随机推荐

  1. PHP服务端优化全面总结

    一.优化PHP原则 1.1PHP代码的优化 (1)升级最新的PHP版本 鸟哥PPT里的对比数据,就是WordPress在PHP5.6执行100次会产生70亿次的CPU指令执行数目,而在PHP7中只需要 ...

  2. swagger2 导出离线Word/PDF/HTML文档

    swagger2离线导出Word/PDF/HTML文档 1.前言 通过前面的两篇博客 我们已经介绍了如何使用spring boot整合swagger2 生成在线的API文档. 但是某些情况下,我们需要 ...

  3. java 解决safari下载中文文件名乱码

    主要就是在响应头设置content-disposition,主要遵循 RFC 5987标准. response.setHeader("content-disposition",&q ...

  4. 《 .NET并发编程实战》阅读指南 - 第11章

    先发表生成URL以印在书里面.等书籍正式出版销售后会公开内容.

  5. java -- Set 用法及特点

    分类专栏: java学习   版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/firearr ...

  6. C# 操作LDAP

    C# 操作LDAP查找组或人员信息 using System; using System.Collections.Generic; using System.Linq; using System.We ...

  7. 私钥、公钥与https

    HTTP的安全缺陷 通信内容不加密,导致被窃听 不验证客户端和服务端的身份,导致: 服务器伪装 响应返回到了其他的客户端 海量恶意连接 无法证明报文的完整性,导致:请求和响应内容被篡改,这称为中间人攻 ...

  8. 【转载】ArrayList使用LastIndexOf方法查找最后一个符合条件的元素位置

    在C#的编程开发中,ArrayList集合是一个常用的非泛型类集合,在ArrayList集合中如果需要查找最后一个符合条件的元素所在的位置,可以使用ArrayList集合的LastIndexOf方法, ...

  9. Extjs 树菜单的自动展开数据的请求

    今天在做extjs开发的时候,在树菜单上遇到了一个坑,也许是我刚接触extjs 不熟的缘故 问题描述:后台设置的树自动展开,但是在前端总是只显示一条数据,但是数据确实都请求到了. 经过几个小时不屑的努 ...

  10. Object.freeze

    Object.freeze() 方法可以冻结一个对象.一个被冻结的对象再也不能被修改:冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性.可配置性.可写性, ...