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. SourceTree 免登录

    SourceTree 是 Windows 和Mac OS X 下免费的 Git 和 Hg 客户端,拥有可视化界面,容易上手操作.同时它也是Mercurial和Subversion版本控制系统工具.支持 ...

  2. __attribute__((format(printf, a, b)))

    最近,在看libevent源码,第一次看到__attribute__((format(printf, a, b)))这种写法.因此,在这里记录下用法. 功能:__attribute__ format属 ...

  3. 【学习笔记】字符串—马拉车(Manacher)

    [学习笔记]字符串-马拉车(Manacher) 一:[前言] 马拉车用于求解连续回文子串问题,效率极高. 其核心思想与 \(kmp\) 类似:继承. --引自 \(yyx\) 学姐 二:[算法原理] ...

  4. Java实习生入职测试

    网络上一度流行的Java实习生入职测试题,可以看看. 1.String类为什么是final的. 2.JDK8的HashMap的源码,实现原理,底层结构 3.反射中,Class.forName和clas ...

  5. 'while' statement cannot complete without throwing an exception

    You are probably using Android Studio or IntelliJ. If so, you can add this above your method contain ...

  6. Jenkins的使用(一)

    Jenkins 介绍: Jenkins是一个独立的开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成 变成可能.前身是Huds ...

  7. 使用linq对ado.net查询出来dataset集合转换成对象(查询出来的数据结构为一对多)

    public async Task<IEnumerable<QuestionAllInfo>> GetAllQuestionByTypeIdAsync(int id) { st ...

  8. 洛谷P1523 旅行商简化版(DP)

    题目: P1523 旅行商简化版 解析 可以看做是两个人同时从西往东走,经过不一样的点,走到最东头的方案数 设\(f[i][j]\)表示一个人走到i,一个人走到j的最短距离(\(i<j\)) 第 ...

  9. SQL Server强制释放内存

    --强制释放内存 CREATE procedure [dbo].ClearMemory as begin --清除所有缓存 DBCC DROPCLEANBUFFERS --打开高级配置 EXEC (' ...

  10. QML官方文档:Qt Quick Controls 1和2对比

    Qt Quick Controls有1和2两个版本,在程序中会看到好多1和2版本混合使用的情况. 原文:https://doc.qt.io/qt-5/qtquickcontrols2-differen ...